Giáo trình Cấu trúc dữ liệu và giải thuật - Chương 14: Ứng dụng của ngăn xếp

Trong trường hợp có dấu ngoặc, dấu mở ‘(‘ cần được lưu trong ngăn xếp cho

đến khi gặp dấu đóng ‘)’ tương ứng. Chúng ta quy ước độ ưu tiên của dấu ngoặc mở

thấp nhất là hợp lý. Mọi toán tử xuất hiện sau dấu ngoặc mở đều không thể làm

cho dấu này được lấy ra khỏi ngăn xếp, trừ khi dấu ngoặc đóng tương ứng được

duyệt đến. Khi gặp dấu đóng ‘)’, xem như kết thúc mọi việc tính toán trongcặp

dấu (), mọi toán tử còn nằm trên dấu mở ‘(‘ trong ngăn xếp đều được lấy ra để đưa

vào biểu thức dạng postfix. Do các dấu ngoặc không bao giờ xuất hiện trong biểu

thức postfix, dấu ‘(‘ được đặt vào ngăn xếp để chờ dấu ‘)’ tương ứng, khi nó được

lấy ra thì sẽ bị vất bỏ. Dấu ‘)’ để giải quyết cho dấu ‘(‘, và cũng sẽ bị vất đi.

Các toán tử +, -, *, / đều là các toán tử kết hợp từ trái sang phải. Biểu thức

a - b - c ( được hiểu là (a-b)-c ) được chuyển đổi thành a b - c - (không phải a b

c - - ). Với một số toán tử kết hợp từ phải sang trái, chẳng hạn phép tính lũy thừa

thì 2^2^3 = 2^(2^3)= 2^8=256, không phải (2^2)^3= 4^3=64, thì các xử lý trên

cần được sửa đổi cho hợp lý. Chương trình hoàn chỉnh chuyển đổi biểu thức dang

infix sang biểu thức dạng postfix, cũng như việc xử lý đặc biệt cho trường hợp

toán tử kết hợp phải được xem như bài tập.

 

pdf12 trang | Chuyên mục: Cấu Trúc Dữ Liệu & Giải Thuật | Chia sẻ: tuando | Lượt xem: 709 | Lượt tải: 0download
Tóm tắt nội dung Giáo trình Cấu trúc dữ liệu và giải thuật - Chương 14: Ứng dụng của ngăn xếp, để xem tài liệu hoàn chỉnh bạn click vào nút "TẢI VỀ" ở trên
iệc tính toán trongcặp 
dấu (), mọi toán tử còn nằm trên dấu mở ‘(‘ trong ngăn xếp đều được lấy ra để đưa 
vào biểu thức dạng postfix. Do các dấu ngoặc không bao giờ xuất hiện trong biểu 
thức postfix, dấu ‘(‘ được đặt vào ngăn xếp để chờ dấu ‘)’ tương ứng, khi nó được 
lấy ra thì sẽ bị vất bỏ. Dấu ‘)’ để giải quyết cho dấu ‘(‘, và cũng sẽ bị vất đi. 
Các toán tử +, -, *, / đều là các toán tử kết hợp từ trái sang phải. Biểu thức 
a - b - c ( được hiểu là (a-b)-c ) được chuyển đổi thành a b - c - (không phải a b 
c - - ). Với một số toán tử kết hợp từ phải sang trái, chẳng hạn phép tính lũy thừa 
thì 2^2^3 = 2^(2^3)= 2^8=256, không phải (2^2)^3= 4^3=64, thì các xử lý trên 
cần được sửa đổi cho hợp lý. Chương trình hoàn chỉnh chuyển đổi biểu thức dang 
infix sang biểu thức dạng postfix, cũng như việc xử lý đặc biệt cho trường hợp 
toán tử kết hợp phải được xem như bài tập. 
14.4. Giải thuật quay lui (backtracking) 
Ngăn xếp còn được sử dụng trong các giải thuật quay lui nhằm lưu lại các 
thông tin đã từng duyệt qua để có thể quay ngược trở lại. Chúng ta sẽ xem xét các 
ví dụ sau đây. 
14.4.1. Ứng dụng trong bài toán tìm đích (goal seeking). 
Hình 14.1 minh họa cho bài toán tìm đích. Chúng ta có một nút bắt đầu và 
một nút gọi là đích đến. Để đơn giản, chúng ta xét đồ thị không có chu trình và 
chỉ có duy nhất một đường đi từ nơi bắt đầu đến đích. Nhìn hình vẽ chúng ta có 
thể nhận ra ngay đường đi này. Tuy nhiên máy tính cần một giải thuật thích 
hợp để tìm ra được con đường này. 
Chúng ta bắt đầu từ nút 1, sang nút 2 và nút 3. Tại nút 3 có 2 ngã rẽ, giả sử 
chúng ta đi theo đường trên, đến nút 4 và nút 5. Tại nút 5 chúng ta lại đi theo 
đường trên đến nút 6 và nút 7. Đến đây chúng ta không còn đường đi tiếp và cũng 
chưa tìm được đích cần đến, chúng ta phải quay trở lại nút 5 để chọn lối đi khác. 
Tại nút 8 chúng ta lại phải quay lại nút 5 để đi sang nút 9,. Bằng cách này, từ 
nút 13, khi chúng ta tìm được nút 16 thì chúng ta không cần phải quay lui để thử 
với nút 17, 18 nữa. Giải thuật kết thúc khi tìm thấy đích đến. 
Giải thuật của chúng ta cần lưu các nút để quay lại. So sánh nút 3 và nút 5, 
chúng ta thấy rằng trên đường đi chúng ta gặp nút 3 trước, nhưng diểm quay về 
để thử trước lại là nút 5. Do đó cấu trúc dữ liệu thích hợp chính là ngăn xếp với 
Chương 14 – Ứng dụng của ngăn xếp 
Giáo trình Cấu trúc dữ liệu và Giải thuật 373
nguyên tắc FILO của nó. Ngoài ra nếu chúng ta lưu nút 3 và nút 5 thì có sự bất 
tiện ở chỗ là khi quay về, thông tin lấy từ ngăn xếp không cho chúng ta biết các 
nhánh nào đã được duyệt qua và các nhánh nào cần tiếp tục duyệt. Do đó, tại nút 
3, trước khi đi sang 4, chúng ta lưu nút 12, tại nút 5, trước khi đi sang 6 chúng ta 
lưu nút 8 và nút 9, 
Với giải thuật trên chúng ta có thể tìm đến đích một cách dễ dàng. Tuy nhiên, 
nếu bài toán yêu cầu in ra các nút trên đường đi từ nút bắt đầu đến đích thì 
chúng ta chưa làm được. Như vậy chúng ta cũng cần phải lưu cả các nút trên 
đường mà chúng ta đã đi qua. Những nút nằm trên những đoạn đường không dẫn 
đến đích sẽ được dỡ bỏ khỏi ngăn xếp khi chúng ta quay lui. Ở đây chúng ta gặp 
phải một vấn đề cũng tương đối phổ biến trong một số bài toán khác, đó là những 
gì chúng ta bỏ vào ngăn xếp không có cùng mục đích. Có hai nhóm thông tin khác 
nhau: một là các nút nằm trên đường đang đi qua, hai là các nút nằm trên các 
nhánh rẽ khác mà chúng ta sẽ lần lượt thử tiếp khi gặp thất bại trên con đường 
đang đi. Trong những trường hợp như vậy, việc giải quyết rất là dễ dàng: chúng 
ta dùng cách đánh dấu để phân biệt từng trường hợp, khi lấy ra khỏi ngăn xếp, 
căn cứ vào cách đánh dấu này chúng ta sẽ biết phải xử lý như thế nào cho thích 
hợp (Việc duyệt cây theo thứ tự LRN trong chương 10 nếu dùng ngăn xếp cũng là 
một ví dụ). Trong hình 14.1, ký tự B trong ngăn xếp cho biết đó là những nút 
dành cho việc quay lui (Backtracking) để thử với nhánh khác. Vậy khi gặp điểm 
cuối của một con đường không dẫn đến đích, chúng ta dỡ bỏ khỏi ngăn xếp các 
nút cho đến khi gặp một nút có ký tự ‘B’, bỏ lại nút này vào ngăn xếp (không còn 
ký tự ‘B’), và đi tiếp các nút kế tiếp theo nút này. Cuối cùng khi gặp đích, con 
đường được tìm thấy chính là các nút đang lưu trong ngăn xếp mà không có ký tự 
‘B’ ở đầu. 
Hình 14.1- Ví dụ và ngăn xếp minh họa quá trình backtracking. 
 Start node 
The goal2 3 1 
4 5 
6
8
9 10 11
16 1514 13 12 
17 18
7
 end 
 7 end goal
 6 end 11 16 
 B8 B8 8 10 15 
 B9 B9 B9 9 14 
 5 5 5 5 B17
 4 4 4 4 13 
B12 B12 B12 B12 B12 12 
3 3 3 3 3 3 
2 2 2 2 2 2 
1 1 1 1 1 1 
(a) (b) (c) (d) (e) (f)
Chương 14 – Ứng dụng của ngăn xếp 
Giáo trình Cấu trúc dữ liệu và Giải thuật 374
Trên đây là mã giả cho bài toán tìm đích, cấu trúc dữ liệu để chứa đồ thị 
chúng ta sẽ được tìm hiểu sau trong chương 13. 
Algorithm seek_goal(val graph_type graph, val node_type start, 
val node_type goal) 
/* 
pre: graph chứa đồ thị không có chu trình, trong đó có một nút start và một nút goal. 
post: nếu đường đi từ start đến goal được tìm thấy sẽ được in ra theo thứ tự từ goal ngược 
về start 
*/ 
{ 
1. Stack nodes. // node_type là kiểu dữ liệu thích hợp. 
2. node_type current_node = start 
3. boolean fail = FALSE 
4. loop ((current_node chưa là goal) AND (!fail)) 
1. nodes.push(current_node) 
2. if (current_node là điểm rẽ nhánh) 
1. next_node = nút rẽ vào 1 nhánh 
2. loop (còn nhánh chưa đưa vào ngăn xếp) // đưa các nhánh 
// còn lại vào ngăn xếp. 
1. nodes.push(nút rẽ vào 1 nhánh, có kèm ‘B’) 
3. endloop 
3. else 
1. if (tồn tại nút kế) 
1. next_node = nút kế 
2. else 
1. repeat 
1. if (nodes.empty()) 
1. fail = TRUE 
2. else 
1. nodes.top(next_node) 
2. nodes.pop() 
3. endif 
2. until ((fail) OR (next_node có ‘B’)) 
3. endif 
4. endif 
5. current_node = next_node 
5. endloop 
6. if (!fail) 
1. print(“The path to your goal is:”) 
2. print(current_node) // chính là goal 
3. loop (!nodes.empty()) 
1. nodes.top(current_node) 
2. nodes.pop() 
3. if (current_node không có ký tự ‘B’) 
1. print(current_node) 
4. endif 
4. endloop 
7. else 
1. print(“Path not found!”) 
8. endif 
} 
Chương 14 – Ứng dụng của ngăn xếp 
Giáo trình Cấu trúc dữ liệu và Giải thuật 375
14.4.2. Bài toán mã đi tuần và bài toán tám con hậu 
Ví dụ tiếp theo liên quan đến bài toán mã đi tuần. Thực ra bài toán tám con 
hậu được trình bày trong chương 6 cũng hoàn toàn tương tự. Sinh viên có thể 
tham khảo ý tưởng được trình bày dưới đây để giải bài toán tám con hậu sử dụng 
ngăn xếp thay vì đệ quy. 
Với bàn cờ 64 ô, bài toán mã đi tuần yêu cầu chúng ta chỉ ra đường đi cho con 
mã bắt đầu từ một ô nào đó, lần lượt đi qua tất cả các ô, mà không có ô nào lập 
lại hơn một lần. 
Từ một vị trí, con mã có tối đa là 8 vị trí chung quanh có thể đi được. Giải 
thuật quay lui rất gần với hướng suy nghĩ tự nhiên của chúng ta. Trong các khả 
năng có thể, chúng ta thường chọn ngẫu nhiên một khả năng để đi. Và với vị trí 
mới chúng ta cũng làm điều tương tự. Mỗi ô đi qua chúng ta đánh dấu lại. Trong 
quá trình thử này, nếu có lúc không còn khả năng lựa chọn nào khác vì các ô nằm 
trong khả năng đi tiếp đều đã được đánh dấu, chúng ta cần phải lùi lại để thử 
những khả năng khác. Thay vì biểu diễn đường đi cho con mã trên bàn cờ (hình 
14.2a), chúng ta vẽ lại các khả năng đi và thấy chúng không khác gì so với bài 
toán tìm đích (hình 14.2b). Và như vậy, chúng ta thấy cách sử dụng ngăn xếp 
trong những bài toán dạng này hoàn toàn đơn giản và tương tự. Phương pháp 
quay lui trong trường hợp này đôi khi còn được gọi là phương pháp thử sai (trial 
and error method). 
 1 2 3 4 5 6 7 8
1 
2 
3 
4 
5 
6 
7 
8 
 (a) (b) 
Hình 14.2- Bài toán mã đi tuần. 
Hình trên đây minh họa bài toán mã đi tuần với điểm bắt đầu là (7,2). Đích 
đến không cụ thể như bài toán trên, mà đường đi cần tìm chính là đường đi nào 
trong đồ thị này có đủ 64 nút. Bài toán này phụ thuộc vào số ô của bàn cờ và vị 
(7,2)
(5,1)
(8,4)
(5,3)
(4,3) 
(3,2) 
(6,3) 
(3,2) 
(4,1) 
(3,4) 
(4,5) 
(6,5) 
(4,1) 
(7,4) 
Chương 14 – Ứng dụng của ngăn xếp 
Giáo trình Cấu trúc dữ liệu và Giải thuật 376
trí bắt đầu của con mã, khả năng có lời giải và có bao nhiêu lời giải chúng ta 
không xem xét ở đây. Chúng ta chỉ quan tâm đến cách sử dụng ngăn xếp trong 
những bài toán tương tự. Bản chất những bài này đều có cùng một đặc trưng của 
bài toán tìm đích trên một đồ thị không có chu trình. Đích đến có thể là nhiều 
hơn một (tương ứng với nhiều lời giải được tìm thấy) như trong bài toán tám con 
hậu mà cách giải đệ quy được trình bày trong chương 6. Sự khác nhau cơ bản giữa 
chúng chỉ là một vài kỹ thuật nho nhỏ dùng để chuyển từ dữ liệu ban đầu của bài 
toán sang dạng đồ thị biểu diễn các khả năng di chuyển trong quá trình tìm đến 
đích mà thôi. 

File đính kèm:

  • pdfgiao_trinh_cau_truc_du_lieu_va_giai_thuat_chuong_14_ung_dung.pdf