DANH SÁCH LIấN KẾT 4.1 Giới thiệu
4.5 Ngăn xếp (Stack) và hàng đợi (Queue) 1 Ngăn xếp
4.5.1 Ngăn xếp
Stack là một danh sỏch mà hai phộp thờm và loại bỏ đều được thực hiện trờn một đầu hay cũn gọi là đỉnh (Top ) của Stack. Như vậy, phần tử nào thờm vào sau sẽ bị loại bỏ trước, nờn Stack cũn được gọi là danh sỏch LIFO (Last In First Our list) hoặc Pushdown list. Cú thể hỡnh dung ngăn xếp như một chương trỡnh Pascal mà chương trỡnh A gọi chương trỡnh B, chương trỡnh B gọi chương trỡnh C. Khi chương trỡnh C được thực hiện xong thỡ sự điều khiển chương trỡnh sẽ trở về thực hiện chương trỡnh B, rồi khi chương trỡnh B được thực hiện xong thỡ sự điều khiển chương trỡnh sẽ trở về thực hiện chương trỡnh A. Như vậy chương trỡnh B được gọi sau sẽ được trở về thực hiện trước chương trỡnh A. Đú là nhờ điểm nhập (entry point) trở về của cỏc chương trỡnh được chứa trong Stack.
Mụ tả Stack và cỏc thao tỏc cơ bản trờn Stack
a) Với Stack được mụ tả bằng mảng:
o Việc thờm một phần tử vào Stack tương đương với việc thờm một phần tử vào cuối mảng.
o Việc bớt một phần tử của Stack tương đương với việc loại bỏ một phần tử ở cuối mảng.
o Stack bị tràn khi bổ xung phần tử vào mảng đó đầy o Stack rỗng khi số phần tử thực sự trong mảng bằng 0.
Program StackByArray;
Const max = 10000;
Var
Stack : Array[1..max] of Integer; Last : Integer;
Procedure StackInit; {khoi tao danh sach rong}
Begin
Last := 0;
End;
Procedure Push(v:integer);{dua gia tri v vao Stack}
Begin
If Last = max then
Write('Stack da day !') Else Begin Inc(last); Stack(last) := V; End; End; Function Pop:integer; Begin If last = 0 then Write('Stack rong !') Else Begin Pop := Stack(last); Dec(last); End; End; <...>
Khi cài đặt Stack bằng mảng tuy cỏc thao tỏc hết sức đơn giản nhưng ta vẫn chia thành cỏc chương trỡnh con, mỗi chương trỡnh con mụ tả một thao tỏc, để từ đú về sau ta chỉ cần biết rằng chương trỡnh của ta cú cấu trỳc Stack, và khi cài đặt Stack bằng cỏc cấu trỳc dữ liệu khỏc chỉ cần sửa lại thủ tục StackInit, Push, Pop mà thụi.
b) Với Stack được mụ tả bằng danh sỏch nối đơn.
Khi cài đặt Stack bằng danh sỏch nối đơn kiểu LIFO thỡ Stack bị tràn vựng khụng gian nhớ dựng cho cỏc biến động khụng cũn đủ để thờm một
phần tử mới, điều này phụ thuộc vào mỗi mỏy tớnh và ngụn ngữ lập trỡnh. Vớ dụ với Pascal khi vựng Heap cũn trống 80 byte thỡ cũng chỉ đủ chỗ cho 10 biến, mỗi biến 6 byte, mặt khỏc khụng gian bộ nhớ dành cho cỏc biến động thường rất lớn nờn việc cài đặt ở đõy ta bỏ qua việc kiểm tra việc Stack tràn. Việc cài đặt ngăn xếp bởi danh sỏch liờn kết giống như chỳng ta làm đối với danh sỏch. Đỉnh của ngăn xếp là đầu của danh sỏch liờn kết.
Program StackByLinkedList;
Type
PNode = ^ TNode; { Con tro tro toi mot nut cua danh sach } TNode = record { Cau truc mot nut cua danh sach }
Value : integer; Link : PNode;
End;
Var
Last : PNode;
Procedure StackInit; { Khoi tao Stack rong }
Begin
Last := NIL;
End;
Procedure Push( v : Integer ); { Day gia tri V vao Stack }
Var
P : PNode;
Begin
New(P); P^.Value := V;
{ Tao ra mot nut moi }
P^.Link := Last; Last := P;
{ Moc noi nut do vao danh sach}
End;
Function Pop: Integer;
{ Lay ra mot phan tu ra khoi Stack }
Var
Begin
If Last = NIL then Write(' Stack is Empty ! ')
Else
Begin
Pop := Last^.Value;
{ gan ket qua ham }
P := Last^.Link;
{ Giu lai nut duoc day vao danh sach truoc nut Last^ }
Dispose(Last); Last := P;
{Giai phong bo nho cap cho Last^, cap nhat lai Last moi}
End; End;