You are on page 1of 13

u trúc d li u và gi i thu t

Ch ng 6. Ng n x p và hàng i

6.1. Ng n x p (Stack)
6.1.1. nh ngh a
Ng n x p (stack) là m t t p h p các ph n t (items) cùng ki u c t ch c m t
cách tu n t , trong ó ph n t c thêm vào cu i cùng c a t p h p s là ph n t b lo i
b u tiên kh i t p h p. Các ng n x p th ng c g i là các c u trúc LIFO (Last In
First Out).
i v i m t ng n x p ch có 2 thao tác c b n, thao tác th nh t th c hi n thêm
m t ph n t vào stack g i là push, thao tác th hai là c giá tr c a m t ph n t và lo i
b nó kh i stack g i là pop.
Ngoài hai thao tác c b n trên chúng ta c n có m t s thao tác ph tr khác: ch ng
h n làm th nào bi t là m t stack không có ph n t nào - t c là r ng hay là y t c là
không th thêm vào b t c m t ph n t nào khác n a. th c hi n u này ng i ta
th ng thêm hai thao tác ti n hành ki m tra là empty và full.
m b o không x y ra tình tr ng g i là stack overflow (tràn stack – không th
thêm vào stack b t c ph n t nào) chúng ta có th cho hàm push tr v ch ng h n 1
trong tr ng h p th c hi n thành công và 0 n u không thành công.
6.1.2. u tr Stack b ng m ng
v Khai báo:
# define MAX_ELE 100
struct stack {
int n; // s ph n t c a ng n x p
DATA nodes[MAX_ELE]; // ng n x p là m ng 1 chi u
};
typedef struct stack STACK;
v Các phép toán c b n:
1. Kh i t o ng n x p
void init(STACK &stack) {
stack.n=0;
}
2. Phép toán empty: ki m tra xem ng n x p có r ng hay không ?
int empty(STACK stack) {
return (stack.n==0 ? TRUE : FALSE);
}
3. Phép toán full: ki m tra xem ng n x p ã y ch a ?
int full(STACK stack)

Ch ng 5. Ng n x p và hàng i Trang 62
u trúc d li u và gi i thu t
{
return (stack.n== MAX_ELE ? TRUE : FALSE);
}
4. Phép thêm vào: Thêm m t ph n t có n i dung là info vào ng n x p.
L u ý: Khi thêm m t ph n t vào ng n x p, ta ph i ki m tra xem ng n x p ã y
hay ch a ?
void push(STACK &stack, DATA info) {
if (full(stack))
printf("Ngan xep bi day.");
else
stack.nodes[++stack.n] = info;
}
5. Phép lo i b : Trích thông tin và lo i b ph n t nh ng n x p.
DATA pop (STACK &stack) {
DATA x = DATANULL;
if(empty(stack))
printf("Danh sach khong co phan tu.");
else
x = stack.nodes[stack.n--];
return x;
}
6. Xem thông tin nh ng n x p:.
DATA top (STACK stack) {
DATA x = NULLDATA;
if(empty(stack))
printf("Danh sach khong co phan tu.");
else
x = stack.nodes[stack.n];
return x;
}
7. Duy t ng n x p: duy t t nh cho n áy ng n x p, m i ph n t c duy t
qua 1 l n.
void ProcessStack(STACK stack){
DATA x;
for (int item=stack.n; item>0; item--) {
x = stack.nodes[item];
Ch ng 5. Ng n x p và hàng i Trang 63
u trúc d li u và gi i thu t
ProcessNode(x);
}
}
trong ó: ProcessNode(DATA x) là hàm x lý m t ph n t trong ng n x p.
6.1.3. u tr Stack b ng danh sách liên k t
v Khai báo:
− Ki u m t ph n t trong ng n x p (t ng t danh sách):
struct node {
DATA info;
struct node *pNext;
};
typedef struct node NODE;
− Ki u ng n x p (t ng t danh sách liên k t):
struct stack {
NODE* pHead;
NODE* pTail;
};
typedef struct stack STACK;
Ho c:
typedef LIST STACK;
v Các phép toán c b n:
1. Kh i t o ng n x p
void init(STACK &stack) {
stack.pHead = NULL;
stack.pTail = NULL;
}
2. Phép toán empty: ki m tra xem ng n x p có r ng hay không ?
int empty(STACK stack) {
return (stack.pHead==NULL ? TRUE : FALSE);
}
3. T o m i m t ph n t :
NODE* getNode (DATA x){
NODE* p = new NODE;
if (p==NULL) return NULL;
p->info = x;

Ch ng 5. Ng n x p và hàng i Trang 64
u trúc d li u và gi i thu t
p->pNext = NULL;
return p;
}
4. Phép thêm vào: Thêm m t ph n t có n i dung là info vào ng n x p.
void push(STACK &stack, DATA info) {
NODE* new_ele = getNode(info);
if (new_ele==NULL)
printf(“Ngan xep day…”);
else if (stack.pHead==NULL) {
stack.pHead = new_ele;
stack.pTail = stack.pHead;
}
else {
new_ele -> pNext = stack.pHead;
stack.pHead = new_ele;
}
}
5. Phép lo i b : Trích thông tin và lo i b ph n t nh ng n x p.
DATA pop (STACK &stack) {
NODE* p;
DATA x = NULLDATA;
if(empty(stack))
printf("Danh sach khong co phan tu.");
else {
p= stack.pHead;
x=p->info;
stack.pHead = stack.pHead->pNext;
delete p;
if (stack.pHead==NULL)
stack.pTail=NULL;
}
return x;

}
6. Xem thông tin nh ng n x p:.

