Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 25 trang
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
Nội dung
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 A, MỞ ĐẦU Lý chọn đề tài Ngăn xếp hàng đợi hai kiểu liệu trừu tượng quan trọng sử dụng nhiều thiết kế thuật toán Về chất, ngăn xếp hàng đợi danh sách tức tập hợp phần tử kiểu có tính thứ tự Ngăn xếp sử dụng nhiều việc giải toán đồ thị đề thi học sinh giỏi Tuy nhiên trình giảng dạy thấy học sinh khó khăn việc phân tích toán để áp dụng thuật toán cài đặt giải toán Vì chọn chuyên đề để giúp học sinh có nhìn tổng quan ngăn xếp ứng dụng ngăn xếp giải toán cụ thể Mục đích đề tài Về nội dung kiến thức ngăn xếp hàng đợi có nhiều tài liệu đề cập đến, chuyên đề tổng hợp lại nội dung kiến thức có chủ yếu đưa vào áp dụng để giải số toán cụ thế, để làm tài liệu tham khảo cho học sinh giáo viên trình học tập giảng dạy đội tuyển học sinh giỏi B NỘI DUNG I, DỮ LIỆU KIỂU NGĂN XẾP (STACK) 1, Khái niệm: Stack kiểu danh sách tuyến tính đặc biệt mà phép bổ sung loại bỏ thực đầu gọi đỉnh (Top) Có thể hình dung cấu hộp chứa đạn súng ← Top trường súng tiểu liên Khi lắp đạn hay lấy đạn đầu hộp Viên đạn vừa lắp vào đỉnh hộp viên đạn ← Bottom lắp vào đáy hộp (Bottom) Viên đạn nạp vào sau lại viên đạn bắn Với nguyên tắc hoạt động stack “vào sau trước” nên gọi với tên danh sách kiểu LIFO (Last - In - First - Out) 2, Cài đặt stack Ta dùng mảng Stack[I Nmax] mà ″đáy″ Stack đầu tức số Việc đưa vào (Push) hay lấy (Pop) thực phần đuôi mảng nhờ trỏ P Các thao tác đưa vào hay lấy ứng với thủ tục hàm thích hợp Giả sử Stack chứa phần tử số nguyên ta có thủ tục hàm sau: 3, Các phép xử lý stack a Khởi tạo stack rỗng: P := 0; b Kiểm tra stack có rỗng hay không: Function StackEmpty:Boolean; {Kiểm tra stack có rỗng không} Begin StackEmpty:=P=0; End; c Thủ tục lấy phần tử đỉnh stack Function Pop: Integer; {Lấy phần tử khởi stack} Begin Pop:=Stack[P]; Dec(P); End; d Thủ tục đẩy phần tử vào stack: Procedure Push (N:Integer); {Đưa số N vào Stack} Begin Inc (P); Stack[P]:=N; End; 4, Ứng dụng ngăn xếp: a, Khử đệ quy thuật toán xếp Quicksort; Const Nmax=5000; Var n, i, j, x, l, r, tg:Integer; s: Nmax; A: Array[1 Nmax] of Integer; Stack: Array [1 Nmax] of Record l, r : Integer; End; Procedure Sort; Begin S:=1; Stack [s].l:=1; Stack [s].r:=n ; Repeat l:=Stack[s].1; r:=Stack[s].r; Dec(s); Repeat i:=1; j:=r; x:=A[(1+r)div 2] Repeat While a[i] < x Do Inc(i); While a [j] > x Do Dec (j); if i < = j then Begin Tg:=a[i]; a[i]:=a[j]; a[j]:=tg; Inc(i); Dec (j); End; Until i >j; If i < r then Begin S: = s +1 ; Stack [s].l: = 1; Stack [s].r:= r ; End; r : = j; Until 1> r ; Until S= 0;End; 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: + * Khi đọc biểu thức từ trái sang phải, giá trị hiển thị Tiếp theo toán tử +, lưu trữ toán hạng bên phải chưa hiển thị, đẩy vào ngăn xếp toán tử: Đầu Ngăn xếp + Tiếp theo toán hạng đọc hiển thị Lúc phải xác định toán hạng bên phải toán tử + toán hạng bên trái toán tử Để xác định điều ta so sánh toán tử + đỉnh ngăn xếp với toán tử * Bởi * ưu tiên +, toán hạng toán hạng bên trái toán tử * Vì ta đẩy * vào ngăn xếp tìm toán hạng bên phải nó: Đầu Ngăn xếp * 72 + Toán hạng đọc hiển thị Bởi lúc ta đạt đến kết thúc biểu thức, toán hạng bên phải toán tử * đỉnh ngăn xếp tìm ra, toán tử * lấy từ ngăn xếp hiển thị: Đầu Ngăn xếp 723* + Dấu kết thúc biểu thức toán hạng bên phải toán tử lại + ngăn xếp tìm ra, lấy hiển thị, ta biểu thức RPN: 3*+ Các dấu ngoặc biểu thức trung tố không gây khó khăn thực Dấu ngoặc bên trái bắt đầu biểu thức đọc đẩy vào ngăn xếp Đến gặp dấu ngoặc phải, toán tử lấy từ ngăn xếp dấu ngoặc trái tương ứng xuất đỉnh Lúc này, biểu thức ban đầu dấu ngoặc chuyển sang dạng RPN, bỏ qua chúng, phép chuyển đổi tiếp tục Thuật toán chuyển từ dạng trung tố sang dạng RPN: Khởi động ngăn xếp rỗng toán tử While a Đọc phần tử x (hằng số, biến số, toán tử số học, dấu ngoặc trái ngoặc phải) biểu thức trung tố b Nếu phần tử x là: - Dấu ngoặc trái: đẩy vào ngăn xếp - Dấu ngoặc phải: lấy hiển thị phần tử ngăn xếp dấu ngoặc trái đọc Nếu ngăn xếp rỗng xảy lỗi - Toán tử: ngăn xếp rỗng hay x ưu tiên phần tử đỉnh ngăn xếp, đẩy x vào ngăn xếp Nếu khác, lấy 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 xem ưu tiên thấp toán tử) - Toán hạng: hiển thị Khi đạt đến kết thúc biểu thức trung tố, lấy hiển thị phần tử ngăn xếp ngăn xếp rỗng Cài đặt: chương trình giả sử toán hạng, toán tử gồm kí tự giả sử biểu thức trung tố hợp lệ kiểm tra tính đắn biểu thức trung tố Program Infix_to_rpn; Uses crt; Const MaxSize = 100; EndMask = ';'; { dau ket thuc bieu thuc trung to } Var infix, rpn : string; top : integer; stack : array[1 MaxSize] of char; Function Pop : char; Begin Pop := stack[top]; top := top - 1; End; Procedure Push(x : char); Begin top := top + 1; stack[top] := x; End; Function Priority(operator : char) : integer; { ham tra lai uu tien cua cac toan tu } Begin case operator of '(' : Priority:=0; '+', '-' : Priority := 1; '*', '/' : Priority := 2; end; End; Procedure Convert_to_rpn; Var i : integer; x, symbol : char; error, donePop : boolean; Begin write('Bieu thuc dang RPN la: '); rpn := ''; top := 0; error := false; i := 1; x := infix[1]; while (x EndMask) and not error begin while infix[i] = ' ' i := i + 1; { nhay qua cac dau cach } x := infix[i]; if x = EndMask then break; case x of '(' : Push(x); ')' : begin donePop := false; repeat if top = then error := true else begin symbol := Pop; if symbol = '(' then donePop := true else rpn := rpn + symbol; end; until donePop or Error; end; '+', '-', '*', '/': begin donePop := false; while (top 0) and (not donePop) begin symbol := Pop; if Priority(x) 0; End; Function Qfull: Boolean; {Kiểm tra xem hàng đợi đầy hay chưa } Begin QFull : = r – > SizeQ; End; 3, Ứng dụng Queue: Ứng dụng hàng đợi điển hình 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) có số ô có mìn Từ ô mìn cho trước mã đến ô khác hay không Nếu đường ngắn File liệu: - Dòng N (kích thước bàn cờ) - Dòng thứ số N dòng tiếp theo: * K số mìn dòng đó, K số, số số cột có mìn - Dòng cuối ghi số d1, c1,d2, c2: * (d1,c1): toạ độ ô xuất phát * (d2,c2): Toạ độ ô đích Nhận xét: Với ta ứng dụng loang theo chiều rộng sau: Dùng mảng A[i,j]: + A[i,j] = ô (i,j) có mìn + A[i,j] = ô (i,j) mìn mã chưa đến + A[i,j]= k (k>1) ô (i,j) bước thứ k mã Put(ô xp); {đưa vào hàng đợi toạ độ ô xuất phát} Nhan { ô xp }: = 0; {khởi tạo nhãn ô xuất phát} Repeat For { ô kề ô 1} if {ô để mình} then if { ô kề chưa đến} then Begin Nhan [ôkề]: = Nhan [ô] +1; Put (ô kề) End; Until QuEmpty; if Nhan [ô đích] = vô Then { thông báo không đến} 10 Else Repeat Tìm lật ngược kể từ ô đích; Until Nhan [ô i] = 0; III BÀI TẬP ÁP DỤNG Bài Chiến trường Ô qua – Nguồn bài: vn.spoj.com Lại nói Lục Vân Tiên, sau vượt qua vòng loại để trở thành Tráng Sỹ, anh gặp Đôrêmon mèo máy cho giang kỷ 19 Trở lại quê hương sau nhiều năm xa cách, với Tráng Sỹ hạng Liên Đoàn Type Thuật cấp, anh Đức Vua cử làm đại tướng thống lãnh quân chống lại giặc Ô Qua xâm lăng Đoàn quân anh gồm N đại đội, đại đội i có A[i] (A[i] > 0) người Quân sỹ đại đội đứng thành cột từ người -> người A[i] , binh sỹ đứng thành N cột Vì Vân Tiên trận đánh bại quân Ô Qua nên cử quân đoàn hùng mạnh Trong sử cũ chép rằng, quân đoàn Vân Tiên cử lúc nhóm đại đội có số liên tiếp (tức đại đội i , i + , … j) - Vì sử sách mối mọt hết nên biết Ngoài theo giang hồ đồn đại sức mạnh quân đoàn = số người đại đội người * số đại đội chọn Nhiệm vụ bạn dựa thông số nhà khảo cổ có , cho biết quân đoàn mà Vân Tiên chọn từ đại đội đến đại đội Chú ý có nhiều phương án ghi phương án mà số đại đội chọn nhỏ Input • Dòng : Số T số test • T nhóm dòng , nhóm dòng mô tả test Nhóm dòng thứ i : o Dòng 1: N (N max then exit; { vuot qua 10 cau lenh } for j := to begin if (j 3) and (top < 2) then continue; if (j = 3) and (top = max) then continue; x[i] := j; case j of : { ADD } for k := to n s[k] := stack[top - 1, k] + stack[top, k]; : { DIV } begin k := 1; while (k [...]... 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 Q := ; for i := 1 to 2n – 1 do begin while (Q ≠ ) & (a[GetRear] ≤ a[i]) do PopRear; Push(i); if... 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ằng hợ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... các cặp vào/ra), bạn phải tạo ra một chương trình hợ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âu lệ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ống phép toán div trong Pascal) của chúng Câu lệnh DUP đẩy thêm vào một... 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ơi A[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ếp tụ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... M[n – i + 1] := GetFront end; return Các phép toán của hàng đợi hai đầu có thể cài đặt bằng mảng với hai chỉ số đầu cuối hoặc STL’s deque Tất cả các phép toán đó có độ phức tạp Ο(1) Thuật toán sử dụng lệnh Push vì vậy có tổng cộng không quá lệnh PopRear và PopFront Từ đó suy ra thời gian thực hiện giải thuật là Ο(�) Bài 3: Optimal Programs File vào File ra File chương trình Giới hạn thời gian OPTIMAL.INP... nhau) và dòng thứ hai chứa y1, y2, , yn 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ý 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(xi) = yi 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 xi... tôi chỉ đưa ra các cách cài đặt cơ bản nhất để từ đó học sinh tự nghiên cứu và phát triển thêm Vì thời gian và trình độ có hạn nên chuyên đề này có thể còn nhiều hạn chế, thiếu sót mong các đồng nghiệp và các em học sinh góp ý D TÀI LIỆU THAM KHẢO 1, Tài liệu chuyên tin quyển 2 – Hồ Sỹ Đàm chủ biên 2, Giáo trình Giải thuật và lập trình – Tác giả Lê Minh Hoàng 3, Một số tài liệu khác của các đồng nghiệp... phần tử trên đỉnh là a và b thì kết quả của stack như sau: Stack lúc đầu a b c AD D a+b c SU B MU L b-a c a*b c DIV b div a c DU P a a b c Tại thời điểm bắt đầu thực hiện chương trình, stack sẽ chỉ chứa 1 số nguyên: số vào Tại thời điểm kết thúc tính toán, stack cũng phải chứa duy nhất một số nguyên, số này là kết quả của sự tính toán Có 3 trường hợp mà stack rơi vào trạng thái lỗi: • Câu... 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ần tử • 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ứ... tiên và chỉ số của đại đội cuối cùng được chọn Ví dụ: Input 2 4 3431 4 1213 Output 913 414 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] ... đẩy vào ngăn xếp - Dấu ngoặc phải: lấy hiển thị phần tử ngăn xếp dấu ngoặc trái đọc Nếu ngăn xếp rỗng xảy lỗi - Toán tử: ngăn xếp rỗng hay x ưu tiên phần tử đỉnh ngăn xếp, đẩy x vào ngăn xếp. .. chọn đề tài Ngăn xếp hàng đợi hai kiểu liệu trừu tượng quan trọng sử dụng nhiều thiết kế thuật toán Về chất, ngăn xếp hàng đợi danh sách tức tập hợp phần tử kiểu có tính thứ tự Ngăn xếp sử dụng... quan ngăn xếp ứng dụng ngăn xếp giải toán cụ thể Mục đích đề tài Về nội dung kiến thức ngăn xếp hàng đợi có nhiều tài liệu đề cập đến, chuyên đề tổng hợp lại nội dung kiến thức có chủ yếu đưa vào