1. Trang chủ
  2. » Giáo Dục - Đào Tạo

Sử dụng các cấu trúc dữ liệu đã học danh sách móc nối, ngăn xếp, hàng đợi,… để thực hiện bài toán “chuyển đổi biểu thức trung tố thành biểu thức hậu tố

22 273 1

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 22
Dung lượng 380,57 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Thuật toán chung của bài toán Thuật toán để chuyển một biểu thức Infix sang dạn Prefix: Đọc từng token trong biểu thức infix từ trái qua phải, với mỗi token ta thực hiện các bước sau: –

Trang 1

MỤC LỤC

A Giới thiệu chung 3

1 Định nghĩa về biểu thức trung tố và biểu thức hậu tố? 3

2 Phân công nhiệm vụ 3

3 Các cấu trúc dữ liệu được sử dụng 3

B Cài đặt trên những cấu trúc dữ liệu cụ thể 3

I Cấu trúc ngăn xếp (Stack) 3

1 Ngăn xếp là gì? 3

2 Thuật toán chung của bài toán 4

3 Ví dụ minh họa 4

4 Các hàm cụ thể 5

5 Test kết quả 8

II Cây nhị phân tìm kiếm 8

1 Cây nhị phân tìm kiếm là gì? 8

2 Cấu trúc dữ liệu cho bài toán 9

3 Ví dụ minh họa 10

4 Các hàm sử dụng trong bài toán 13

5 Test kết quả 17

III Hàng đợi 17

1 Hàng đợi là hì? 17

2 Ứng dụng của Queue trong kí pháp Ba Lan 18

3 Các hàm sử dụng 19

4 Test kết quả 20

Trang 2

Đề bài: Sử dụng các cấu trúc dữ liệu đã học: danh sách móc nối, ngăn xếp, hàng đợi,

… để thực hiện bài toán “chuyển đổi biểu thức trung tố thành biểu thức hậu tố” Yêu cầu:

- Dữ liệu được sinh ngẫu nhiên hoặc nhập từ bàn phím.

- Dữ liệu được tổ chức lưu trữ trên tệp tin

- Mô phỏng giải thuật bằng phương pháp trực quan.

- Đánh giá độ phúc tạp của thuật toán trên những cấu trức dữu liệu khác nhau.

Trang 3

A Giới thiệu chung

1 Định nghĩa về biểu thức trung tố và biểu thức hậu tố?

Các biểu thức đại số được sử dụng hằng ngày đều được biểu diễn dưới dạng trung tố (infix) Cách biểu diễn này rất dễ hiểu với con người vì hầu hết các toán tử (+, -, *, /) đều là toán tử hai ngôi và chúng phân cách giữa hai toán hạng với nhau Tuy nhiên đối với máy tính, để tính được giá trị của một biểu thức đại số theo dạng này không đơn giản như ta vẫn làm Để khắc phục điều đó, máy tính cần chuyển cách biểu diễn các biểu thức đại số từ trung tố sang một dạng khác là tiền tố hoặc hậu tố.

– 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.

2 Phân công nhiệm vụ

Hà Thị Vân Anh Nguyễn Thị Hằng Châu Vương Thị Phương

B Cài đặt trên những cấu trúc dữ liệu cụ thể

I Cấu trúc ngăn xếp (Stack)

1 Ngăn xếp là gì?

Một ngăn xếp là một cấu trúc dữ liệu trừu tượng (Abstract Data Type – viết tắt là ADT), 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

Trang 4

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, …

2 Thuật toán chung của bài toán

Thuật toán để chuyển một biểu thức Infix sang dạn Prefix:

Đọc từng token trong biểu thức infix từ trái qua phải, với mỗi token ta thực hiện các bước sau:

– Nếu là toán hạng: cho ra output.