Ch ng 5. Ng n x p và hàng i Trang 65
u trúc d li u và gi i thu t
DATA top (STACK stack) {
DATA x = NULLDATA;
if(empty(stack))
printf("Danh sach khong co phan tu.");
else
x = stack.pHead -> info;
return x;
}
7. Duy t ng n x p: duy t t nh cho n áy ng n x p, m i ph n t c duy t
qua 1 l n.
void ProcessStack(STACK stack){
NODE* p;
p = stack.pHead;
while (p!=NULL){
ProcessNode(p);
p=p->pNext;
}
}
trong ó: ProcessNode(NODE* p) là hàm x lý m t ph n t trong ng n x p.
8. Xóa ng n x p:
void removeStack(STACK &stack){
NODE* p;
while (stack.pHead !=NULL){
p = stack.pHead;
stack.pHead = p->pNext;
delete p;
}
stack.pTail =NULL;
}
6.1.4. ng d ng c a Stack
C u trúc Stack thích h p l u tr các lo i d li u mà trình t truy xu t ng cv i
trình t l u tr , do v y m t s ng d ng sau th ng c n n stack:
Trong trình biên d ch (thông d ch), khi th c hi n các th t c, Stack c s d ng
l u môi tr ng c a các th t c.
Trong m t s bài toán c a lý thuy t th (nh tìm ng i), Stack c ng th ng
c s d ng l u d li u khi gi i các bài toán này.

