You are on page 1of 58

Chương 5

Stack & Queue


Nội dung trình bày

• Giới thiệu
• Cài đặt
Stack
• Các thao tác
• Ứng dụng

• Giới thiệu
• Cài đặt
Queue
• Các thao tác
• Ứng dụng

Cấu trúc dữ liệu - Khoa CNTT 2


Cấu trúc dữ liệu - Khoa CNTT 3
5.1 Stack

Giới
Cài đặt
thiệu

Các thao Ứng


tác dụng

Cấu trúc dữ liệu - Khoa CNTT 4


5.1.1 Giới thiệu stack
 Một ngăn xếp (stack) là
một cấu trúc dữ liệu mà
việc bổ sung và loại bỏ
được thực hiện tại
cùng một đầu (gọi là
đỉnh của stack).
 Cơ chế hoạt động của
stack là vào sau ra
trước – LIFO (Last In
First Out)
5.1.1 Giới thiệu stack
 Lưu trữ kế tiếp: dạng mảng một chiều
 Lưu trữ móc nối: dạng danh sách liên kết

Cấu trúc dữ liệu - Khoa CNTT 7


5.1.1 Giới thiệu stack
 Lưu trữ kế tiếp: dạng mảng một chiều
 Lưu trữ móc nối: dạng danh sách liên kết

pTop 700

Địa chỉ 700 ‘S’ 300

300 ‘L’ 600

600 ‘D’ null

Cấu trúc dữ liệu - Khoa CNTT 8


5.1.1 Giới thiệu
Mảng 1 chiều Danh sách LK
Kích thước stack Cấp phát
khi quá thiếu, lúc động!
quá thừa

Push/Pop
Push / Pop hơi khá dễ
phức tạp dàng

Cấu trúc dữ liệu - Khoa CNTT 9


5.1.2 Cài đặt
 Lưu trữ móc nối: dạng danh sách liên kết
pTop info next
700
typedef struct node
node {
7 300 DataType info;
node* next;
12 600 } NODE;
typedef NODE* NodePtr;

9 null NodePtr pTop;

pTop quản lý stack


Cấu trúc dữ liệu - Khoa CNTT 10
5.1.3 Các thao tác
 Các thao tác trên stack Phần minh hoạ
sẽ dùng
InitStack Push DataType là int
Pop
IsEmpty GetSize
Top

pTop

Đầu
danh sách

Cấu trúc dữ liệu - Khoa CNTT 11


5.1.3 Các thao tác trên ngăn xếp
 Init: khởi tạo ngăn xếp, ban đầu chưa có phần tử nào
void Init(NodePtr *pTop)
{
*pTop = NULL;
}

 IsEmpty: kiểm tra ngăn xếp rỗng

int IsEmpty(NodePtr pTop)


{
return (pTop==NULL);
}

Cấu trúc dữ liệu - Khoa CNTT 12


5.1.3 Các thao tác
 Push – Đưa một phần tử mới vào đỉnh stack
- Tạo nút mới
- Đưa vào đỉnh stack

pTop pTop
Push
new

2 9 8 2 9
node

Cấu trúc dữ liệu - Khoa CNTT 13


5.1.3 Các thao tác
 Push – Đưa một phần tử mới vào đỉnh stack

1. void Push(NodePtr &pTop, int x)


2. { //tao nut moi
3. NodePtr node;
4. node = new NODE;
5. node->info = x;
6. //dua vao dinh ngan xep
7. node->next = pTop;
8. pTop = node;
9. }

Cấu trúc dữ liệu - Khoa CNTT 14


5.1.3 Các thao tac
 Pop: Lấy một phần tử ra khỏi đỉnh Stack
- Lấy ra phần tử đầu danh sách

- Trả về nội dung và giải phóng nút

pTop pTop
Pop

5 2 9 2 9

