1. Trang chủ
  2. » Luận Văn - Báo Cáo

NGĂN xếp (STACK) và HÀNG đợi (QUEUE

25 959 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 25
Dung lượng 219,5 KB

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

Nội dung

Ngăn xếp được sử dụng rấtnhiều trong việc giải quyết các bài toán về đồ thị trong các đề thi học sinh giỏi.. Vì vậy tôichọn chuyên đề này để giúp học sinh có cái nhìn tổng quan hơn về ng

Trang 1

TRƯỜNG THPT CHUYÊN TỈNH LÀO CAI

TỔ TOÁN - TIN

-*@* -CHUYÊN ĐỀ NGĂN XẾP (STACK) VÀ HÀNG ĐỢI (QUEUE)

NĂM HỌC: 2015 - 2016

Trang 2

A, MỞ ĐẦU

1 Lý do chọn đề tài

Ngăn xếp và hàng đợi là hai kiểu dữ liệu trừu tượng rất quan trọng và được sửdụng nhiều trong thiết kế thuật toán Về bản chất, ngăn xếp và hàng đợi là danh sáchtức là một tập hợp các phần tử cùng kiểu có tính thứ tự Ngăn xếp được sử dụng rấtnhiều trong việc giải quyết các bài toán về đồ thị trong các đề thi học sinh giỏi Tuynhiên trong quá trình giảng dạy tôi thấy học sinh vẫn còn khó khăn trong việc phântích bài toán để có thể áp dụng được thuật toán và cài đặt giải bài toán Vì vậy tôichọn chuyên đề này để giúp học sinh có cái nhìn tổng quan hơn về ngăn xếp và ứngdụng của ngăn xếp trong giải các bài toán cụ thể

2 Mục đích của đề tài

Về nội dung kiến thức ngăn xếp và hàng đợi đã có rất nhiều tài liệu đề cập đến, trongchuyên đề này chúng tôi chỉ tổng hợp lại các nội dung kiến thức đã có và chủ yếu làđưa vào áp dụng để giải một số bài toán cụ thế, để làm tài liệu tham khảo cho họcsinh và giáo viên trong quá trình học tập và giảng dạy các đội tuyển học sinh giỏi

Trang 3

B NỘI DUNG

I, DỮ LIỆU KIỂU NGĂN XẾP (STACK)

1, Khái niệm:

Stack là một kiểu danh sách tuyến tính đặc biệt mà phép

bổ sung và loại bỏ luôn thực hiện ở một đầu gọi là đỉnh (Top)

Có thể hình dung nó như cơ cấu của một hộp chứa đạn súng

trường hoặc súng tiểu liên Khi lắp đạn hay lấy đạn ra cũng chỉ

ở đầu hộp Viên đạn vừa lắp vào sẽ ở trên đỉnh hộp và viên đạn

lắp vào đầu tiên sẽ ở đáy hộp (Bottom) Viên đạn nạp vào sau

cùng lại là viên đạn bắn đầu tiên

Với nguyên tắc hoạt động của stack “vào sau ra trước” nên nó còn được gọi với tên danhsách kiểu LIFO (Last - In - First - Out)

2, Cài đặt stack

Ta dùng mảng Stack[I Nmax] mà ″đáy″ của Stack là ở đầu tức chỉ số là 1 Việc đưa vào (Push) hay lấy ra (Pop) được thực hiện phần đuôi của mảng nhờ một con trỏ P Các thao tác đưa vào hay lấy ra đó ứng với các thủ tục hàm thích hợp Giả sử Stack chứa các phần

tử là các số nguyên thì ta sẽ có các thủ tục và hàm sau:

3, Các phép xử lý trên stack

a. Khởi tạo stack rỗng: P := 0;

b. Kiểm tra một stack có rỗng hay không:

Function StackEmpty:Boolean; {Kiểm tra stack có rỗng không}

d. Thủ tục đẩy một phần tử vào stack:

Procedure Push (N:Integer); {Đưa số N vào Stack}

Trang 4

a, Khử đệ quy thuật toán sắp xếp Quicksort;

b, Chuyển biểu thức từ dạng trung tố sang dạng hậu tố

Để minh hoạ ta xét biểu thức trung tố sau đây: 7 + 2 * 3 Khi đọc biểu thức này từtrái sang phải, giá trị 7 được hiển thị ngay lập tức Tiếp theo là toán tử +, nhưng nó được

Trang 5

lưu trữ vì toán hạng bên phải của nó chưa được hiển thị, vì vậy nó được đẩy vào ngăn xếpcác toán tử:

Đầu ra Ngăn xếp

Tiếp theo là toán hạng 2 được đọc và được hiển thị Lúc này nó phải được xácđịnh là toán hạng bên phải của toán tử + hay là toán hạng bên trái của toán tử tiếp theo

Để xác định điều này ta so sánh toán tử + ở đỉnh ngăn xếp với toán tử tiếp theo * Bởi vì

* được ưu tiên hơn +, toán hạng 2 là toán hạng bên trái của toán tử * Vì vậy ta đẩy * vàongăn xếp và tìm toán hạng bên phải của nó:

Thuật toán chuyển từ dạng trung tố sang dạng RPN:

1 Khởi động một ngăn xếp rỗng các toán tử

2 While <không xảy ra lỗi và chưa đạt đến kết thúc của biểu thức trung tố> do

a Đọc phần tử x (hằng số, biến số, toán tử số học, các dấu ngoặc trái và ngoặc phải)

tiếp theo trong biểu thức trung tố

b Nếu phần tử x là:

- Dấu ngoặc trái: đẩy nó vào ngăn xếp

- Dấu ngoặc phải: lấy ra và hiển thị các phần tử của ngăn xếp cho đến khi dấungoặc trái được đọc Nếu ngăn xếp rỗng thì xảy ra lỗi

- Toán tử: nếu ngăn xếp rỗng hay x được ưu tiên hơn phần tử ở đỉnh ngăn xếp, đẩy x vào ngăn xếp.

Trang 6

Nếu khác, lấy ra và hiển thị phần tử ở đỉnh ngăn xếp; Lặp lại việc so sánh x với

phần tử ở đỉnh ngăn xếp (Dấu ngoặc trái được xem ưu tiên thấp hơn các toántử)

- Toán hạng: hiển thị nó

3 Khi đạt đến kết thúc của biểu thức trung tố, lấy ra và hiển thị các phần tử của ngănxếp cho đến khi ngăn xếp rỗng

Cài đặt: chương trình này giả sử các toán hạng, toán tử chỉ gồm 1 kí tự và giả sử biểu

thức trung tố là hợp lệ và chỉ kiểm tra rất ít tính đúng đắn của biểu thức trung tố

stack : array[1 MaxSize] of char;

Function Pop : char;

Function Priority(operator : char) : integer;

{ ham tra lai do uu tien cua cac toan tu }

Trang 8

write('Vao bieu thuc dang trung to: '); readln(infix);

infix := infix + EndMask;

II, DỮ LIỆU KIỂU HÀNG ĐỢI (QUEUE)

1 Khái niệm hàng đợi (Queue)

Khác với stack, queue là một danh sách tuyến tính mà phép bổ sung thực hiện ở một đầu,gọi là lối sau (rear) và phép loại bỏ thực hiện ở một đầu khác, gọi là lối trước (front)

Như vậy cơ cấu của queue giống như một hàng đợi (như là một hàng người chờ tính tiền

ở siêu thị, một dãy các máy bay chờ hạ cánh ở một sân bay, ) vào ở một đầu, ra ở đầukhác, nghĩa là vào trước thì ra trước Vì vậy queue được gọi là danh sách kiểu FIFO (First

- In - First - Out)

Quầy bán vé

Lối ra

Trang 9

2 Cài đặt queue

Có thể dùng mảng làm cấu trúc lưu trữ queue Để truy nhập vào queue ta phải dùng 2

biến trỏ: font trỏ đầu hàng đợi và rear trỏ cuối hàng đợi Một phần tử được lấy ra khỏi queue bằng cách tìm phần tử của mảng tại vị trí font và tăng font thêm 1 Một phần tử được thêm vào queue bằng cách lưu trữ nó tại vị trí rear của mảng, giả sử rear không vượt quá độ dài lớn nhất MaxSize của mảng, sau đó tăng rear thêm 1 Sau đây ta xét một vài cấu hình cụ thể của queue với MaxSize = 5:

Trang 10

Procedure Get(Var FistOb :Td); {lấy ra khỏi hàng đợi }

Ứng dụng của hàng đợi điển hình là thuật toán tìm kiếm theo chiều rộng

Trên bàn cờ vua quốc tế N*N ( n≤ 50) trong đó có một số ô có mìn Từ một ô không có mìn cho trước con mã có thể đi đến một ô khác được hay không Nếu được hãy chỉ ra đường đi ngắn nhất

File dữ liệu:

- Dòng 1 là N (kích thước bàn cờ)

- Dòng thứ nhất trong số N dòng tiếp theo:

* đầu tiên là K số mìn trên dòng đó, tiếp theo là K số, mỗi số là chỉ số cột có mìn

+ A[i,j] = 0 nếu ô (i,j) có mìn

+ A[i,j] = 1 nếu ô (i,j) không có mìn và mã chưa đến

+ A[i,j]= k (k>1) nếu ô (i,j) là bước thứ k của con mã

Put(ô xp); {đưa vào hàng đợi toạ độ ô xuất phát}

Nhan { ô xp }: = 0; {khởi tạo nhãn của ô xuất phát}

Trang 11

Bài 1 Chiến trường Ô qua – Nguồn bài: vn.spoj.com

Lại nói về Lục Vân Tiên, sau khi vượt qua vòng loại để trở thành Tráng Sỹ, anh đãgặp được Đôrêmon và được chú mèo máy cho đi quá giang về thế kỷ 19 Trở lại quêhương sau nhiều năm xa cách, với tấm bằng Tráng Sỹ hạng 1 do Liên Đoàn Type Thuậtcấp, anh đã được Đức Vua cử làm đại tướng thống lãnh 3 quân chống lại giặc Ô Qua xâmlăng

Đoàn quân của anh sẽ gồm N đại đội, đại đội i có A[i] (A[i] > 0) người Quân sỹtrong 1 đại đội sẽ đứng thành 1 cột từ người 1 -> người A[i] , như vậy binh sỹ sẽ đứngthành N cột Vì Vân Tiên quyết 1 trận sẽ đánh bại quân Ô Qua nên đã cử ra 1 quân đoànhùng mạnh nhất Trong sử cũ chép rằng, quân đoàn của Vân Tiên cử ra lúc đó là mộtnhóm các đại đội có chỉ số liên tiếp nhau (tức là đại đội i , i + 1 , … j) - Vì sử sách thìmối mọt hết cả nên chỉ biết được mỗi thế Ngoài ra theo giang hồ đồn đại thì sức mạnhcủa 1 quân đoàn = số người của đại đội ít người nhất * số đại đội được chọn

Nhiệm vụ của bạn là dựa trên các thông số của các nhà khảo cổ có được , hãy chobiết quân đoàn mà Vân Tiên đã chọn ra là từ đại đội nào đến đại đội nào Chú ý nếu cónhiều phương án thì ghi ra phương án mà chỉ số của đại đội đầu tiên được chọn là nhỏnhất

Trang 12

Output

 Kết quả mỗi test ghi ra trên 1 dòng, gồm 3 số: sức mạnh quân đoàn mạnh nhất, chỉ

số của đại đội đầu tiên và chỉ số của đại đội cuối cùng được chọn

Ví dụ:

24

3 4 3 14

1 2 1 3

9 1 3

4 1 4

 Hướng dẫn thuật toán:

Xin tóm tắt lại đề bài như sau:

Trong tất cả các đoạn phần tử liên tiếp, hãy chọn ra đoạn [i … j] sao cho tích:min{A[i],…,A[j]} * (j – i + 1) đạt giá trị lớn nhất

- Với đặc điểm của bài toán, rõ ràng với phần tử A[i] ta sẽ phải tìm hai chỉ số j và k(trong đó A[j] phía trước A[i] và A[k] phía sau A[i]) sao cho A[j] gần với A[i] nhất vàA[j] < A[i], A[k] gần với A[i] nhất và A[k] < A[i] Từ đó cập nhật giá trị lớn nhất vơiA[i] * (k – j – 1)

- Để tìm A[j] ta có thể duyệt từ A[i] ngược về 1, để tìm A[k] ta sẽ duyệt từ A[i] tiếptục đến N, tuy nhiên cách này sẽ bị lỗi quá thời gian Ta có thể sử dụng STACK đểlàm giảm thời gian tìm kiếm A[j] và A[k]:

+ Gọi L[i] là chỉ số của phần tử A[L[i]] sao cho L[i] < i và L[i] gần với i nhất đểA[L[i]] <= A[i]

Trang 13

- Nếu A[i] > A[STACK[top]] thì bổ sung i vào STACK và L[i] = STACK[top]

- Nếu A[i] <= A[STACK[top]] thì loại dần các phần tử ở đỉnh STACK cho đếnkhi A[i] > A[STACK[top]] Lúc đó gán L[i] = STACK[top]

+ Tương tự gọi R[i] là chỉ số của phần tử A[R[i]] sao cho i < R[i] và R[i] gần với inhất để A[R[i]] < A[i]

Cách tìm mảng R tương tự như với việc tìm mảng L nhưng theo chiều ngược lại

KQ cuối cùng = max{A[i] * (R[i] – L[i] + 1)}

Bài 2 KIỂM TRA TIN HỌC (PREVNOI 2013- Nguyễn Thế Hùng)

Dạy tin học cơ sở luôn là công việc vất vả ngay cả với những giáo viên nhiều kinhnghiệm như thầy HUNGNT Trong giờ bài tập tin học, có học sinh ngồi quanh một bàntròn, các học sinh được đánh số từ 1 tới theo chiều kim đồng hồ Xuất phát từ một vị trí

từ đầu buổi học, thầy HUNGNT phải đi một vòng quanh bàn theo chiều kim đồng hồ đểhướng dẫn từng bạn theo đúng thứ tự thầy đi qua Mỗi bạn được thầy hướng dẫn đúng micro giây (”s) và sau đó bắt tay vào lập trình ngay trong khi thầy chuyển sang hướngdẫn bạn kế tiếp theo chiều kim đồng hồ…, thời gian di chuyển của thầy coi như khôngđáng kể

Do biết rõ kỹ năng lập trình của từng bạn, thầy HUNGNT có thể ước lượng chính xácrằng bạn học sinh thứ sau khi được thầy hướng dẫn sẽ cần đúng 𝑎𝑖 ”s để viết xongchương trình của mình (∀𝑖 = 1,2,… , 𝑛) Vấn đề là thầy muốn kết thúc buổi học càngsớm càng tốt, muốn vậy, việc chọn học sinh nào hướng dẫn đầu tiên phải được tính toán

kỹ lưỡng…

Yêu cầu: Bạn được cho biết số , giá trị , dãy 𝐴 = (𝑎1, 𝑎2,… , 𝑎𝑛) Hãy giúp thầyHUNGNT chọn vị trí xuất phát sao cho thời gian từ lúc bắt đầu buổi học cho tới khi tất cảcác học sinh viết xong chương trình của mình là nhỏ nhất

Để tránh việc phải đọc một lượng dữ liệu quá lớn, dãy sẽ được cho bởi ba số nguyêndương 𝑝, 𝑞, 𝑚, trong đó mỗi phần tử được xác định theo công thức:

𝑎𝑖 = (𝑝 ∗ 𝑖) mod 𝑚 + 𝑞 (∀𝑖: 1 ≤ 𝑖 ≤ 𝑛)

Dữ liệu: Vào từ file văn bản PERIOD.INP

 Dòng 1 chứa hai số nguyên dương 𝑛, Δ (𝑛 ≤ 5.106; Δ ≤ 109)

Trang 14

 Dòng 2 chứa ba số nguyên dương 𝑝, 𝑞, 𝑚 xác định dãy (𝑝,

𝑞, 𝑚 ≤ 109) Các số trên một dòng của input file được ghi cách

nhau bởi dấu cách

Kết quả: Ghi ra file văn bản PERIOD.OUT một số nguyên duy nhất là thời gian (tính

bằng ”s) từ lúc bắt đầu buổi học cho tới khi tất cả các học sinh viết xong chương trìnhtheo phương án tìm được

Ví dụ

Giải thích: Δ = 3; Dãy 𝐴 = (3,5,7,9,2)

Phương án tối ưu: Thầy bắt đầu với học sinh 2,

Thời điểm viết xong chương trình của từng học sinh như sau:

40% số điểm ứng với các test có 𝑛 ≤ 103

30 % số điểm ứng với các test có

30% số điểm ứng với các test có 𝑛 ∈ [106,5.106]

Hướng dẫn giải thuật :

Xây dựng dãy 𝑏1,𝑏2,…,𝑏2𝑛−1 từ dãy như sáu:

Trang 15

… 𝑏2𝑛−1 =𝑎𝑛−1 +( 𝑛−1)Δ

Có thể hiểu là 𝑏𝑖 được tính bằng phần tử thứ trong dãy theo vòng tròn cộng thêm 𝑖Δ

Dễ thấy rằng nếu HUNGNT bắt đầu từ học sinh 1 thì thời gian giờ học kéo dài là

max{𝑏[1…𝑛]} Nếu bắt đầu từ học sinh 2 thì thời gian giờ học kéo dài là

max{𝑏[2…𝑛+1]}−Δ… Tổng quát: nếu bắt đầu từ học sinh thì thời gian giờ học kéo dài

Từ đây có thể tóm tắt thuật toán như sáu: Với mỗi vị trí , ta cần nhánh chóng xác định𝑀[𝑖] là giá trị lớn nhất trong phần tử tính từ Khi đó đáp số là Việc xác định giá trị lớn nhất trong các đoạn gồm phần tử liên tiếp trong dãy có thể thực hiện trong thời gian Ο(𝑛) bằng cách sử dụng hàng đợi hái đầu chứa các chỉ số trong với các phép toán:

GetFront: Trả về phần tử đầu

GetRear: Trả về phần tử cuối

PopFront: Hủy phần tử đầu

PopRear: Hủy phần tử cuối

Push( ): Đẩy phần tử vào cuối hàng đợi

Bài 3: Optimal Programs

File chương trình OPTIMAL.PAS

Giới hạn thời gian 1 giây

Trang 16

Như bạn đã biết, viết chương trình thường là việc không dễ dàng Mọi việc thậm trítrở nên khó khăn nếu chương trình của bạn cần được hoàn thành nhanh nhất có thể Vàđôi khi cũng có lý do để làm việc đó Rất nhiều chương trình lớn như hệ điều hành hoặc

cơ sở dữ liệu gặp phải sự “tắc nghẽn” - các đoạn mã được thực hiện đi và thực hiện lại, vàchiếm một phần lớn thời gian chạy ở đây người ta thường phải viết lại đoạn mã đó bằnghợp ngữ (assembly), từ đó thời gian chạy đạt được nhỏ nhất và sẽ rất quan trọng nếu đoạn

mã này được thực hiện hàng tỉ lần

Trong bài toán này, chúng ta xem xét nhiệm vụ tự động sinh ra mã hợp ngữ tối ưu.Cho trước một hàm số (như là một dãy các cặp vào/ra), bạn phải tạo ra một chương trìnhhợp ngữ ngắn nhất để tính hàm số này

Các chương trình bạn tạo ra sẽ phải chạy trên một stack cơ sở, nó chỉ hỗ trợ 5 câulệnh: ADD, SUB, MUL, DIV và DUP Bốn câu lệnh đầu lấy ra 2 phần tử trên đỉnh stack

và đẩy vào stack tương ứng tổng, hiệu, tích hoặc thương nguyên của phép chia (giốngphép toán div trong Pascal) của chúng Câu lệnh DUP đẩy thêm vào một phần tử giốngphần tử trên đỉnh stack Như vậy, nếu các câu lệnh được áp dụng trên một stack với 2

phần tử trên đỉnh là a và b thì kết quả của stack như sau:

Stacklúc đầu

ADD

SUB

MU

DUP

Có 3 trường hợp mà stack rơi vào trạng thái lỗi:

 Câu lệnh DIV được thực hiện và phần tử trên đỉnh stack là 0

 Các lệnh ADD, SUB, MUL hoặc DIV được thực hiện trong khi stack chỉ chứa 1 phầntử

 Một phép tính sinh ra giá trị có giá trị tuyệt đối lớn hơn 30000

Dữ liệu: File vào bao gồm các mô tả một dãy các hàm số Mỗi mô tả bắt đầu với một

dòng chứa một số nguyên n (n  10), là số các cặp vào/ra tiếp theo Hai dòng tiếp theo: dòng thứ nhất chứa n số nguyên x 1 , x 2 , , x n (tất cả khác nhau) và dòng thứ hai chứa y 1,

y 2 , , y n Các số có giá trị tuyệt đối không vượt quá 30000

Kết thúc file vào bằng một trường hợp kiểm tra bắt đầu với n = 0 Trường hợp kiểm tra

này là không phải xử lý

Trang 17

Kết quả: Bạn phải tìm chương trình ngắn nhất tính hàm f, sao cho f(x i ) = y i với mọi i 

1, , n Điều này nghĩa là chương trình bạn đưa ra có thể không vào trạng thái lỗi nếu

thực hiện các dữ liệu vào x i (mặc dù nó có thể rơi vào trạng thái lỗi đối dữ liệu vào khác).Chỉ xem xét các chương trình có nhiều nhất 10 câu lệnh

Với mỗi một mô tả hàm, đầu tiên ghi ra số thứ tự của mô tả đó Sau đó ghi ra dãy các câulệnh làm nên chương trình ngắn nhất tính hàm cho trước này Nếu có nhiều hơn mộtchương trình như vậy, thì hãy đưa ra chương trình nhỏ nhất theo thứ tự sắp xếp từ điển.Nếu không có chương trình có tối đa 10 câu lệnh thì in ra dòng chữ “Impossible” Nếuchương trình ngắn nhất có không câu lệnh thì in ra “Empty Sequence”

Ghi một dòng trắng sau mỗi trường hợp kiểm tra

Ví dụ:

OPTIMAL.INP OPTIMAL.OUT4

1 2 3 4

0 -2 -6 -123

1 2 3

1 11 20031

200320030

Program 1DUP DUP MUL SUB

Program 2Impossible

Program 3Empty sequence

= ('ADD', 'DIV', 'DUP', 'MUL', 'SUB');

{ sap theo thu tu tu dien }

stack : array[1 max] of Sequence;

inp, out : text;

Function Read_data : integer;

Var i : integer;

Begin

d := d + 1;

Ngày đăng: 03/01/2016, 21:34

TỪ KHÓA LIÊN QUAN

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

TÀI LIỆU LIÊN QUAN

w