Ch ng 5. Ng n x p và hàng i Trang 66
u trúc d li u và gi i thu t
Ngoài ra, Stack c ng còn c s d ng trong tr ng h p kh qui uôi.
v Stack và vi c cài t th t c quy
N u m t ch ng trình con qui P(x) c g i t ch ng trình chính ta nói ch ng
trình con c th c hi n m c 1. Ch ng trình con này g i chính nó, ta nói nó i sâu vào
m c 2... cho n m t m c k. Rõ ràng m c k ph i th c hi n xong thì m c k-1 m i c
th c hi n ti p t c, hay ta còn nói là ch ng trình con quay v m c k-1.
Trong khi m t ch ng trình con t m c i i vào m c i+1 thì các bi n c c b c a m c
i và a ch c a mã l nh còn dang d ph i c l u tr , a ch này g i là a ch tr v .
Khi t m c i+1 quay v m c i các giá tr ó c s d ng. Nh v y nh ng bi n c c b và
a ch l u sau c dùng tr c. Tính ch t này g i ý cho ta dùng m t ng n x p l u gi
các giá tr c n thi t c a m i l n g i t i ch ng trình con. M i khi lùi v m t m c thì các
giá tr này c l y ra ti p t c th c hi n m c này. Ta có th tóm t t quá trình nh sau:
c 1: L u các bi n c c b và a ch tr v .
c 2: N u tho u ki n ng ng qui thì chuy n sang b c 3. N u không thì tính
toán t ng ph n và quay l i b c 1 ( qui ti p).
c 3: Khôi ph c l i các bi n c c b và a ch tr v .
Ví d dùng ng n x p lo i b ch ng trình qui c a bài toán "Tháp Hà N i".
Ch ng trình con qui gi i bài toán tháp Hà N i nh sau:
void Move(int N, int x, int y, int z) {
if (n==1)
printf("Chuyen 1 dia tu %d sang %d\n", x, y);
else {
Move(N-1, x,z,y); //chuy n N-1 a t c c ngu n sang c c trung gian
Move(1,x,y,z); //chuy n 1 a t c c ngu n sang c c ích
Move(N-1,z,y,x); //chuy n N-1 a t c c trung gian sang c c ích
}
}
Quá trình th c hi n ch ng trình con c minh ho v i ba a (N=3) nh sau:
Move(1,x,y,z)
Move(2,x,z,y) Move(1,x,z,y)
Move(1,y,z,x)
Move(3,x,y,z) Move(1,x,y,z)
Move(1,z,x,y)
Move(2,z,y,x) Move(1,z,y,x)
Move(1,x,y,z)
M c1 M c2 M c3
kh qui ta ph i n m nguyên t c sau ây:
M i khi ch ng trình con qui c g i, ng v i vi c i t m c i vào m c i+1, ta
Ch ng 5. Ng n x p và hàng i Trang 67
u trúc d li u và gi i thu t
ph i l u tr các bi n c c b c a ch ng trình con b c i vào ng n x p. Ta c ng ph i l u
a ch mã l nh" ch a c thi hành c a ch ng trình con m c i. Tuy nhiên khi l p
trình b ng ngôn ng c p cao thì ây không ph i là a ch ô nh ch a mã l nh c a máy mà
ta s t ch c sao cho khi m c i+1 hoàn thành thì l nh ti p theo s c th c hi n là l nh
u tiên ch a c thi hành trong m c i.
T p h p các bi n c c b c a m i l n g i ch ng trình con xem nh là m t m u tin
ho t ng (activation record).
M i l n th c hi n ch ng trình con t i m c i thì ph i xoá m u tin l u các bi n c c
b m c này trong ng n x p.
Nh v y n u ta t ch c ng n x p h p lí thì các giá tr trong ng n x p ch ng nh ng
u tr c các bi n c c b cho m i l n g i qui, mà còn " i u khi n c th t tr
v " c a các ch ng trình con. Ý t ng này th hi n trong cài t kh qui cho bài toán
tháp Hà N i là: m u tin l u tr các bi n c c b c a ch ng trình con th c hi n sau thì
c a vào ng n x p tr c nó c l y ra dùng sau.
//Ki u c u trúc l u tr bi n c c b
struct data {
int N;
int x, y, z;
};
typedef struct data DATA;
void MOVE(DATA X) {
DATA data, temp;
STACK stack;
init(stack);
push(stack,X);
do {
data=pop(stack); //Lay phan tu dau
if (data.N==1)
printf("\nChuyen 1 dia: %d --> %d",data.x,data.y);
else {
//Luu cho loi goi Move(N-1,z,y,x)
temp.N=data.N-1;
temp.x=data.z;
temp.y=data.y;
temp.z=data.x;
push(stack,temp);
// Luu cho loi goi Move(1,x,y,z)
temp.N=1;
Ch ng 5. Ng n x p và hàng i Trang 68
u trúc d li u và gi i thu t
temp.x=data.x;
temp.y=data.y;
temp.z=data.z;
push(stack,temp);
// Luu cho loi goi Move(N-1,x,z,y)
temp.N=data.N-1;
temp.x=data.x;
temp.y=data.z;
temp.z=data.y;
push(stack,temp);
}
} while (!empty(stack));
}
Các l n l p ti p t c ch x lý vi c chuy n 1 a ( ng v i tr ng h p không g i
qui). Ch ng trình con in ra các phép chuy n và d n n ng n x p r ng.

