Các hoạt động cơ bản trên cấu trúc dữ liệu ngăn xếp...8Chương III: ỨNG DỤNG STACK ĐỂ CHUYỂN BIỂU THỨC TỪ DẠNG TRUNG TỐ SANG HẬU TỐ.... Xây dựng phép dịch biểu thức trung tố sang dạng hậu
Trang 1TRƯỜNG ĐẠI HỌC KINH TẾ QUỐC DÂN VIỆN CÔNG NGHỆ THÔNG TIN – KINH TẾ
****************************
BÀI TẬP LỚN NGUYÊN LÝ NGÔN NGỮ LẬP TRÌNH
Đề tài: Nghiên cứu cài đặt chương trình chuyển một biểu thức
ở dạng trung tố sang dạng ký pháp hậu tố (Ký pháp đảo Ba Lan)
Họ và tên: Trần Quang Khải
Mã sinh viên: 11146120
Lớp tín chỉ: Nguyên lý ngôn ngữ lập trình(216)_1
Hà Nội, Năm 2017
Báo cáo thực tập tổng hợp
Trang 2MỤC LỤC
LỜI MỞ ĐẦU 3
NỘI DUNG 4
Chương I: CƠ SỞ LÝ THUYẾT VỀ KÝ PHÁP BA LAN 4
1.1 Ký pháp Ba Lan 4
1.2 Ký pháp nghịch đảo Ba Lan 5
1.3 Các phương pháp biểu diễn phép toán hai ngôi 5
Chương II: CẤU TRÚC DỮ LIỆU NGĂN XẾP (STACK) 7
2.1 Giới thiệu Ngăn xếp (Stack) 7
2.2 Biểu diễn cấu trúc dữ liệu ngăn xếp (Stack) 7
2.3 Các hoạt động cơ bản trên cấu trúc dữ liệu ngăn xếp 8
Chương III: ỨNG DỤNG STACK ĐỂ CHUYỂN BIỂU THỨC TỪ DẠNG TRUNG TỐ SANG HẬU TỐ 9
3.1 Xây dựng phép dịch biểu thức trung tố sang dạng hậu tố 9
3.2 Giải thuật dịch biểu thức dạng ký pháp trung tố sang biểu thức dạng ký pháp hậu tố 9
Chương IV: CÀI ĐẶT CHƯƠNG TRÌNH TRÊN NGÔN NGỮ LẬP TRÌNH C 12
4.1 Định hình 12
4.2 Viết chương trình 12
4.3 Test chương trình 14
KẾT LUẬN 16
Tài liệu tham khảo: 17
Báo cáo thực tập tổng hợp
Trang 3LỜI MỞ ĐẦU
Ký pháp Ba lan (Polish notation), còn gọi là ký pháp tiền tố (Prefix notation), là một cách viết một biểu thức đại số rất thuận lợi cho việc thực hiện các phép toán Đặc điểm cơ bản của cách viết này là không cần dùng đến các dấu ngoặc và luôn thực hiện
từ trái sang phải
Mục đích của đề tài là nhằm giới thiệu cơ sở lý thuyết về ký pháp nghịch đảo Ba Lan, thuật toán chuyển một biểu thức từ dạng trung tố sang hậu tố và cài đặt chương trình trên ngôn ngữ lập trình C
Chương 1: Cơ sở lý thuyết về ký pháp Ba Lan
Chương 2: Cấu trúc dữ liệu Ngăn xếp (Stack)
Chương 3: Ứng dụng Stack để chuyển biểu thức từ dạng trung tố sang hậu tố Chương 4: Cài đặt chương trình trên ngôn ngữ lập trình C
Báo cáo thực tập tổng hợp
Trang 4NỘI DUNG
Chương I: CƠ SỞ LÝ THUYẾT VỀ KÝ PHÁP BA LAN
1.1 Ký pháp Ba Lan
Ký pháp Ba lan (tiếng Anh: Polish notation), còn gọi là ký pháp tiền tố (tiếng Anh: prefix notation), là một cách viết một biểu thức đại số rất thuận lợi cho việc thực hiện các phép toán Đặc điểm cơ bản của cách viết này là không cần dùng đến các dấu ngoặc và luôn thực hiện từ trái sang phải
Kí pháp Ba Lan do nhà logic toán Jan Łukasiewicz đề xuất khoảng năm 1920 Jan Łukasiewicz là một nhà toán học người Ba Lan Ông sinh ra ở Lwów, Galicia (nay là Lviv, Ukraina) Lĩnh vực nghiên cứu chính của ông là logic toán
Khi lập trình, tính giá trị một biểu thức toán học là điều quá đỗi bình thường Tuy nhiên, trong nhiều ứng dụng (như chương trình vẽ đồ thị hàm số chẳng hạn, trong
đó chương trình cho phép người dùng nhập vào hàm số), ta cần phải tính giá trị của một biểu thức được nhập vào từ bàn phím dưới dạng một chuỗi Với các biểu thức toán học đơn giản (như a+b) thì bạn có thể tự làm bằng các phương pháp tách chuỗi “thủ công” Nhưng để “giải quyết” các biểu thức có dấu ngoặc, ví dụ như (a+b)*c + (d+e)*f , thì các phương pháp tách chuỗi đơn giản đều không khả thi Trong tình huống này, ta phải dùng đến Ký Pháp Nghịch Đảo Ba Lan (Reserve Polish Notation – RPN), một thuật toán “kinh điển” trong lĩnh vực trình biên dịch
Jan Łukasiewicz
Báo cáo thực tập tổng hợp
Trang 51.2 Ký pháp nghịch đảo Ba Lan
Cách trình bày biểu thức theo cách thông thường tuy tự nhiên với con người nhưng lại khá “khó chịu” đối với máy tính vì nó không thể hiện một cách tường minh quá trình tính toán để đưa ra giá trị của biểu thức Để đơn giản hóa quá trình tính toán này, ta phải biến đổi lại biểu thức thông thường về dạng hậu tố - postfix (cách gọi ngắn của thuật ngữ ký pháp nghịch đảo Ba Lan) Để phân biệt hai dạng biểu diễn biểu thức,
ta gọi cách biểu diễn biểu thức theo cách thông thường là trung tố - infix (vì toán tử nằm ở giữa hai toán hạng)
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
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 +
Quá trình tính toán giá trị của biểu thức hậu tố khá tự nhiên đối với máy tính
1.3 Các phương pháp biểu diễn phép toán hai ngôi
Một phép toán hai ngôi trên tập hợp X là một ánh xạ f: X×X→X cho
Ánh xạ f khi đó thường được ký hiệu bởi *, được gọi là toán tử, các phần tử a, b được gọi là các hạng tử (còn gọi là toán hạng)
Biểu thức trung tố hiểu đơn giản tức là toán tử sẽ được đặt giữa hai toán hạng,
dĩ nhiên đây phải là toán tử hai ngôi Vậy dựa vào vị trí của của toán tử, liệu ta có thể biểu diễn biểu thức đại số dưới dạng khác? Câu trả lời là được, và như đã nói, ta có ba cách là biểu thức tiền tố (prefix), trung tố (infix) và hậu tố (postfix)
Prefix: Biểu thức tiền tố được biểu diễn bằng cách đặt toán tử lên trước các toán hạng Cách biểu diễn này còn được biết đến với tên gọi “ký pháp Ba Lan” do nhà toán học Ba Lan Jan Łukasiewicz phát minh năm 1920 Với cách biểu diễn này, thay vì viết x+y như dạng trung tố, ta sẽ viết +xy Tùy theo độ ưu tiên của toán tử mà chúng sẽ được sắp xếp khác nhau, bạn có thể xem một số ví dụ ở phía sau phần giới thiệu này
Postfix: Ngược lại với cách Prefix, tức là các toán tử sẽ được đặt sau các toán hạng Cách biểu diễn này được gọi là “ký pháp nghịch đảo Ba Lan” hoặc được viết tắt là RPN (Reverse Polish notation), được phát minh vào khoảng giữa thập kỷ 1950 bởi một triết học gia và nhà khoa học máy tính Charles Hamblin người Úc
Báo cáo thực tập tổng hợp
Trang 6Về lý thuyết, ký pháp tiền tố và ký pháp hậu tố còn có thể được mở rộng cho các phép toán ba ngôi hoặc nhiều hơn mà vẫn không phải dùng tới dấu ngoặc để thể hiện
độ ưu tiên các phép toán, tương tự với hàm số đa biến, còn ký pháp trung tố thì không thể Tuy nhiên, trong thực tế không có nhiều phép toán đa ngôi và ký pháp trung tố vẫn được dùng rộng rãi vì thói quen
Một số ví dụ:
Báo cáo thực tập tổng hợp
Trang 7Chương II: CẤU TRÚC DỮ LIỆU NGĂN XẾP (STACK)
2.1 Giới thiệu Ngăn xếp (Stack)
Một ngăn xếp là một cấu trúc dữ liệu trừu tượng, hầu như được sử dụng trong hầu hết mọi ngôn ngữ lập trình Đặt tên là ngăn xếp bởi vì nó hoạt động như một ngăn xếp trong đời sống thực, ví dụ như một cỗ bài hay một chồng đĩa, …
Trong đời sống thực, ngăn xếp chỉ cho phép các hoạt động tại vị trí trên cùng của ngăn xếp Ví dụ, chúng ta chỉ có thể đặt hoặc thêm một lá bài hay một cái đĩa vào trên cùng của ngăn xếp Do đó, cấu trúc dữ liệu trừu tượng ngăn xếp chỉ cho phép các thao tác dữ liệu tại vị trí trên cùng Tại bất cứ thời điểm nào, chúng ta chỉ có thể truy cập phần tử trên cùng của ngăn xếp
Đặc điểm này làm cho ngăn xếp trở thành cấu trúc dữ liệu dạng LIFO LIFO là viết tắt của Last-In-First-Out Ở đây, phần tử được đặt vào (được chèn, được thêm vào) cuối cùng sẽ được truy cập đầu tiên Trong thuật ngữ ngăn xếp, hoạt động chèn được gọi là hoạt động PUSH và hoạt động xóa được gọi là hoạt động POP
2.2 Biểu diễn cấu trúc dữ liệu ngăn xếp (Stack)
Sơ đồ minh họa một ngăn xếp và các hoạt động diễn ra trên ngăn xếp
Một ngăn xếp có thể được triển khai theo phương thức của Mảng (Array), Cấu trúc (Struct), Con trỏ (Pointer) và Danh sách liên kết (Linked List) Ngăn xếp có thể là ở
Báo cáo thực tập tổng hợp
Trang 8dạng kích cỡ cố định hoặc ngăn xếp có thể thay đổi kích cỡ Phần dưới chúng ta sẽ triển khai ngăn xếp bởi sử dụng các mảng với việc triển khai các ngăn xếp cố định 2.3 Các hoạt động cơ bản trên cấu trúc dữ liệu ngăn xếp
Hoạt động PUSH trong cấu trúc dữ liệu ngăn xếp :
Tiến trình đặt (thêm) một phần tử dữ liệu mới vào trên ngăn xếp còn được biết đến với tên Hoạt động PUSH Hoạt động push bao gồm các bước sau:
Bước 1: kiểm tra xem ngăn xếp đã đầy hay chưa
Bước 2: nếu ngăn xếp là đầy, tiến trình bị lỗi và thoát ra
Bước 3: nếu ngăn xếp chưa đầy, tăng top để trỏ tới phần bộ nhớ trống tiếp theo
Bước 4: thêm phần tử dữ liệu vào vị trí nơi mà top đang trỏ đến trên ngăn xếp
Bước 5: trả về success
Hoạt động POP của cấu trúc dữ liệu ngăn xếp:
Việc truy cập nội dung phần tử trong khi xóa nó từ ngăn xếp còn được gọi là Hoạt động POP Trong sự triển khai Mảng của hoạt động pop(), phần tử dữ liệu không thực
sự bị xóa, thay vào đó top sẽ bị giảm về vị trí thấp hơn trong ngăn xếp để trỏ tới giá trị tiếp theo Nhưng trong sự triển khai Danh sách liên kết, hoạt động pop() thực sự xóa phần tử xữ liệu và xóa nó khỏi không gian bộ nhớ
Hoạt động POP có thể bao gồm các bước sau:
Bước 1: kiểm tra xem ngăn xếp là trống hay không
Bước 2: nếu ngăn xếp là trống, tiến trình bị lỗi và thoát ra
Bước 3: nếu ngăn xếp là không trống, truy cập phần tử dữ liệu tại top đang trỏ tới
Bước 4: giảm giá trị của top đi 1
Bước 5: trả về success
Chương III: ỨNG DỤNG STACK ĐỂ CHUYỂN BIỂU THỨC TỪ DẠNG TRUNG
TỐ SANG HẬU TỐ
Báo cáo thực tập tổng hợp
Trang 93.1 Xây dựng phép dịch biểu thức trung tố sang dạng hậu tố
Gọi ∑ là toán hạng, Г là toán tử ( + , - , * , / ) thì dạng ký pháp hậu tố (postfix) được định nghĩa như sau:
Nếu biểu thức E (Expression) có dạng a ∈ ∑ thì:
Postfix của a chính là a
Nếu biểu thức E có dạng E1θ E2 , trong đó E1, E2 là các biểu thức, còn θ là
toán tử nào đó thì:
Postfix của E1θ E2 là E '1E '2θ , trong đó E '1, E'2tương ứng là postfix của
E 1 , E2.
Nếu biểu thức E có dạng (E) thì:
Postfix của (E) là biểu diễn postfix của E
VD: Cho biểu thức dạng trung tố (infix): (a+b)*c Hãy xác định dạng ký pháp hậu tố (postfix) của biểu thức trên?
Giải:
Xác định dạng ký pháp Postfix:
o Đặt E1 = (a+b), E2 = c, θ = *
o Với E1 = (a+b) thì ta lại đặt: E11 = a, E12 = b, θ = + nên ta có dạng
postfix của E1 là ab+
Do đó, ta có dạng ký pháp Postfix của E là ab+c*
3.2 Giải thuật dịch biểu thức dạng ký pháp trung tố sang biểu thức dạng ký pháp hậu tố
Input: Biểu thức số học dạng infix.
Output: Biểu thức số học dạng postfix.
Phương pháp: Ta sử dụng 2 Stack: S1 lưu trữ toán tử và toán hạng, đồng thời lưu luôn kết quả, S2 lưu trữ toán tử
Trước hết, mỗi toán tử ta gán cho 1 mức ưu tiên (Giá trị số nguyên), toán tử nào có mức ưu tiên lớn thì thực hiện trước, toán tử nào có mức ưu tiên nhỏ hơn thì thực hiện sau
Hoạt động: Duyệt biểu thức vào từ trái qua phải và thực hiện các thao tác sau:
o Nếu ký hiệu vào là toán hạng thì ghi vào S1
o Nếu ký hiệu vào là toán tử thì khi đố ta phải kiểm tra S2:
Nếu S2 rỗng thì ghi toán tử vào S2.
Nếu S2 không rỗng thì: Ta so sánh mức đọ ưu tiên của các toán tử theo nguyên tắc sau: Giả sử gọi θi là toán tử đang
xét, θj là toán tử trong S2 => Xảy ra các trường hợp: Nếu θi
Báo cáo thực tập tổng hợp
Trang 10≤ θj thì đẩy θj khỏi đỉnh của S2, sau đó tiếp tục lặp cho đến khi θi > θj thì dừng, lúc này mới ghi θi vào S2; còn trong
các trường hợp khác thì ta ghi luôn θi vào S2
o Nếu ký hiệu vào là dấu mở ngoặc “(” thì ta ghi ngay vào S2, sau
đó áp dụng lại các thao tác 1,2 ở trên cho đến khi gặp dâu ngoặc
“)”, có toán tử nào nằm trong cặp dấu ngoặc “(”, “)” thì phải đẩy hết Khi đẩy hết thì cặp dấu ngoặc này sẽ “tự hủy”
Lưu ý: Ta sử dụng thêm 1 ký hiệu đặc biệt để đánh dấu kết thúc phải nhất của biểu thức và nó có mức ưu tiên nhỏ nhất
VD: Mô tả giải thuật dịch biểu thức dạng ký pháp trung tố: a+b*c sang biểu thức dạng
ký pháp hậu tố (postfix)
Giải:
Ta sử dụng 2 stach S1, S2, dấu “;” để đánh dấu kết thúc và gán giá trị mức ưu tiên cho các toán tử và dấu “;” như bảng sau:
Ta có hoạt động của giải thuật như sau:
Báo cáo thực tập tổng hợp
Trang 11Báo cáo thực tập tổng hợp
Trang 12Chương IV: CÀI ĐẶT CHƯƠNG TRÌNH TRÊN NGÔN NGỮ LẬP TRÌNH C
4.1 Định hình
Chương trình giúp chuyển biểu thức từ dạng trung tố sáng dạng hậu tố Với biểu thức trung tố được nhập vào và kết quả là biểu thức hậu tố tương ứng
4.2 Viết chương trình
Báo cáo thực tập tổng hợp
Trang 13Báo cáo thực tập tổng hợp
Trang 144.3 Test chương trình
Nhập vào biểu thức (a+b)*c/d+e
Báo cáo thực tập tổng hợp
Trang 15Kết quả: ab+c*d/e+
Báo cáo thực tập tổng hợp
Trang 16KẾT LUẬN
Đến đây chúng ta đã kết thúc việc bàn luận về nghiên cứu cài đặt chương trình chuyển một biểu thức ở dạng trung tố sang dạng ký pháp hậu tố (ký pháp đảo ba lan) Qua quá trình nghiên cứu đề tài, em nhận được một số kết quả sau:
1 Hiểu rõ ký pháp Ba Lan, nghịch đảo Ba Lan
2 Nắm bắt được giải thuật chuyển biểu thức từ dạng trung tố sang hậu tố
2 Cài đặt thành công thuật toán bằng ngôn ngữ lập trình C
Đề tài còn nhiều sai sót, em mong thầy và các bạn đóng góp ý kiến để có thể hoàn thiện tốt hơn đề tài này Em xin chân thành cảm ơn!Báo cáo thực tập tổng hợp
Trang 17Tài liệu tham khảo:
1 Bài giảng Nguyên lý ngôn ngữ lập trình - ThS Lưu Minh Tuấn - Bộ môn CNTT - Viện CNTTKT - ĐHKTQD
2 Viết chương trình tính giá trị biểu thức – Tác giả: Đặng Nhật Anh – Diễn đàn: caulacbovb.com
3 Các nguồn khác trên Internet
Báo cáo thực tập tổng hợp