Stack đ c nng d ng đ bi u di n nhi u thu t gi i ph c t p khác nhau, đ c bi t đ i v i nh ng bài toán c n s d ng đ n các l i g i đ qui. D i đây là m t s các ví d đi n hình c a vi c ng d ng stack.
o ng c xâu kí t : Quá trình đ o ng c m t xâu kí t gi ng nh vi c đ a vào
(push) t ng kí t trong xâu vào stack, sau đó đ a ra (pop) các kí t trong stack ra cho t i khi stack r ng ta đ c m t xâu đ o ng c.
Chuy n đ i s t h th p phân sang h c s b t k : chuy n đ i m t s h
tr l i ph n d c a phép chia, sau đó đ o ng c l i dãy các s d ta nh n đ c s c n chuy n đ i, vi c làm này gi ng nh c ch LIFO c a stack.
Tính giá tr m t bi u th c d ng h u t :Xét m t bi u th c d ng h u t ch ch a các phép toán c ng (+), tr (-), nhân (*), chia (/), l y th a ($). C n ph i nh c l i r ng, nhà logic h c Lewinski đã ch ng minh đ c r ng, m i bi u th c đ u có th bi u di n d i d ng h u t mà không c n dùng thêm các kí hi u ph .
Ví d : 23+5*2$ = ( (2 + 3) *5 ) 2 = 625
tính giá tr c a bi u th c d ng h u t , chúng ta s d ng m t stack l u tr bi u th c quá trình tính toán đ c th c hi n nh sau:
L y toán h ng 1 ( 2 ) -> L y toán h ng 2 ( 3 ) -> L y phép toán ‘+’ -> L y toán h ng 1 c ng toán h ng 2 và đ y vào stack (5) -> L y toán h ng ti p theo (5), l y phép toán ti p theo (*), nhân v i toán h ng 1 r i đ y vào stack (25), l y toán h ng ti p theo (2), l y phép toán ti p theo ($) và th c hi n, l y lu th a r i đ y vào stack. Cu i cùng ta nh n đ c 25 2= 625.
D i đây là ch ng trình đ o ng c xâu kí t s d ng stack. Nh ng ví d khác, b n đ c có th tìm th y trong các tài li u [1], [2]. Ví d 3.1. Ch ng trình đ o ng c xâu kí t . #include <stdio.h> #include <stdlib.h> #include <conio.h> #include <dos.h> #include <string.h> #define MAX 100 #define TRUE 1 #define FALSE 0 typedef struct{ int top; char node[MAX]; } stack;
/* nguyen mau cua ham*/
int Empty(stack *); void Push(stack *, char);
char Pop(stack *); /* Mo ta ham */ int Empty(stack *ps){ if (ps->top==-1) return(TRUE); return(FALSE); }
if (ps->top==MAX-1 ){
printf("\n Stack full"); delay(2000); return; } (ps->top)= (ps->top) + 1; ps->node[ps->top]=x; } char Pop(stack *ps){ if (Empty(ps)){
printf("\n Stack empty"); delay(2000);return(0); } return( ps ->node[ps->top--]); } void main(void){ stack s; char c, chuoi[MAX]; int i, vitri,n;s.top=-1;clrscr();
printf("\n Nhap String:");gets(chuoi); vitri=strlen(chuoi);
for (i=0; i<vitri;i++) Push(&s, chuoi[i]); while(!Empty(&s)) printf("%c", Pop(&s)); getch(); } 3.2. HÀNG I (QUEUE) 3.2.1. nh ngh a và khai báo
Khác v i stack, hàng đ i (queue) là m t danh sách tuy n tính mà thao tác b sung ph n t đ c th c hi n m t đ u g i là l i vào (rear). Phép lo i b ph n t đ c th c hi n m t đ u khác g i là l i ra (front). Nh v y, c ch c a queue gi ng nh m t hàng đ i, đi vào m t đ u và đi ra m t đ u hay FIFO (First- In- First- Out).
Ta có th khai báo hàng đ i nh m t danh sách tuy n tính g m MAX ph n t m i ph n t là m t c u trúc, hai bi n front, rear tr l i vào và l i ra trong queue. Ví d d i đây đnh ngh a m t hàng đ i c a các s n ph m g m hai thu c tính mã hàng (mahang) và tên hàng (ten).
typedef struct{ int mahang;
char ten[20]; } hang;
typedef struct {
int front, rear; hang node[MAX]; } q;
truy nh p vào hàng đ i, chúng ta s d ng hai bi n con tr front ch l i tr c và
rear ch l i sau. Khi l i tr c trùng v i l i sau (q.rear = q.rear) thì queue tr ng thái r ng (hình a), đ thêm d li u vào hàng đ i các ph n t A, B, Cđ c th c hi n thông qua thao tác insert(q,A), insert(q,B), insert(q,C) đ c mô t hình b, thao tác lo i b ph n t kh i hàng đ i Remove(q)đ c mô t hình c, nh ng thao tác ti p theo đ c mô t t i hình d, e.
Hình a. Tr ng thái r ng c a hàng đ i. q.rear=2 q.front=0 Hình b. insert(Q,A);insert(Q,B), insert(Q,C)
q.rear=2 q.front=1 Hình c. remove(q).
q.rear=3 q.front=1 Hình d. insert(q,D).
q.rear=3 q.front=2 Hình e. remove(q).
Hình 3.3. Các thao tác trên Hàng đ i (Queue)
Cách t ch c này s d n t i tr ng h p các ph n t di chuy n kh p không gian nh khi th c hi n b sung và lo i b . Trong nhi u tr ng h p, khi th c hi n thêm ho c lo i b ph n t c a hàng đ i chúng ta c n xét t i m t th t u tiên nào đó, khi đó hàng đ i đ c g i là hàng đ i có đ u tiên ( Priority Queue ). V i priority queue, thì nút nào có đ u tiên cao nh t đ c th c hi n lo i b tr c nh t, còn v i thao tác thêm ph n t vào hàng đ i tr thành thao tác thêm ph n t vào hàng đ i có xét t i đ u tiên.
C B A
C B
D C B
3.2.2. ng d ng hàng đ i
M i v n đ c a th c t liên quan t i c ch FIFO nh c ch g i ti n, rút ti n trong ngân hàng, đ t vé máy bay đ u có th ng d ng đ c b ng hàng đ i. Hàng đ i còn có nh ng ng d ng trong vi c gi i quy t các bài toán c a H đi u hành và ch ng trình d ch nh bài toán đi u khi n các quá trình, đi u khi n n p ch ng trình vào b nh hay bài toán l p l ch. B n đ c có th tham kh o thêm trong các tài li u [1], [2]. D i đây, chúng ta đ a ra m t ng d ng c a hàng đ i đ gi i quy t bài toán “Nhà s n xu t và Ng i tiêu dùng”.
Ví d 3.2- Gi i quy t bài toán ”Ng i s n xu t và nhà tiêu dùng “ v i s các vùng đ m h n ch .
Chúng ta mô t quá trình s n xu t và tiêu dùng nh hai quá trình riêng bi t và th c hi n song hành, ng i s n xu t có th s n xu t t i đa n m t hàng. Ng i tiêu dùng ch đ c phép s d ng trong s n m t hàng. Tuy nhiên, ng i s n xu t ch có th l u tr vào kho khi và ch khi kho ch a b đ y. Ng c l i, n u kho hàng không r ng (kho có hàng) ng i tiêu dùng có th tiêu dùng nh ng m t hàng trong kho theo nguyên t c hàng nào nh p vào kho tr c đ c tiêu dùng tr c gi ng nh c ch FIFO c a queue. Sau đây là nh ng thao tác ch y u trên hàng đ i đ gi i quy t bài toán:
Ta xây d ng hàng đ i nh m t danh sách tuy n tính g m MAX ph n t m i ph n t là m t c u trúc, hai bi n front, rear tr đ n l i vào và l i ra trong queue:
typedef struct{ int mahang; char ten[20]; } hang;
typedef struct {
int front, rear; hang node[MAX]; } queue;
Thao tác Initialize: thi t l p tr ng thái ban đ u c a hàng đ i. tr ng thái này, font và rear có cùng m t giá tr MAX-1.
void Initialize ( queue *pq){
pq->front = pq->rear = MAX -1; }
Thao tác Empty: ki m tra hàng đ i có tr ng thái r ng hay không. Hàng đ i r ng khi front == rear.
int Empty(queue *pq){
if (pq->front==pq->rear) return(TRUE); return(FALSE); }
Thao tác Insert: thêm X vào hàng đ i Q. N u vi c thêm X vào hàng đ i đ c th c hi n đ u hàng, khi đó rear có giá tr 0, n u rear không ph i đ u hàng đ i thì giá tr c a nó đ c t ng lên 1 đ n v .
void Insert(queue *pq, hang x){ if (pq->rear==MAX-1 ) pq->rear=0; else
(pq->rear)++; if (pq->rear ==pq->front){
printf("\n Queue full"); delay(2000);return; }
else
pq->node[pq->rear]=x; }
Thao tác Remove: lo i b ph n t v trí front kh i hàng đ i. N u hàng đ i tr ng thái r ng thì thao tác Remove không th th c hi n đ c, trong tr ng h p khác front đ c t ng lên m t đ n v .
hang Remove(queue *pq){ if (Empty(pq)){
printf("\n Queue Empty"); delay(2000); } else { if (pq->front ==MAX-1) pq->front=0; else pq->front++; } return(pq->node[pq->front]); }
Thao tác Traver: Duy t t t c các nút trong hàng đ i. void Traver( queue *pq){
int i;
if(Empty(pq)){
printf("\n Queue Empty");
return;
}
if (pq->front ==MAX-1)
else
i = pq->front+1; while (i!=pq->rear){
printf("\n %11d % 15s", pq->node[i].mahang, pq->node[i].ten); if(i==MAX-1)
i=0;
else
i++; }
printf("\n %11d % 15s", pq->node[i].mahang, pq->node[i].ten); } D i đây là toàn b v n b n ch ng trình: #include <stdio.h> #include <stdlib.h> #include <conio.h> #include <dos.h> #include <string.h> #include <math.h> #define MAX 50 #define TRUE 1 #define FALSE 0 typedef struct{ int mahang; char ten[20]; } hang; typedef struct {
int front, rear; hang node[MAX]; } queue;
/* nguyen mau cua ham*/ void Initialize( queue *pq); int Empty(queue *); void Insert(queue *, hang x); hang Remove(queue *);
void Traver(queue *); /* Mo ta ham */
void Initialize ( queue *pq){
pq->front = pq->rear = MAX -1; }
int Empty(queue *pq){
return(TRUE); return(FALSE); }
void Insert(queue *pq, hang x){ if (pq->rear==MAX-1 ) pq->rear=0; else
(pq->rear)++; if (pq->rear ==pq->front){
printf("\n Queue full"); delay(2000);return; } else pq->node[pq->rear]=x; } hang Remove(queue *pq){ if (Empty(pq)){
printf("\n Queue Empty"); delay(2000); } else { if (pq->front ==MAX-1) pq->front=0; else pq->front++; } return(pq->node[pq->front]); }
void Traver( queue *pq){ int i;
if(Empty(pq)){
printf("\n Queue Empty");
return; } if (pq->front ==MAX-1) i=0; else i = pq->front+1; while (i!=pq->rear){
printf("\n %11d % 15s", pq->node[i].mahang, pq->node[i].ten); if(i==MAX-1)
i=0;
else
i++; }
printf("\n %11d % 15s", pq->node[i].mahang, pq->node[i].ten); }
void main(void){ queue q;
char chucnang, front1; char c; hang mh; clrscr();
Initialize(&q); do {
clrscr();
printf("\n NGUOI SAN XUAT/ NHA TIEU DUNG"); printf("\n 1- Nhap mot mat hang");
printf("\n 2- Xuat mot mat hang"); printf("\n 3- Xem mot mat hang"); printf("\n 4- Xem hang moi nhap"); printf("\n 5- Xem tat ca");
printf("\n 6- Xuat toan bo");
printf("\n Chuc nang chon:");chucnang=getch(); switch(chucnang){
case ‘1’:
printf("\n Ma mat hang:"); scanf("%d", &mh.mahang); printf("\n Ten hang:");scanf("%s", mh.ten);
Insert(&q,mh);break;
case ‘2’:
if (!Empty(&q)){
mh=Remove(&q);
printf("\n %5d %20s",mh.mahang, mh.ten); }
else {
printf("\n Queue Empty"); delay(1000);
}
break;
case ‘3’:
front1=(q.front==MAX-1)?0:q.front+1; printf("\n Hang xuat");
printf("\n%6d%20s",q.node[front1].mahang,q.node[front1].ten); break;
case ‘4’:
printf("\n Hang moi nhap");
printf("\n%5d%20s",q.node[q.rear].mahang,q.node[q.rear].ten); break;
case ‘5’:
printf("\ Hang trong kho"); Traverse(&q);delay(2000);break; } } while(chucnang!=’0’); } 3.3. DANH SÁCH LIÊN K T N 3.3.1. Gi i thi u và đnh ngh a
M t danh sách móc n i, ho c ng n g n h n, m t danh sách, là m t dãy có th t các ph n t đ c g i là đnh. Danh sách có đi m b t đ u, g i là tiêu đ hay đnh đ u, m t đi m cu i cùng g i là đnh cu i. M i đnh trong danh sách đ u có cùng ki u ngay c khi ki u này có nhi u d ng khác nhau.
B n ch t đ ng là m t trong nh ng tính ch t chính c a danh sách móc n i. Có th thêm ho c b t đnh trong danh sách vào m i lúc, m i v trí. Vì s đnh c a danh sách không th d ki n tr c đ c, nên khi th c hi n, chúng ta ph i dùng con tr mà không dùng đ c m ng đ b o đ m vi c th c hi n hi u qu và tin c y.
M i đnh trong danh sách đ u g m hai ph n. Ph n th nh t ch a d li u. D li u có th ch là m t bi n đ n ho c là m t c u trúc (ho c con tr c u trúc) có ki u nào đó. Ph n th hai c a đnh là m t con tr ch vào đa ch c a đnh ti p theo trong danh sách. Vì v y có th d dàng s d ng các đnh c a danh sách qua m t c u trúc t tr ho c đ qui.
Danh sách móc n i đ n gi n d i đây xây d ng m i đnh c a danh sách ch l u gi m t bi n nguyên.
/*đnh c a danh sách đ n ch ch a m t s nguyên*/ struct don {
int phantu; struct don *tiep; };
typedef struct don don_t;
Trong tr ng h p này, bi n nguyên phantu c a t ng đnh ch a d li u còn bi n con tr tiep ch a đa ch c a đnh ti p theo. S đ bi u di n danh sách móc n i đ n đ c bi u di n nh hình d i đây:
Ph n_t Ph n_t Ph n_t ....
T ng quát h n, m i đnh c a danh sách có th ch a nhi u ph n t d li u. Trong tr ng h p này, h p lý h n c là đnh ngh a m t ki u c u trúc t ng ng v i d li u c n l u gi t i m i đnh. Ph ng pháp này đ c s d ng trong đnh ngh a ki u sau đây:
/*đnh c a danh sách t ng quát */ struct tq { thtin_t phantu; struc tq*tiep; }; typedef struct tq tq_t; Ki u c u trúc thtin_t ph i đ c đnh ngh a tr c đó đ t ng ng v i các d li u s đ c l u tr t i t ng đnh. Danh sách đ c t o nên t ki u đnh này gi ng nh s đ trong Hình 3.4, ngo i tr vi c m i phantu là m t bi n nguyên.
3.3.2. Các thao tác trên danh sách móc n i
Các thao tác trên danh sách móc n i bao g m vi c c p phát b nh cho các đnh và gán d li u cho con tr . danh sách đ c t o nên đúng đ n, ta bi u di n ph n t cu i danh sách là m t con tr NULL. Con tr NULL là tín hi u thông báo không còn ph n t nào ti p theo trong danh sách n a.
Ti n h n c là chúng ta đnh ngh a m t con tr t i danh sách nh sau:
struct node { int infor; struct node *next; };
typedef struct node *NODEPTR; // Con tr t i node
C p phát b nh cho m t node:
NODEPTR Getnode(void) { NODEPTR p;
P = (NODEPTR) malloc(sizeof( struct node)); Return(p);
}
Gi i phóng b nh c a m t node”
NODEPTR Freenode( NODEPTR p){ free(p);
}
Chèn m t ph n t m i vào đ u danh sách:
Các b c đ chèn m t ph n t m i vào đ u danh sách c n th c hi n là: X C p không gian b nh đ l u gi m t đnh m i;
X Thi t l p liên k t v i đnh m i.
S đ bi u di n phép thêm m t đnh m i vào đ u danh sách đ c th hi n nh trên hình 3.5.
Node c n chèn vào đ u danh sách móc n i.
Hình 3.5. Thêm đnh m i vào đ u danh sách móc n i đ n
void Push_Top( NODEPTR *plist, int x) { NODEPTR p;
p= Getnode(); // c p không gian nh cho đnh m i p -> infor = x; // gán giá tr thích h p cho đnh m i p ->next = *plist;
*plist = p; // thi t l p liên k t }
Thêm m t ph n t m i vào cu i danh sách:
thêm m t node vào cu i danh sách, ta c n th c hi n qua các b c sau: X C p phát b nh cho node m i;
X Gán giá tr thích h p cho node m i;
X Di chuy n con tr t i ph n t cu i danh sách; X Thi t l p liên k t cho node m i.
S đ th hiên phép thêm m t ph n t m i vào cu i danh sách đ c th hi n nh trong hình 3.6
Hình 3.6. Thêm node m i vào cu i danh sách.
infor next infor next infor next
infor next
infor next infor next infor next
void Push_Bottom( NODEPTR *plist, int x) { NODEPTR p, q;
p= Getnode(); // c p phát b nh cho node m i p->infor = x; // gán giá tr thông tin thích h p q = *plist; // chuy n con tr t i cu i danh sách while (q-> next != NULL)
q = q -> next;
// q là node cu i cùng c a danh sách liên k t q -> next = p; //node cu i bây gi là node p; p ->next = NULL; // liên k t m i c a p }
Thêm node m i q vào gi a danh sách tr c node p:
thêm node q vào tr c node p, chúng ta c n l u ý node p ph i có th c trong danh sách. Gi s node p là có th c, khi đó x y ra hai tình hu ng: ho c node p là node cu i cùng c a danh sách liên k t t c p->next =NULL, ho c node p ch a ph i là cu i cùng hay p->next != NULL. Tr ng h p th nh t, chúng ta ch c n g i t i thao tác Push_Bottom(). Tr ng h p th 2, chúng ta th c hi n theo các b c nh sau:
X C p phát b nh cho node m i; X Gán giá tr thích h p cho node;
X Thi t l p liên k t node q v i node k ti p p; X Thi t l p liên k t node node p v i node q; void Push_Before( NODEPTR p, int x ){
NODEPTR q; if (p->next==NULL) Push_Bottom(p, x);
else {
q= Getnode(); // c p phát b nh cho node m i q -> infor = x; // gán giá tr thông tin thích h p
q-> next = p-> next; // thi t l p liên k t node q v i node k ti p p; p->next = q; // thi t l p liên k t node p v i node k ti p q;