15
5.1.3 Các thao tác
1. int Pop(NodePtr &pTop)
2. {
3. NodePtr p; //trỏ nút loại bỏ
4. int value; //lưu giá trị nút
5. if (pTop == NULL) //ngăn xếp rỗng
6. { cout<<“Stack is empty!”;
7. return -1;
8. }
9. p = pTop;
10. pTop = pTop->next;
11. value = p->info;
12. delete p;
13. return value;
14.}
16
5.1.3 Các thao tác
GetSize - đếm số nút của stack
1. int GetSize(NodePtr &pTop)
2. { int d = 0;
3. NodePtr p; //con tro duyet
4. p = pTop; //duyet tu dau
5. while (p!= NULL)
6. { d++;
7. p = p -> next;
8. }
9. return d;
10.}
17
5.1.3 Các thao tác

 Top: Lấy ra nội dung của phần tử đầu stack

pTop

Top

5 2 9
pTop

5 2 9

18
5.1.3 Các thao tác

 Top: Lấy ra nội dung của phần tử đầu stack

1. int Top(NodePtr pTop)


2. {
3. if (pTop == NULL)
4. return -1;
5. else
6. return pTop -> info;
7. }

19
5.1.4 Ứng dụng stack
 Ứng dụng stack
- Khử đệ quy:
 Tháp Hanoi, QuickSort…

- Áp dụng cho các bài toán dùng mô hình LIFO


 Bài toán đổi cơ số

 Chuyển biểu thức trung tố sang hậu tố

 Tính giá trị biểu thức hậu tố

20
Chuyển đổi hệ cơ số
 Chuyển đổi một số nguyên n từ hệ cơ số 10 sang hệ cơ
số b, dùng Stack
22 2
Quy tắc
Muốn đổi số nguyên n từ hệ cơ 0 11 2
số 10 sang hệ cơ số b, thực hiện
như sau: 1 5 2
B1: Lấy n chia cho b.
B2: Nếu kết quả còn khác 0, 1 2 2
chia tiếp cho b, nếu kết quả bằng
0 chuyển sang bước 3. 0 2
B3: Viết ngược thứ tự các phần
1
dư nhận được trong quá trình 1
thực hiện phép chia ta thu được
0
biểu diễn của n trong hệ cơ số b. 22(10)  10110 (2)
21
Postfix
 Chuyển biểu thức trung tố sang hậu tố

Trung tố Hậu tố

(6 / 2 + 3) * (7 - 4) 62/3+74-*

Biểu thức hậu


tố dễ tính toán
hơn trong máy
tính

23
Cấu trúc dữ liệu - Khoa CNTT 24
Cấu trúc dữ liệu - Khoa CNTT 25
Cấu trúc dữ liệu - Khoa CNTT 26
Postfix
 Duyệt qua từng phần tử trong infix  C
