Tải bản đầy đủ (.docx) (26 trang)

CHUYÊN đề NGĂN xếp (STACK) và HÀNG đợi (QUEUE)

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 (213.94 KB, 26 trang )

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

CHUYÊN ĐỀ NGĂN XẾP (STACK) VÀ HÀNG ĐỢI (QUEUE)

1


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 tố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 và hàng đợi đã có rất nhiều tài liệu đề cập đến, trong
chuyên đề này chúng 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

2


B. NỘI DUNG
I, DỮ LIỆU KIỂU NGĂN XẾP (STACK)
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à đỉ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 lấy đạn ra cũng chỉ ở đầu
hộp. Viên
 Top
đạ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.
 Bottom
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 dùng mảng Stack[I. Nmax] mà ″đáy″ của Stack là ở đầu tức chỉ số là 1. Việc đưa vào
(Push) hay lấy ra (Pop) được thực hiện phần đuôi của mảng nhờ một con trỏ P. Các thao
tác đưa vào hay lấy ra đó ứng với các thủ tục hàm thích hợp. Giả sử Stack chứa các phần
tử là các số ngun thì ta sẽ có các thủ tục và hàm sau:
3, Các phép xử lý trên stack
a. Khởi tạo stack rỗng: P := 0;
b. Kiểm tra một stack có rỗng hay khơng:
Function StackEmpty:Boolean; {Kiểm tra stack có rỗng khơng}
Begin
StackEmpty:=P=0;
End;
c. Thủ tục lấy một phần tử ở đỉnh stack
Function Pop: Integer; {Lấy 1 phần tử ra khởi stack}
Begin
Pop:=Stack[P];
Dec(P);
End;
d. Thủ tục đẩy một phần tử vào stack:
Procedure Push (N:Integer); {Đưa số N vào Stack}

Begin
Inc (P);
Stack[P]:=N;
End;
4, Ứng dụng của ngăn xếp:

3


a, Khử đệ quy thuật toán sắp xếp Quicksort;
Const
Nmax=5000;
Var
n, i, j, x, l, r, tg:Integer;
s: 0.. Nmax;
A: Array[1..Nmax] of Integer;
Stack: Array [1..Nmax] of Record l,
r : Integer;
End;
Procedure Sort;
Begin
S:=1; Stack [s].l:=1;
Stack [s].r:=n ;
Repeat
l:=Stack[s].1; r:=Stack[s].r;
Dec(s);
Repeat
i:=1; j:=r;
x:=A[(1+r)div 2]
Repeat

While a[i] < x
Do Inc(i);
While a [j] > x
Do Dec (j);
if i < = j then
Begin
Tg:=a[i]; a[i]:=a[j];
a[j]:=tg; Inc(i); Dec (j);
End;
Until i >j;
If i < r then
Begin
S: = s +1 ;
Stack [s].l: = 1;
Stack [s].r:= r ;
End; r : = j;
Until 1> r ;
Until S= 0;End;
b, 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
4


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 toá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 toán tử tiếp theo *. Bởi vì
* được ưu tiên hơn +, tốn hạng 2 là toán hạng bên trái của toá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
+
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 tố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 tố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 toá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 toán tử.

2. While <không xảy ra lỗi và chưa đạt đến kết thúc của biểu thức trung 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.
5


-

Toá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 toán
tử).
- Toá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 tốn hạng, tố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ố.
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;
6


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
begin
while infix[i] = ' ' do i := i + 1; { nhay qua cac dau cach }
x := infix[i];
if x = EndMask then break;
case x of
'(' : Push(x);
')' : begin
donePop := false;
repeat
if top = 0 then error := true
else begin
symbol := Pop;
if symbol = '(' then donePop := true
else rpn := rpn + symbol;
end;
until donePop or Error;
end;
'+', '-', '*', '/':
begin
donePop := false;
while (top <> 0) and (not donePop) do
begin
symbol := Pop;

if Priority(x) <= Priority(symbol) then rpn:=rpn+symbol
else begin
Push(symbol);
donePop := true;
end;
end;
Push(x);
7


end;
else rpn := rpn + x; { x la toan hang}
end; { of case }
i := i + 1;
end; { of while }
while (top <> 0) and (not error) do
begin
symbol := Pop;
if symbol = '(' then error := true
else rpn := rpn + symbol;
end;
if error then writeln('<Co loi trong bieu thuc trung to>')
else writeln(rpn);
End;
Procedure Read_data;
Begin
write('Vao bieu thuc dang trung to: '); readln(infix);
infix := infix + EndMask;
End;
Begin

clrscr;
Read_data;
Convert_to_rpn;
readln;
End.
II, DỮ LIỆU KIỂU HÀNG ĐỢI (QUEUE)
1. Khái niệm hàng đợi (Queue)
Khác với stack, queue là một danh sách tuyến tính mà phép bổ sung thực hiện ở một đầu,
gọi là lối sau (rear) và phép loại bỏ thực hiện ở một đầu khác, gọi là lối trước (front).
Như vậy cơ cấu của queue giống như một hàng đợi (như là một hàng người chờ tính tiền
ở siêu thị, một dãy các máy bay chờ hạ cánh ở một sân bay, ...) vào ở một đầu, ra ở đầu
khác, nghĩa là vào trước thì ra trước. Vì vậy queue được gọi là danh sách kiểu FIFO (First
- In - First - Out).
Quầy bán vé

8











9



10


11


12


13






14


15


16










17


18


19


20


21


22


23


24


25



×