Ngd ng ca stack

Một phần của tài liệu cơ sở kỷ thuật lập trình (Trang 54)

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;

Một phần của tài liệu cơ sở kỷ thuật lập trình (Trang 54)

Tải bản đầy đủ (PDF)

(156 trang)