6.2. Hàng i (Queue)


6.2.1. nh ngh a
ng t nh ng n x p (stack), hàng i (queue) c ng là m t t p h p các ph n t
(items) cùng ki u c t ch c m t cách tu n t , trong ó ph n t c thêm vào u
tiên c a t p h p s là ph n t b lo i b u tiên kh i t p h p (ng c l i v i ng n x p).
Các hàng i th ng c g i là các c u trúc FIFO (First In First Out).
6.2.2. u tr Queue b ng m ng
v Khai báo:
# define MAX_ELE 100
struct queue {
int front, rear; // ch s ph n t u, cu i c a hàng i
DATA nodes[MAX_ELE]; // hàng i là m ng 1 chi u
};
typedef struct queue QUEUE;
v Các phép toán c b n:
1. Kh i t o hàng i
void init(QUEUE &queue) {
queue.front= queue.rear=MAX_ELE;
}
2. Phép toán empty: ki m tra xem hàng i có r ng hay không ?

Ch ng 5. Ng n x p và hàng i Trang 69
u trúc d li u và gi i thu t
int empty(QUEUE queue) {
return (queue.front==queue.rear ? TRUE : FALSE);
}
3. Phép toán full: ki m tra xem hàng i ã y ch a ?
int full(QUEUE queue)
{
return (queue.rear - queue.front +1 ) % MAX_ELE==0;
}
4. Phép thêm vào: Thêm m t ph n t có n i dung là info vào hàng i.
L u ý: Khi thêm m t ph n t vào hàng i, ta ph i ki m tra xem hàng i ã y
hay ch a ?
void push(QUEUE &queue, DATA info) {
if (full(queue))
printf("Hang doi day.");
else {
if (queue.rear<MAX_ELE)
queue.rear++;
else
queue.rear=1;
queue.nodes[queue.rear] = info;
}
}
5. Phép lo i b : Trích thông tin và lo i b ph n t nh hàng i.
DATA pop (QUEUE & queue) {
DATA x=NULLDATA;
if(empty(queue))
printf("Hang doi khong co phan tu.");
else {
if (queue.front<MAX_ELE)
queue.front++;
else queue.front=1;
x = queue.nodes[queue.front];
}
return x;
}

Ch ng 5. Ng n x p và hàng i Trang 70
u trúc d li u và gi i thu t
6. Xem thông tin ph n t u hàng i:
DATA front(QUEUE queue) {
DATA x=NULLDATA;
if(empty(queue))
printf("Hang doi khong co phan tu.");
else {
if (queue.front<MAX_ELE)
queue.front++;
else queue.front=1;
x = queue.nodes[queue.front];
}
return x;
}
7. Xem thông tin ph n t cu i hàng i:
DATA rear (QUEUE queue) {
DATA x=NULLDATA;
if(empty(queue))
printf("Hang doi khong co phan tu.");
else
x = queue.nodes[queue.rear];
return x;
}
6.2.3. u tr Queue b ng danh sách liên k t
v Khai báo:
− Ki u m t ph n t trong hàng i (t ng t danh sách):
struct node {
DATA info;
struct node *pNext;
};
typedef struct node NODE;
− Ki u hàng i (t ng t danh sách liên k t):
struct queue {
NODE* pHead;
NODE* pTail;
};