- Nếu C là “(“ thì push  stack.

- Nếu C là “)” thì lấy tất cả phần tử trong stack cho đến khi
gặp “(“. Xuất ra biểu thức hậu tố

- Nếu C là toán tử: lấy trong stack ra tất cả toán tử có độ


ưu tiên cao hơn C, xuất những phần tử này ra biểu thức
hậu tố, và đưa C vào stack

- Trường hợp C là toán hạng xuất C ra biểu thức hậu tố

27
Postfix
(2 * 3 + 8 / 8) * (5 – 1)

Đọc Xử lý Stack Bt hậu tố


( Đẩy vào stack (
2 Xuất ra bt hậu tố ( 2
Do ‘*’ ưu tiên hơn ‘(‘ ở đỉnh stack
* (* 2
nên đưa ‘*’ vào stack
3 Xuất ra bt hậu tố (* 23
Do ‘+’ ưu tiên thấp hơn ‘*’ ở đỉnh
stack nên ta lấy ‘*’ ra.
+ (+ 23*
Tiếp tục so sánh ‘+’ với ‘(‘ thì ‘+’ ưu
tiên cao hơn nên đưa vào stack
8 Xuất ra bt hậu tố (+ 23*8
Do ‘/’ có độ ưu tiên cao hơn ‘+’ trên
/ (+/ 23*8
đỉnh stack nên đưa ‘/’ vào stack.
8 Xuất ra bt hậu tố (+/ 23*88
28
Postfix (2 * 3 + 8 / 8) * (5 – 1)
Đọc Xử lý Stack Bt hậu tố

Lấy trong stack ra cho đến khi gặp


) 23*88/+
ngoặc (.

* Đưa vào stack * 23*88/+


( Đưa vào stack *( 23*88/+
5 Xuất ra bt hậu tố *( 23*88/+5
Độ ưu tiên của ‘-‘ cao hơn ‘(‘ trong
- *(- 23*88/+5
đỉnh stack nên đưa ‘-‘ vào stack
1 Xuất ra bt hậu tố *(- 23*88/+51
Lấy trong stack ra cho đến khi gặp
) * 23*88/+51-
ngoặc đóng
Lấy những phần tử còn lại trong
23*88/+51-*
stack và hiển thị
29
Postfix - Tính giá trị biểu thức hậu tố
 Tính giá trị biểu thức postfix

Postfix không cần có dấu


ngoặc vẫn có thể tính đúng
bằng cách đọc lần lượt biểu
thức từ trái qua phải và dùng
một stack để lưu trữ kết quả
trung gian
34*5+

Jan Lukasiewicz

30
Postfix
Ý tưởng
 Khởi tạo stack = {Ø}
 Đọc biểu thức hậu tố lần lượt từ trái, kiểm tra
- Nếu toán hạng: push  stack
- Nếu toán tử: lấy hai toán hạng ở đỉnh stack ra, thực hiện
phép toán, kết quả push vào stack
 Sau khi đọc xong, trong stack còn duy nhất một
phần tử  kết quả!

31
Cấu trúc dữ liệu - Khoa CNTT 32
Cấu trúc dữ liệu - Khoa CNTT 33
35
5.2 Queue

Giới
thiệu

Ứng Cài
Queue
dụng đặt

Các
thao
tác

36
5.2.1 Giới thiệu
 Queue là một cấu trúc dữ liệu mà việc bổ sung và loại
bỏ thực hiện ở hai đầu khác nhau
 Bổ sung vào cuối và loại bỏ ở đầu

pFront pRear

5 2 9

37
5.2.1 Giới thiệu
 FIFO: First In First Out
 Thêm vào cuối và lấy ra ở đầu

38
5.2.1 Giới thiệu
 Queue dùng DSLK
- Con trỏ pFront trỏ đầu danh sách
- Con trỏ pRear trỏ đến cuối danh sách
- Thao tác Remove diễn ra ở pFront
- Tháo tác Insert diễn ra ở pRear
- Thao tác thêm xoá dễ dàng

pFront pRear

5 2 9

39
5.2.2 Cài đặt
 Khai báo cho Queue dạng DSLK

typedef struct node


{
DataType info;
node* next;
}NODE;
typedef NODE* NodePtr;
typedef struct
{
NodePtr pFront;
NodePtr pRear;
} Queue;

40
5.2.3 Các thao tác
 Các thao tác trên Queue
- Init : Khởi tạo hàng đợi

- IsEmpty : Kiểm tra hàng đợi rỗng

- Insert : Bổ sung 1 ptử vào hàng đợi

- Remove : Loại bỏ 1 ptử khỏi hàng đợi

- QueueFront : Lấy giá trị của nút pFront

- QueueRear : Lấy giá trị của nút pRear

- QueueSize : Đếm số nút của hàng đợi

- Clear : Xóa toàn bộ hàng đợi


41
5.2.3 Các thao tác
 Init – Khởi tạo Queue

void Init(Queue &q)


{
*q.pFront = NULL;
*q.pRear = NULL;
}

42
5.2.3 Các thao tác
 Init – Khởi tạo Queue

int IsEmpty(Queue &q)


{
if ( q.pFront == NULL)
return 1;
else
return 0;
}
43
5.2.3 Các thao tác
 Insert – Bổ sung phần tử vào hàng đợi

pFront pRear

new

5 2 9 x
node

pFront pRear
q.pRear = node

5 2 9 x
q.pRear -> next =node

44
5.2.3 Các thao tác
1. void Insert(Queue &q, int x)
2. { NodePtr node;
3. node = new NODE;
4. node -> info = x;
5. node -> next = NULL;
6. if (q.pRear == NULL)
7. { q.pRear = node;
8. q.pFront = node;
9. }
10. else
11. { q.pRear->next = node;
12. q.pRear = node;
13. }
14.}
45
5.2.3 Các thao tác
 Remove - Loại bỏ một nút khỏi hàng đợi

pFront pRear

5 2 9

pFront pRear

2 9

46
5.2.3 Các thao tác
1. int Remove(Queue &q)
2. { NodePtr p;
3. int value;
4. if (q.pFront == NULL) //hang doi rong
5. return -1;
6. else
7. if (q.pFront == q.pRear) //chi co 1 nut
8. { p = q.pFront;
9. q.pFront = q.pRear = NULL;
10. }
11. else //co nhieu nut
12. { p =q.pFront;
13. q.pFront = p->next; }
14. value = p->info;
15. delete p;
16. return value;
17.}
47
5.2.3 Các thao tác
 QueueSize - Đếm số nút của hàng đợi
1. int QueueSize(Queue &q)
2. { int d = 0; //bien dem d
3. NodePtr p; //con tro de duyet
4. p = q.pFront; //duyet tu dau
5. while (p != NULL)
6. { d++;
7. p = p -> next;
8. }
9. return d;
10.}

48
5.3.2 Các thao tác
 QueueFront – Lấy ra giá trị của nút trỏ bởi pFront
1. int QueueFront(Queue &q)
2. {
3. if (q.pFront == NULL)
4. return -1;
5. else
6. return q.pFront->info;
7. }

49
5.3.2 Các thao tác
 QueueRear – Lấy ra giá trị của nút trỏ bởi pRear
1. int QueueRear(Queue &q)
2. {
3. if (q.pRear == NULL)
4. return -1;
5. else
6. return q.pRear->info;
7. }

50
5.2.3 Các thao tác
 ClearQueue – Xóa hàng đợi
1. void ClearQueue(Queue &q)
2. { NodePtr p;
3. while (q.pFront != NULL)
4. { p = q.pFront;
5. q.pFront = p -> next;
6. delete p;
7. }
8. }

51
5.2.4 Ứng dụng
 Ứng dụng Queue
- Trong bài toán hàng đợi “Vào trước ra trước” FIFO:
 Hệ thống print server
 Cơ chế thông điệp, bộ đệm, hàng đợi xử lý sự kiện…
 Các ứng dụng đặt vé tàu lửa, máy bay…
 Các hệ thống rút tiền…

52
Câu hỏi củng cố bài
1. Thao tác nào dưới đây thực hiện trên ngăn xếp
(stack):
A. Thêm và loại bỏ phần tử luôn thực hiện ở đầu
danh sách

B. Thêm phần tử vào vị trí bất kỳ

C. Loại bỏ phần tử tại vị trí bất kỳ

D. Thêm phần tử luôn thực hiện tại vị trí cuối danh


sách

Cấu trúc dữ liệu -- Khoa


Cấu Khoa CNTT
CNTT1 53
Câu hỏi củng cố bài
2. Thao tác nào dưới đây thực hiện trên hàng đợi
(queue):
A. Thêm và loại bỏ phần tử luôn thực hiện tại lối
trước (đầu danh sách)

B. Thêm phần tử vào vị trí bất kỳ

C. Loại bỏ phần tử tại vị trí bất kỳ

D. Thêm phần tử luôn thực hiện tại lối sau (cuối


danh sách)

Cấu trúc dữ liệu -- Khoa


Cấu Khoa CNTT
CNTT1 54
Câu hỏi củng cố bài
3. Hoạt động của ngăn xếp là ____________ để
thêm một phần vào đỉnh ngăn xếp và __________
để loại bỏ phần tử ở đỉnh ngăn xếp.
A. malloc (), free ()

B. pop (), push ()

C. push (), pop ()

D. new (), delete ()

Cấu trúc dữ liệu -- Khoa


Cấu Khoa CNTT
CNTT1 55
Câu hỏi củng cố bài
4. Cơ chế nào dưới đây được cài đặt cho hàng đợi
A. Cơ chế vào trước ra trước (FIFO)

B. Cơ chế Round Robin

C. Cơ chế tuần tự

D. Cơ chế vào sau ra trước (LIFO)

Cấu trúc dữ liệu -- Khoa


Cấu Khoa CNTT
CNTT1 56
Câu hỏi củng cố bài
5. Cho một hàng đợi lưu trữ dưới dạng một danh
sách liên kết, có một con trỏ trỏ vào lối trước và
một con trỏ trỏ vào lối sau của danh sách. Các
biến con trỏ sẽ thay đổi thế nào khi bổ sung một
phần tử vào một hàng đợi rỗng?
A. Không thay đổi
B. Cả hai thay đổi.
C. Chỉ có con trỏ lối trước thay đổi.
D. Chỉ có con trỏ lối sau thay đổi.
Cấu trúc dữ liệu -- Khoa
Cấu Khoa CNTT
CNTT1 57
Câu hỏi củng cố bài
6. Cho một hàng đợi lưu trữ dưới dạng một danh
sách liên kết, có một con trỏ trỏ vào lối trước và
một con trỏ trỏ vào lối sau của danh sách. Các
biến con trỏ sẽ thay đổi thế nào khi bổ sung một
phần tử vào một hàng đợi không rỗng?
A. Không thay đổi
B. Cả hai thay đổi.
C. Chỉ có con trỏ lối trước thay đổi.
D. Chỉ có con trỏ lối sau thay đổi.
Cấu trúc dữ liệu -- Khoa
Cấu Khoa CNTT
CNTT1 58
Bài tập
1. Cho một danh sách nối kép có nút đầu được trỏ bởi
pHead. Trường info của các nút chứa giá trị nguyên.
Viết giải thuật bổ sung và loại bỏ để danh sách hoạt
động như một Queue.
2. Viết chương trình C++ chứa tất cả các thao tác trên
stack.
3. Viết chương trình C++ chứa tất cả các thao tác trên
queue.

Cấu trúc dữ liệu -- Khoa


Cấu Khoa CNTT
CNTT1 60
Tài liệu tham khảo
[1]. Giáo trình Cấu trúc dữ liệu và giải thuật – Lê Văn
Vinh, NXB Đại học quốc gia TP HCM, 2013
[2]. Cấu trúc dữ liệu & thuật toán, Đỗ Xuân Lôi, NXB
Đại học quốc gia Hà Nội, 2010.
[3]. Trần Thông Quế, Cấu trúc dữ liệu và thuật toán
(phân tích và cài đặt trên C/C++), NXB Thông tin và
truyền thông, 2018
[4]. Robert Sedgewick, Cẩm nang thuật toán, NXB
Khoa học kỹ thuật, 2004 .
[5]. PGS.TS Hoàng Nghĩa Tý, Cấu trúc dữ liệu và
thuật toán, NXB xây dựng, 2014

Cấu trúc dữ liệu -- Khoa


Cấu Khoa CNTT
CNTT1 61
Cấu trúc dữ liệu -- Khoa
Cấu Khoa CNTT
CNTT1 62

You might also like