Cấu trúc dữ liệu và giải thuật_ Bài tập lớn

Chia sẻ: thocon_carot

*ADT (Abstract Data Types) – kiểu dữ liệu trừu tượng bao gồm: Tập các giá trị (đối tượng) Tập các phép toán có thể thực hiện với tất cả các giá trị này Cách biểu diễn dữ liệu được sử dụng chung cho tất cả các giá trị này *Stack (ngăn xếp): là một kiểu dữ liệu trừu tượng, một dạng đặc biệt của danh sách tuyến tính (dãy gồm 0 hoặc nhiều hơn các phần tử cùng kiểu cho trước) trong đó các đối tượng được nạp vào (push) và lấy ra (pop) chỉ từ một đầu gọi là đỉnh (top) của danh sách....

Nội dung Text: Cấu trúc dữ liệu và giải thuật_ Bài tập lớn

Cấu trúc dữ liệu và giải thuật ADT Stack


Bài tập lớn

CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT
Đề tài: ADT Stacks [Ngăn xếp]

-o0o-
Mai Xuân Cường - Nguyễn Trung Dũng A - Hoàng Mạnh Hùng
Nguyễn Thị Thu Nga - Vũ Thị Quỳnh Trang - Ngô Anh Tuấn - Nguyễn Tuấn
***
I. Định nghĩa:
*ADT (Abstract Data Types) – kiểu dữ liệu trừu tượng bao gồm:
­ Tập các giá trị (đối tượng)
­ Tập các phép toán có thể thực hiện với tất cả các giá trị này
­ Cách biểu diễn dữ liệu được sử dụng chung cho tất cả các giá trị này
*Stack (ngăn xếp): là một kiểu dữ liệu trừu tượng, một dạng đặc biệt của danh sách tuyến tính 
(dãy gồm 0 hoặc nhiều hơn các phần tử cùng kiểu cho trước) trong đó các đối tượng được nạp 
vào (push) và lấy ra (pop) chỉ từ một đầu gọi là đỉnh (top) của danh sách.
 nguyên tắc: vào sau ra trước (LIFO – last in first out)
­  Đối tượng cất giữ:  các phần tử ­ số (nguyên, thực), ký tự, xâu 
(string), mảng (array), bản ghi (record), file...
­ Các phép toán cơ bản: 
+ push  đẩy phần tử vào ngăn xếp
+ pop  lấy phần tử ra khỏi ngăn xếp
+ isEmpty  kiểm tra ngăn xếp rỗng
+ size  trả về số phần tử của ngăn xếp
+ top  trả về giá trị của phần tử nằm ở đầu danh sách mà không lấy nó ra khỏi ngăn xếp
II. Cài đặt:
1­ Các cấu trúc dữ liệu để biểu diễn và cài đặt các phép toán:
a) Mảng:
+ nạp các phần tử theo thứ tự từ trái sang phải
+ có biến lưu trữ chỉ số của phần tử ở đầu ngăn xếp

Stack 3 5 2 …… 6 7
0 1 2 …. n maxn


+ trong đó:
maxn _ số phần tử tối đa xin cấp phát của ngăn xếp
n _ biến dùng để lưu trữ chỉ số phần tử ở đầu ngăn xếp
+ một hạn chế của việc sử dụng mảng là phải khai báo kích thước tối đa để dự phòng nên gây 
lãng phí bộ nhớ hoặc phải thông báo tràn bộ nhớ (Full Stack) khi thực hiện thao tác push
b) Danh sách móc nối (con trỏ):



1
Cấu trúc dữ liệu và giải thuật ADT Stack


+ mỗi nút bao gồm 2 thành phần cơ bản:  elements  để lưu trữ nội dung dữ liệu của phần tử, 
*next là con trỏ đến nút tiếp theo trong ngăn xếp
+ thao tác bố sung và loại bỏ luôn làm việc ở nút đầu tiên thông qua việc sử dụng một con trỏ 
*top trỏ đến nút đầu tiên trong ngăn xếp
+ việc sử dụng danh sách móc nối (hay con trỏ) có một ưu điểm là không phải khai báo số phần 
tử tối đa của ngăn xếp để dự phòng từ đó có thể tiết kiệm được bộ nhớ không cần thiết.


7 54 ……. 93 5 NULL
*top elements *next