– Nếu là dấu mở ngoặc “(“: cho vào stack – Nếu là dấu đóng ngoặc “)”: lấy các toán tử trong stack ra và cho vào output cho đến khi gặp dấu mở ngoặc “(“ (Dấu mở ngoặc cũng phải được đưa ra khỏi stack)

– Nếu là toán tử:

+/Chừng nào ở đỉnh stack là toán tử và toán tử đó có độ ưu tiên lớn hơn hoặc bằng toán tử hiện tại thì lấy toán tử đó ra khỏi stack và cho ra output.

+/Đưa toán tử hiện tại vào stack Sau khi duyệt hết biểu thức infix, nếu trong stack còn phần tử thì lấy các token trong đó ra và cho lần lượt vào output.

Trang 5

4 Các hàm cụ thể

4.1 Các hoạt động cơ bản của Stack

Các hoạt động cơ bản trên ngăn xếp có thể liên quan tới việc khởi tạo ngăn xếp,

sử dụng nó và sau đó xóa nó Ngoài các hoạt động cơ bản này, một ngăn xếp có hai hoạt động nguyên sơ liên quan tới khái niệm, đó là:

- Hoạt động push(): lưu giữ một phần tử trên ngăn xếp.

- Hoạt động pop(): xóa một phần tử từ ngăn xếp.

Khi dữ liệu đã được PUSH lên trên ngăn xếp:

Để sử dụng ngăn xếp một cách hiệu quả, chúng ta cũng cần kiểm tra trạng thái của ngăn xếp Để phục vụ cho mục đích này, dưới đây là một số tính năng hỗ trợ khác của ngăn xếp:

- Hoạt động peek(): lấy phần tử dữ liệu ở trên cùng của ngăn xếp, mà không xóa

phần tử này.

Trang 6

- Hoạt động isFull(): kiểm tra xem ngăn xếp đã đầy hay chưa.

- Hoạt động isEmpty(): kiểm tra xem ngăn xếp là trống hay không.

Tại mọi thời điểm, chúng ta duy trì một con trỏ tới phần tử dữ liệu vừa được PUSH cuối cùng vào trên ngăn xếp Vì con trỏ này luôn biểu diễn vị trí trên cùng của ngăn xếp vì thế được đặt tên là top Con trỏ top cung cấp cho chúng ta giá trị của phần

tử trên cùng của ngăn xếp mà không cần phải thực hiện hoạt động xóa ở trên (hoạt động pop).

Hoạt động PUSH ( thêm một phần tử vào danh sách )

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.

Nếu Danh sách liên kết được sử dụng để triển khai ngăn xếp, thì ở bước 3 chúng ta cần cấp phát một không gian động.

Hoạt động POP ( xóa một phần tử từ 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

Trang 7

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.

4.2 Các hàm chính của bài toán

- Hàm kiểm tra mức độ ưu tiên của các toán tử

+ Mức độ ưu tiên thấp nhất là dấu “(”

+ Mức độ ưu tiên thứ hai là dấu “+” và “-”

+ Mức độ ưu tiên thử ba là dấu “*” và “/”

+ Mức độ ưu tiên cao nhất là dấu mũ “^”

Trang 8

- Hàm kiểm tra là toán hạng hay toán tử

5 Test kết quả

Trang 9

II Cây nhị phân tìm kiếm

1 Cây nhị phân tìm kiếm là gì?

Cây tìm kiếm nhị phân (Binary Search Tree): là một cấu trúc dữ liệu cơ bản được sử dụng để xây dựng các cấu trúc dữ liệu trừu tượng hơn như các tập hợp, đa tập hợp, các dãy kết hợp, giữa các nút có một quan hệ phân cấp gọi là quan hệ “cha - con” Có một nút đặc biệt gọi là nút gốc.

Một cây nhị phân có một điều kiện đặc biệt là mỗi nút có thể có tối đa 2 nút con Mỗi cây nhị phân tận dụng dụng lợi thế của hai kiểu cấu trúc dữ liệu: một mảng

đã sắp thứ tự và một danh sách liên kết (Linked List), do đó việc tìm kiếm sẽ nhanh như trong mảng đã sắp thứ tự và các thao tác chèn và xóa cũng sẽ nhanh bằng trong

Linked List.

Node trong cây tìm kiếm nhị phân có đặc điểm chung là giá trị bên phải bao giờ cũng lớn hơn giá trị bên trái Một node trong cây tìm kiếm nhị phân sẽ bao gồm node trái – phải, key giá trị của node đó trong cây.

Trang 10

Duyệt cây là việc lần lượt viếng thăm các đỉnh của cây theo thứ tự nào

đó Có 2 cách duyệt một cây nhị phân tìm kiếm đó là duyệt sâu vàduyệt rộng

2 Cấu trúc dữ liệu cho bài toán

Ý tưởng chung của thuật toán:

 Thuật toán này yêu cầu sử dụng 2 Stack:

 Operators Stack: chứa các toán tử

 Treenodes Stack: chứa các node tạo nên cấu trúc cây(node gốc của các cây con được xây dựng từ dưới lên)

 Mô tả thuật toán:

 Tạo ra một phương thức phụ attachOperator() có nhiệm

vụ tạo ra một cây nhị phân gồm 3 node Node gốc là toán

tử Pop được lấy ra từ operators Stack, hai node lá là toánhạng được lấy ra từ Pop của treenodes Stack Cuối cùngđưa node gốc vào lại treenodes Stack

 Lặp qua từng token trong biểu thức trung tố (infix):

 Nếu là toán hạng: push vào treenodes Stack

 Nếu là dấu mở ngoặc “( “ thì push vào operatorsStack

 Nếu là dấu đóng ngoặc “)” thì

 Lặp cho đến khi lấy được dấu mở ngoặc “(“trong operators Stack Mỗi lần lặp như vậy

sẽ gọi phương thức attachOperator()

 Pop dấu mở ngoặc “(“ ra khỏi operatorsStack

 Nếu là toán tử

 Lặp cho đến khi operators Stack rỗng hoặc

độ ưu tiên của toán tử ở đỉnh operators Stacknhỏ hơn độ ưu tiên của toán tử hiện tại Mỗilần lặp gọi lại phương thức attachOperator()

 Push toán tử vào operators Stack

A

Con trỏ đến phần tử

bên trái Giá trị củaNode Con trỏ đến phần tửbên phải

Trang 11

 Khi hết vòng lặp nếu operators Stack còn phần tử, gọiphương thức attachOperator () cho đến khi operatorsStack rỗng Node còn lại cuối cùng trong nodeStack lànode gốc của cây nhị phân

3 Ví dụ minh họa

Ví dụ chuyển đổi biểu thức trung tố sau thành biểu thức hậu tố:(A+B)*C-D/E

Trang 12

Bước 1: dựng cây biểu thức từ biểu thức trung tố

Token Operators Treenodes Description

- Cho A và B ra làm node con của +

- Push + và treenodes, pop dấu mởngoặc “(“ ra khỏi operators

C * + C Push C vào treenodes vì C là toán

hạng

toán tử * ở đỉnh của stack operatorsnên gọi phương thức tạo cây con:Đưa + và C làm node con của *Push * vào treenodes

{empty

Đưa / vào treenodes

Trang 13

{empty} - Đưa * và / làm node con của –

Đưa – vào treenodes Node – chính lànode gốc của cây biểu thức

Bước 2: duyệt cây biểu thức vừa tạo theo phương pháp duyệt hậu thức

tự và đưa ra biểu thức hậu tố

Duyệt cây theo phương pháp PostOrder là duyệt con trái > con phải

-> gốc

- Bắt đầu từ node gốc – ta thăm con trái của nó Gặp node *, tiếp tục thăm contrái của node * ta gặp node + Vì node + có con trái nên ta tiếp tục thăm contrái của + là node A.Vì node A là node lá không có con nên ta in giá trị củanode này Vậy kết quả biểu thức hậu tố là ouput = A

- Sau khi đã duyệt hết con trái ta chuyển sang con phải của + ta chuyển sangthăm con phải của nó là B Vì B là node lá và không có con nên ta in giá trịcủa node này và đưa vào chuỗi kết quả ouput = A B

- Sau khi đã duyệt hết con trái và con phải của + ta tiến hành thăm node cha và

in giá trị của node gốc và thêm vào chuỗi output = A B +

- Sau khi đã thăm hết con trái của node * ta thăm con phải của nó là C Vì C lànode lá không có con trái và con phải nên ta in giá trị của node này và thêmvào chuỗi kết quả ouput = A B + C

- Sau khi đã duyệt xong con trái và con phải của * ta tiến hành thăm node cha

* và in giá trị của nó và thêm vào output = A B + C *

- Sau khi đã thăm hết con trái của node gốc – ta tiến hành thăm con phải của

nó Gặp node /, tiếp tục thăm con trái của / là D Vì D không có con nên ta ingiá trị của node này và thêm vào chuỗi output = A B + C * D

Trang 14

- Tiếp tục thăm con phải của / gặp node E Vì node E không có con nên ta ingiá trị của node này và thêm vào chuỗi output = A B + C * D E

- Sau khi đã thăm hết con của / ta tiến hành thăm node cha / và tiến hành ingiá trị của node này và thêm vào chuỗi output = A B + C * D E /

- Cuối cùng khi đã duyệt hết con trái và con phải của node gốc -, ta tiến hànhduyệt node gốc và in ra giá trị của nó và thêm vào chuỗi output = A B + C *

D E /

Kết quả của việc chuyển đổi là: A B + C * D E /

-4 Các hàm sử dụng trong bài toán

 Cấu trúc dữ liệu lưu trữ

 Stack<char>input: lưu trữ biểu thức nhập vào

 Stack<Node*>treenodes: lưu trữ các node tạo nên cấutrúc cây

 Stack<Node*>operators: stack lưu trữ các toán tử

 Hàm xử lý

 Struct Node: khai báo cấu trúc của 1 Node

 Int priority(char op): trả về độ ưu tiên của toán tử, nếu là

‘+’ và ‘-‘ thì trả về 1, còn ‘*’ và ‘/’ thì trả về 2

 Node* newNode(char data): tạo một node mới có giá trịdata Node mới này không có con trái và con phải

Trang 15

 Quá trình tạo cây biểu thức

 Dùng vòng for để đưa lần lượt các phần tử biểu thứctrung tố đã nhập vào stack input

Trang 16

 Dùng vòng while(với input khác rỗng) để lặp qua cácphần tử có trong stack input, dùng top() để lấy lần lượtcác phần tử ra, dùng 1 biến temp để lưu lại giá trị đượclấy ra từ đỉnh input stack

 Dùng if để kiểm tra xem phần tử vừa được lấy ra là toánhạng (số, chữ) hay là toán tử, hay là dấu mở ngoặc ”)”,dấu đóng ngoặc “(“

 Nếu là toán hạng thì đưa vào stack treenodes và tạonode có giá trị data được đưa vào và giá trị củaphần tử đang xét là biến temp

 Nếu là dấu đóng ngoặc thì đưa vào stack operators

và tạo node

 Nếu là toán tử (+ - * /) thì tiến hành lặp cho đến khi stackoperators rỗng hoặc toán tử hiện tại có độ ưu tiên lớn hơn hoặcbằng độ ưu tiên của toán tử top() hiện tại của stack, mỗi lần nhưvậy sẽ gọi phương thức tạo cây con attachOperator Sau đópush toán tử vào stack operators

Để thực hiện vòng lặp, ta kiểm tra xem toán tử hiện tại đãđược push vào operators stack chưa, nếu chưa thì tiến hànhkiểm tra điều kiện và độ ưu tiên

- Nếu stack operators rỗng thì tiến hành tạo node và push vào stack

- Ngược lại, nếu phần tử top() của stack operators là dấu đóng ngoặc thì tếnhành tạo node và push phần tử vào stack

- Ngược lại nếu phần tử hiện tại có độ ưu tiên lớn hơn hoặc bằng phần tử top()thì tạo node và push vào stack

Trang 17

- Ngược lại ta sẽ gọi phương thức tạo cây con, kết thúc vòng lặp while

 Nếu phần tử được đọc từ stack input là dấu mở ngoặc thì lặp cho đến khi lấyđược dấu đóng ngoặc của stack operators Mỗi lần lặp gọi phương thức tạocây con attachOperator Kết thúc vòng lặp pop() dấu đóng ngoặc ra khỏistack

 Khi đã kiểm tra hết các phần tử trong stack input, tiến hành gọi phương thứcgọi tạo cây con cho đến khi stack operator rỗng, Node còn lại cuối cùng lànode gốc của cây biểu thức

Trang 19

 Trong cuộc sống chúng ta thường xuyên gặp hàng, ví dụ hàng người xếp chờ mua vé xem phim Người ta chỉ có thể đi vào hàng ở cuối hàng và người được phục vụ đi ra khỏi hàng là người ở đầu hàng, ai vào trước sẽ được phục vụ trước Vì vậy hàng đợi còn gọi là danh sách FIFO ( Fisrt In First Out) vào trước ra trước.

 Các phép toán hàng đợi:

₋ Khởi tạo hàng đợi rỗng: InitQueue( Queue),

₋ Kiểm tra hàng đợi rỗng: isEmpty( Queue),

₋ Thêm một phần tử vào hàng đợi: Put(Queue,item),

₋ Lấy một phần tử ra khỏi hàng: Get( Queue)

 Có hai cách lưu trữ tương tự như stack:

Ứng dụng gián tiếp: Cấu trúc dữ liệu phụ trợ cho các thuật toán

2 Ứng dụng của Queue trong kí pháp Ba Lan

 Thuật toán chuyển biểu thức trung tố sang biểu thức hậu tố: Giả sử cho biểu thức trung tố E

 Bước 1: đọc lần lượt phần tử đầu tiên của biểu thức E (từ trái qua phải), giả sử phần tử đầu tiên là x

₋ Nếu x là toán hạng thì viết vào biểu thức E1( kết quả)

₋ Nếu x là dấu ‘(’ thì đưa vào stack

₋ Nếu x là các toán tử ‘+’, ‘-’, ‘*’,’/’ thì xét độ ưu tiên Giả sử phần tử cần xét là y

+ y>=x thì loại y ra khỏi stack và đẩy y về E1

+ y<x thì đưa x vào stack

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

Cho dãy E= a*(b+c)-d/e

Trang 20

E Stack E1(kết quả)

₋ Bool iope: so sánh các phép toán tử nếu nhỏ hơn 4 thì trả về giá trị

‘true’ và ngược lại trả về ‘false’

bool isope(char c){

Ngày đăng: 03/07/2020, 16:54

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

🧩 Sản phẩm bạn có thể quan tâm

w