Ch ng 5. Ng n x p và hàng i Trang 71
u trúc d li u và gi i thu t
typedef struct queue QUEUE;
Ho c:
typedef LIST QUEUE;
v Các phép toán c b n:
1. Kh i t o hàng i
void init(QUEUE & queue) {
queue.pHead = NULL;
queue.pTail = NULL;
}
2. Phép toán empty: ki m tra xem hàng i có r ng hay không ?
int empty(QUEUE queue) {
return (queue.pHead==NULL ? TRUE : FALSE);
}
3. T o m i m t ph n t :
NODE* getNode (DATA x){
NODE* p = new NODE;
if (p==NULL) return NULL;
p->info = x;
p->pNext = NULL;
return p;
}

4. Phép thêm vào: Thêm m t ph n t có n i dung là info vào hàng i.


void push(QUEUE & queue, DATA info) {
NODE* new_ele = getNode(info);
if (new_ele==NULL)
printf(“Hang doi day…”);
else if (empty(queue)==1) {
queue.pHead = new_ele;
queue.pTail = queue.pHead;
}
else {
queue.pTail -> pNext = new_ele;
queue.pTail = new_ele;

Ch ng 5. Ng n x p và hàng i Trang 72
u trúc d li u và gi i thu t
}
}
5. Phép lo i b : Trích thông tin và lo i b ph n t ra kh i hàng i.
DATA pop (QUEUE &q) {
NODE* p;
DATA x = NULLDATA;
if(empty(queue))
printf("Hang doi khong co phan tu.");
else {
p= queue.pHead;
x=p->info;
queue.pHead = queue.pHead->pNext;
delete p;
if (queue.pHead==NULL)
queue.pTail=NULL;
}
return x;
}
6. Xem thông tin u hàng i:.
DATA top (QUEUE queue) {
DATA x = NULLDATA;
if(empty(queue))
printf("Hang doi khong co phan tu.");
else
x = queue.pHead -> info;
return x;
}
7. Duy t hàng i: duy t t nh cho n áy hàng i, m i ph n t c duy t
qua 1 l n.
void ProcessQueue(QUEUE queue){
NODE* p;
p = queue.pHead;
while (p!=NULL){
ProcessNode(queue);
p=p->pNext;

Ch ng 5. Ng n x p và hàng i Trang 73
u trúc d li u và gi i thu t
}
}
trong ó: ProcessNode(NODE* queue) là hàm x lý m t ph n t trong hàng i.
8. Xóa hàng i:
void removeQueue(QUEUE & queue){
NODE* p;
while (queue.pHead !=NULL){
p = queue.pHead;
queue.pHead = p->pNext;
delete p;
}
queue.pTail =NULL;
}
6.2.4. ng d ng c a Queue
v Trong các h u hành:
− Hàng i các công vi c ho c các ti n trình ang i c th c hi n
− Hàng i các ti n trình ch các tín hi u t các thi t b IO
− Các file c g i t i máy in
v Mô ph ng các h th ng hàng i th i trong th c t .
− Các khách hàng trong các c a hàng t p hóa, trong các h th ng ngân hàng
− Các n t hàng c a m t công ty
− Phòng c p c u
− Các cu c g i n tho i ho c các t hàng vé máy bay, các t hàng
c a khách hàng …
v Các ng d ng khác: Th t topo: v i m t t p các s ki n, và các c p (a, b)
trong ó s ki n a có u tiên cao h n so v i s ki n b (bài toán l p l ch),
duy t th theo chi u r ng (Breadth First Search).

Bài t p
1. Vi t ch ng trình i s th p phân thành s nh phân và ng c l i.
2. Hãy vi t ch ng trình chuy n i m t bi u th c d ng infix (d ng thông
th ng) n gi n (không ch a các d u ()) thành m t bi u th c d ng ti n t
(prefix).
3. Vi t ch ng trình ki m tra các c p ký hi u cân b ng trong m t ch ng trình
ch ng h n {}, (), [].
Ví d {()} và {()({})} là các bi u th c úng còn {((} và {(}) không ph i là
các bi u th c úng.
Ch ng 5. Ng n x p và hàng i Trang 74