2­ Chương trình minh họa:  file: StackPtr.cpp, STACKARR.cpp
III. Ứng dụng:
1­ Phát biểu bài toán:
*Tính giá trị biểu thức số học:
Biểu thức số học xuất hiện rất nhiều trong cuộc sống và việc tính toán giá trị của các biểu thức 
đó là điều tất yếu, quan trọng. Ví dụ: 
­ Khi sử dụng máy tính (calculator), người dùng sẽ nhập các biểu thức số học cần tính thông 
qua các phím số và phép toán có sẵn. Nhiệm vụ của máy sẽ tính toán và hiển thị kết quả chính 
xác ra màn hình.
­ Khi sử dụng các bảng tính điện tử (như Excel, …) để lập các bảng tính lương, thống kê việc thu 
chi của doanh nghiệp…, người dùng sẽ nhập các biểu thức số học vào các ô tính. Khi đó, chương 
trình sẽ có nhiệm vụ phân tích và tính toán rồi đưa ra kết quả tại ô đó.
­ Hay trong các ngôn ngữ lập trình (như C, PASCAL…), ta đã khá quen thuộc với các lệnh gán
X= //X là biến
Khi thực hiện chương trình, gặp các lệnh gán, máy tính cần phải xác định giá trị của các biểu 
thức số học đó và gán kết quả cho biến X. 
Vì vậy, việc xây dựng một chương trình tính toán giá trị của các biểu thức số học là cần thiết.
Biểu thức số học là một dãy các toán hạng (hằng (số), biến hoặc hàm) nối với nhau bởi các 
phép toán số học (như cộng, trừ, nhân, chia, lũy thừa, căn thức,...). Trong các biểu thức có thể 
chứa các dấu ngoặc tròn để xác định thứ tự ưu tiên. Khi đó các phép toán trong ngoặc sẽ được 
thực hiện trước các phép toán ở ngoài.
Các phép toán số học được phân ra làm 2 loại:
­ Các phép toán hai ngôi (+, ­, *, /, ^,…): mỗi phép toán được đặt giữa các toán hạng. Ví dụ: 
2+3, 56*12, 3^8,…
­ Các phép toán một ngôi (căn, logarit, các hàm lượng giác: sin, cos, tg,…): mỗi phép toán đi 
ngay trước toán hạng. Ví dụ: sin4, ln7,…
Hơn nữa, khi tính các biểu thức số học, ta cần phải tuân theo những quy tắc sau:
­ Thứ tự ưu tiên: ^  *, /  +, ­
­ Quy tắc kết hợp: cho biết khi có 2 phép toán có cùng thứ tự ưu tiên thì sẽ thực hiện phép toán 
nào trước.
+ ^: thực hiện từ phải qua trái.
+ + ­ * /: thực hiện từ trái qua phải.


2
Cấu trúc dữ liệu và giải thuật ADT Stack


+ dấu () được ưu tiên hơn cả thứ tự ưu tiên và quy tắc kết hợp.
2­ Mô tả thuật toán giải và đánh giá độ phức tạp của thuật toán:
a) Mô tả thuật toán giải:
Bài toán tính toán giá trị của biểu thức số học được xây dựng một cách dễ dàng bằng thuật toán 
Ba Lan trên cơ sở ứng dụng của kiểu dữ liệu trừu tượng ngăn xếp (stack).
*Ký pháp nghịch đảo Ba Lan:
Ký pháp nghịch đảo Ba Lan được phát minh vào khoảng giữa thập kỷ 1950 bởi Charles Hamblin 
­ một triết học gia và khoa học gia máy tính người Úc ­ dựa theo công trình về ký pháp Ba Lan 
của nhà Toán học người Ba Lan Jan Łukasiewicz. Hamblin trình bày nghiên cứu của mình tại một 
hội nghị khoa học vào tháng 6 năm 1957 và chính thức công bố vào năm 1962.
Từ cái tên hậu tố cũng có thể đoán ra phần nào là theo cách biểu diễn này, các toán tử sẽ được 
đặt sau các toán hạng. Cụ thể là biểu thức trung tố: 4+5 sẽ được biểu diễn lại thành 4 5 +. 
Ý tưởng là đọc biểu thức từ trái sang phải, nếu gặp một toán hạng (con số hoặc biến) thì push 
toán hạng này vào ngăn xếp; nếu gặp toán tử, lấy hai toán hạng ra khỏi ngăn xếp (stack), tính kết 
quả, đẩy kết quả trở lại ngăn xếp. Khi quá trình kết thúc thì con số cuối cùng còn lại trong ngăn 
xếp chính là giá trị của biểu thức đó. 
Ví dụ:  biểu thức trung tố : 
5 + ((1 + 2) * 4) + 3
được biểu diễn lại dưới dạng hậu tố là (ta sẽ bàn về thuật toán chuyển đổi từ trung tố sang hậu 
tố sau): 
5 1 2 + 4 * + 3 +
Quá trình tính toán sẽ diễn ra theo như bảng dưới đây: 


Ký tự Thao tác Trạng thái stack
5 Push 5 5
1 Push 1 5, 1
2 Push 2 5, 1, 2
+ Tính 1 + 2  5, 3

Push 3
4 Push 4 5, 3, 4
* Tính 3 * 4 5, 12

Push 12
+ Tính 12 + 5  17

Push 17
3 Push 3 17, 3
+ Tính 17 + 3 20

Push 20


Chuyển đổi từ trung tố sang hậu tố:

