Tải bản đầy đủ (.doc) (54 trang)

CHUYÊN đề NGĂN xếp (STACK) môn tin học

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (191.3 KB, 54 trang )

TRƯỜNG THPT CHUYÊN TỈNH LÀO CAI
TỔ TOÁN - TIN
-----------------*@*---------------------

CHUYÊN ĐỀ NGĂN XẾP
(STACK) môn Tin HỌC

NĂM HỌC:
1 2014 - 2015


A, MỞ ĐẦU
1. Lý do chọn đề tài
Ngăn xếp và hàng đợi là hai kiểu dữ liệu trừu tượng rất quan trọng và
được sử dụng nhiều trong thiết kế thuật toán. Về bản chất, ngăn xếp và
hàng đợi là danh sách tức là một tập hợp các phần tử cùng kiểu có tính
thứ tự. Ngăn xếp được sử dụng rất nhiều trong việc giải quyết các bài
toán về đồ thị trong các đề thi học sinh giỏi. Tuy nhiên trong q trình
giảng dạy tơi thấy học sinh vẫn cịn khó khăn trong việc phân tích bài
tốn để có thể áp dụng được thuật toán và cài đặt giải bài toán. Vì vậy tơi
chọn chun đề này để giúp học sinh có cái nhìn tổng quan hơn về ngăn
xếp và ứng dụng của ngăn xếp trong giải các bài toán cụ thể.
2. Mục đích của đề tài
Về nội dung kiến thức ngăn xếp đã có rất nhiều tài liệu đề cập đến, trong
chuyên đề này tôi chỉ tổng hợp lại các nội dung kiến thức đã có và chủ
yếu là đưa vào áp dụng để giải một số bài toán cụ thế, để làm tài liệu
tham khảo cho học sinh và giáo viên trong quá trình học tập và giảng
dạy các đội tuyển học sinh giỏi
B. NỘI DUNG
1, Khái niệm:
Stack là một kiểu danh sách tuyến tính đặc biệt mà


phép bổ sung và loại bỏ luôn thực hiện ở một đầu gọi là
← Top
đỉnh (Top). Có thể hình dung nó như cơ cấu của một hộp
chứa đạn súng trường hoặc súng tiểu liên. Khi lắp đạn hay
← Bottom
lấy đạn ra cũng chỉ ở đầu hộp. Viên đạn vừa lắp vào sẽ ở
trên đỉnh hộp và viên đạn lắp vào đầu tiên sẽ ở đáy hộp
(Bottom). Viên đạn nạp vào sau cùng lại là viên đạn bắn đầu tiên.
Với nguyên tắc hoạt động của stack “vào sau ra trước” nên nó cịn được gọi
với tên danh sách kiểu LIFO (Last - In - First - Out).
2, Cài đặt stack
Ta cài đặt ngăn xếp như một mảng chứa các phần tử của ngăn xếp và
một biến top để lưu trữ vị trí của phần tử đỉnh trong ngăn xếp.
Const
MaxSize = 100;
{ độ dài cực đại của stack }
Type
ElementType = integer;
{ kiểu các phần tử của stack }
StackType = array[1..MaxSize] of ElementType;
Var

2


top : integer;
stack : StackType;

3, Các phép xử lý trên stack
a. Khởi tạo stack rỗng: top := 0;

b. Kiểm tra một stack có rỗng hay khơng:
if top = 0 then < stack rỗng >
else < stack không rỗng >;
c. Thủ tục lấy một phần tử ở đỉnh stack
Function Pop : ElementType; { Trả lại phần tử ở trên đỉnh
stack }
Begin
if top = 0 then writeln('STACK can!')
else begin
Pop := stack[top];
top := top - 1;
end;
End;
d. Thủ tục đẩy một phần tử vào stack:
Procedure Push(x : ElementType); { Đẩy phần tử x vào ngăn
xếp }
Begin
if top = MaxSize then writeln('STACK tran!')
else begin
top := top + 1;
stack[top] := x;
end;
End;

4, Ứng dụng của ngăn xếp: ký pháp nghịch đảo Ba Lan (RPN- Reverse
Polish Notation)
Nhiệm vụ của bộ dịch (compiler) là tạo ra các chỉ thị máy cần thiết để
thực hiện các lệnh của chương trình gốc viết trong một ngơn ngữ lập trình
cấp cao. Một phần của nhiệm vụ này là tạo ra các chỉ thị máy để đánh giá
biểu thức số học. Chẳng hạn như trong lệnh gán x := a∗ b + c; bộ dịch phải

tạo ra các chỉ thị máy tương tự như sau:
Loa a
; nạp giá trị của ô nhớ a vào thanh ghi dự trữ
Mul b
; nhân giá trị của ô nhớ b với giá trị trong thanh ghi dự trữ
Add c
; cộng thêm giá trị của thanh ghi dự trữ với giá trị trong ô nhớ c
3


Sto x

; lưu trữ giá trị trong thanh ghi dự trữ vào ô nhớ x
Trong đa số các ngôn ngữ lập trình, các biểu thức số học được viết
như dạng thơng thường của tốn học, nghĩa là theo kí pháp trung tố (Infix
notation): mỗi tốn tử 2 ngơi được đặt giữa 2 tốn hạng và có thể thêm dấu
ngoặc. Nhiều bộ dịch trước hết chuyển các biểu thức trung tố này sang kí
pháp hậu tố (Postfix notation) hay tiền tố (Prefix notation). ở dạng hậu tố các
toán tử đi sau tốn hạng và ở dạng tiền tố thì các tốn tử đi trước tốn hạng.
Ví dụ:
Infix
2∗(3+4)
Postfix 2 3 4 + ∗
Prefix
∗2+34
Những năm đầu 1950, nhà lơgíc học Ba Lan: Jan Lukasiewicz đã phát
hiện rằng các dấu ngoặc là không cần thiết trong kí pháp hậu tố cũng như
tiền tố. Sau đây ta chỉ xét đối với kí pháp hậu tố, cịn gọi là kí pháp nghịch
đảo Ba Lan RPN - Reverse Polish Notation (ta có thể suy ra hồn tồn tương
tự với kí pháp tiền tố).

5, Chuyển biểu thức từ dạng trung tố sang dạng hậu tố
Để minh hoạ ta xét biểu thức trung tố sau đây: 7 + 2 * 3. Khi đọc biểu
thức này từ trái sang phải, giá trị 7 được hiển thị ngay lập tức. Tiếp theo là
tốn tử +, nhưng nó được lưu trữ vì tốn hạng bên phải của nó chưa được
hiển thị, vì vậy nó được đẩy vào ngăn xếp các tốn tử:
Đầu ra
Ngăn xếp
7

+

Tiếp theo là toán hạng 2 được đọc và được hiển thị. Lúc này nó phải
được xác định là toán hạng bên phải của toán tử + hay là toán hạng bên trái
của toán tử tiếp theo. Để xác định điều này ta so sánh toán tử + ở đỉnh ngăn
xếp với tốn tử tiếp theo *. Bởi vì * được ưu tiên hơn +, toán hạng 2 là tốn
hạng bên trái của tốn tử *. Vì vậy ta đẩy * vào ngăn xếp và tìm tốn hạng
bên phải của nó:
Đầu ra

Ngăn xếp

72

*
+
4


Tốn hạng 3 được đọc và hiển thị. Bởi vì lúc này ta đạt đến kết thúc
biểu thức, toán hạng bên phải của toán tử * ở đỉnh ngăn xếp được tìm ra,

tốn tử * có thể lấy ra từ ngăn xếp và hiển thị:
Đầu ra
Ngăn xếp
723*

+

Dấu kết thúc biểu thức cũng chỉ ra rằng toán hạng bên phải của tốn
tử cịn lại + trong ngăn xếp được tìm ra, vì vậy nó được lấy ra và hiển thị, ta
được biểu thức RPN: 7 2 3 * +
Các dấu ngoặc trong biểu thức trung tố khơng gây khó khăn thực sự
nào cả. Dấu ngoặc bên trái chỉ ra bắt đầu một biểu thức con và khi đọc nó
được đẩy vào ngăn xếp. Đến khi gặp dấu ngoặc phải, các toán tử được lấy ra
từ ngăn xếp cho đến khi dấu ngoặc trái tương ứng xuất hiện ở đỉnh. Lúc này,
biểu thức con ban đầu trong các dấu ngoặc đã được chuyển sang dạng RPN,
vì vậy có thể bỏ qua chúng, vì vậy phép chuyển đổi tiếp tục.
Thuật tốn chuyển từ dạng trung tố sang dạng RPN:
1. Khởi động một ngăn xếp rỗng các tốn tử.
2. While tố> do
a. Đọc phần tử x (hằng số, biến số, toán tử số học, các dấu ngoặc trái và
ngoặc phải) tiếp theo trong biểu thức trung tố.
b. Nếu phần tử x là:
- Dấu ngoặc trái: đẩy nó vào ngăn xếp.
- Dấu ngoặc phải: lấy ra và hiển thị các phần tử của ngăn xếp cho
đến khi dấu ngoặc trái được đọc. Nếu ngăn xếp rỗng thì xảy ra lỗi.
- Tốn tử: nếu ngăn xếp rỗng hay x được ưu tiên hơn phần tử ở đỉnh
ngăn xếp, đẩy x vào ngăn xếp.
Nếu khác, lấy ra và hiển thị phần tử ở đỉnh ngăn xếp; Lặp lại việc
so sánh x với phần tử ở đỉnh ngăn xếp. (Dấu ngoặc trái được xem

ưu tiên thấp hơn các tốn tử).
- Tốn hạng: hiển thị nó.
3. Khi đạt đến kết thúc của biểu thức trung tố, lấy ra và hiển thị các phần tử
của ngăn xếp cho đến khi ngăn xếp rỗng.
Cài đặt: chương trình này giả sử các toán hạng, toán tử chỉ gồm 1 kí tự và
giả sử biểu thức trung tố là hợp lệ và chỉ kiểm tra rất ít tính đúng đắn của
biểu thức trung tố.
5


Program Infix_to_rpn;
Uses crt;
Const
MaxSize = 100;
EndMask = ';';
{ dau ket thuc bieu thuc trung
to }
Var
infix, rpn : string;
top : integer;
stack : array[1..MaxSize] of char;
Function Pop : char;
Begin
Pop := stack[top];
top := top - 1;
End;
Procedure Push(x : char);
Begin
top := top + 1;
stack[top] := x;

End;
Function Priority(operator : char) : integer;
{ ham tra lai do uu tien cua cac toan tu }
Begin
case operator of
'('
: Priority:=0;
'+', '-' : Priority := 1;
'*', '/' : Priority := 2;
end;
End;
Procedure Convert_to_rpn;
Var
i : integer;
x, symbol : char;
error, donePop : boolean;
Begin
write('Bieu thuc dang RPN la: ');
rpn := '';
top := 0;
error := false;
i := 1;
x := infix[1];
while (x <> EndMask) and not error do

6



−−∗








−−∗
−−∗
−−∗
−∗
−∗

























∈{

}


















×