3
Cấu trúc dữ liệu và giải thuật ADT Stack


Thuật toán chuyển đổi này được phát minh bởi vị giáo sư người Đức nổi tiếng Edsger Dijkstra 
(cũng là tác giả của thuật toán tìm đường đi ngắn nhất được đặt theo tên ông và semaphore, một 
kỹ thuật để đồng bộ các tiến trình trong lập trình đa nhiệm). Thuật toán này cũng dựa theo cơ chế 
ngăn xếp. Ý tưởng chung của thuật toán cũng là duyệt biểu thức từ trái sang phải:
­ Nếu gặp một toán hạng (con số hoặc biến) thì ghi nó vào chuỗi kết quả (chuỗi kết quả là biểu 
thức trung tố).
­ Nếu gặp dấu mở ngoặc, đưa nó vào stack.
­ Nếu gặp một toán tử (gọi là o1 ), thực hiện hai bước sau:
+ Chừng nào còn có một toán tử o2 ở đỉnh ngăn xếp VÀ độ ưu tiên của o1 nhỏ hơn hay bằng độ 
ưu tiên của o2 thì lấy o2 ra khỏi ngăn xếp và ghi vào kết quả.
+ Push o1 vào ngăn xếp
­ Nếu gặp dấu đóng ngoặc thì cứ lấy các toán tử trong ngăn xếp ra và ghi vào kết quả cho đến 
khi lấy được dấu mở ngoặc ra khỏi ngăn xếp.
­ Khi đã duyệt hết biểu thức trung tố, lần lượt lấy tất cả toán hạng (nếu có) từ ngăn xếp ra và ghi 
vào chuỗi kết quả.
Để dễ hiểu, bạn hãy quan sát quá trình thực thi của thuật toán qua một ví dụ cụ thể sau:
Biểu thức cần chuyển đổi: 3+4*2/(1­5)
Ký tự Thao tác Stack Chuỗi hậu tố
3 Ghi 3 vào k.quả   3
+ Push + +  
4 Ghi 4 vào k.quả   3 4
* Push * + *   
2 Ghi 2 vào kquả   3 4 2
/ Lấy * ra khỏi stack, ghi vào  +  / 3 4 2 *
k.quả, push /
( Push (  + / ( 3 4 2 *
1 Ghi 1 vào k.quả + / (  3 4 2 * 1
­ Push ­ + / ( ­  3 4 2 * 1
5 Ghi 5 vào k.quả  + / ( ­  3 4 2 * 1 5
) Pop cho đến khi lấy được (, ghi  + /  3 4 2 * 1 5 ­
các toán tử pop được ra k.quả 
2 Ghi 2 ra k.quả  + /  3 4 2 * 1 5 – 2
  Pop tất cả các toán tử ra khỏi    3 4 2 * 1 5 – 2  / +
ngăn xếp và ghi vào kết quả


b) Đánh giá độ phức tạp của thuật toán:
Giả sử xâu biểu thức dạng trung tố đầu vào có độ dài là n
Gọi thời gian tính của thuật toán là O(f(n)), 
­ thời gian tính của hàm convert (char *input, char *output) chuyển đổi xâu biểu thức đầu vào 
từ dạng trung tố sang hậu tố là O(g(n)), 
­ thời gian tính của hàm tinhtoan (char *bieuthuc) tính toán giá trị của biểu thức dạng hậu tố là 
O(h(n)).


4
Cấu trúc dữ liệu và giải thuật ADT Stack


Ta  có:  thời gian  cài đặt  và  thực hiện  các  phép  toán  cơ  bản trên stack  như  Push(),   Pop(),  
Is_Empty(), … là hằng số  O(1).
Vậy ta có thời gian tính của thuật toán là:
O(f(n)) = max {O(g(n)), O(h(n))}
 
* Đánh giá độ phức tạp của hàm convert(char *input, char *output)     tính O(g(n))
    
­ Chuyển xâu biểu thức đầu vào sang chữ thường strlwr(input) thời gian tính là O(n);
­ Duyệt toàn bộ xâu:
while(input[i]!=’\0’) 
{
while(input[i]==””) // loại bỏ dấu “ ”;
{
// câu lệnh hoặc khối câu lệnh với thời gian O(1);
i++;
}
if(((input[i]>='0')&&(input[i]='0')&&(input[i]
Đề thi vào lớp 10 môn Toán |  Đáp án đề thi tốt nghiệp |  Đề thi Đại học |  Đề thi thử đại học môn Hóa |  Mẫu đơn xin việc |  Bài tiểu luận mẫu |  Ôn thi cao học 2014 |  Nghiên cứu khoa học |  Lập kế hoạch kinh doanh |  Bảng cân đối kế toán |  Đề thi chứng chỉ Tin học |  Tư tưởng Hồ Chí Minh |  Đề thi chứng chỉ Tiếng anh
Theo dõi chúng tôi
Đồng bộ tài khoản