stack và queue

6 523 2
stack và queue

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

Thông tin tài liệu

KIỂU DỮ LIỆU STACKQUEUE Nguyễn Thế Anh Ngoài các kiểu dữ liệu chuẩn như array, string,… mà PASCAL hỗ trợ thì còn có các kiểu dữ liệu trừu tượng khác trong đó 2 kiểu dữ liệu STACKQUEUE có ứng dụng rất rộng rãi. Hôm nay tôi xin giới thiệu với các bạn chi tiết về 2 kiểu dữ liệu này. I. Stack (Ngăn xếp). Đây là kiểu dữ liệu mà việc cập nhật truy nhập nó đều theo nguyên tắc ″Vào sau ra trước″(Last In, Firt Out viết tắt là LIFO). Ta có thể hình dung Stack là một mảng, một chiều mà việc truy nhập cập nhật nó đều diễn ra ở một đầu của mảng. Sau đây là mô tả quy tắc hoạt động của 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 hàm sau: Procedure Push (N:Integer); {Đưa số N vào Stack} Begin Inc (P); Stack[P]:=N; End; Function Pop: Integer; {Lấy 1 phần tử ra khởi stack} Begin Pop:=Stack[P]; Dec(P); End; Function StackEmpty:Boolean; {Kiểm tra stack có rỗng không} Begin StackEmpty:=P=0; End; Ví dụ: Khử đệ quy thuật toán sắp xếp Quicksort; Const Nmax=5000; Var n, i, j, x, l, r, tg:Integer; s: 0 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 1 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; II. Queue (Hàng đợi) Khác với Stack, Queue là một kiểu dữ liệu trừu tượng mà cơ chế cập nhật truy xuất xảy ra ở hai đầu khác nhau theo quy tắc vào trước ra trước (First In − First Out viết tắt là FIFO). Nếu có thể xác định được kích cỡ cần đến của Queue ta có thể dùng một mảng tĩnh (thay cho một xâu liên kết động) để mô phỏng Queue theo đó, đầu trái của mảng là đầu ra (dùng con trỏ l) đầu phải của mảng là đầu vào (dùng con trỏ r) tương ứng với thủ tục Put, hàm Get một hàm Qfull kiểu Boolean để thông báo Queue đầy hay chưa. Giả sử mảng mô phỏng Queue là Q: Const SizeQ = 5000; Type Td = Record d,c: Integer; End; Var Q: Array [1 SizeQ ] of Td; L,R: Integer;F: Text; Procedure Put (NewOb:Td); {Đưa vào hàng đợi } Begin Inc (R); Q[r-1) div Sizequ +1]: = NewOb; End; Procedure Get(Var FistOb :Td); {lấy ra khỏi hàng đợi } Begin Inc(L); FistOb:=Q[L Mod SizeQư1]; End; Function Qempty:Boolean; {Kiểm tra hàng đợi có rỗng hay không } Begin Qempty:=L – R >0; End; Function Qfull: Boolean; {Kiểm tra xem hàng đợi đã đầy hay chưa } Begin 2 QFull : = r – 1 > SizeQ; End; ứng dụng quan trọng của Queue là giúp giải pháp ″Loang″ hay tìm kiếm theo chiều rộng. Ví dụ: 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. - Dòng cuối ghi 4 số d1, c1,d2, c2: * (d1,c1): toạ độ ô xuất phát. * (d2,c2): Toạ độ ô đích. Nhận xét: Với bài này ta có thể ứng dụng loang theo chiều rộng như sau: Dùng một mảng A[i,j]: + A[i,j] = 0 nếu ô (i,j) có mìn. + A[i,j] = 1 nếu ô (i,j) không có mìn 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} Repeat For { ô kề ô 1} do if {ô để không có mình} then if { ô kề chưa đến} then Begin Nhan [ôkề]: = Nhan [ô] +1; Put (ô kề) End; Until QuEmpty; if Nhan [ô đích] = vô cùng Then { thông báo không đến} Else Repeat Tìm lật ngược kể từ ô đích; Until Nhan [ô i] = 0; Dưỡi đây là toàn bộ chương trình: {$ R-, Q-} Uses Crt; Const Dd:aray[1 8] of -2 2 = (-2,-2,-1.-1, 1, 1, 2, 2); Cc:array[1 8]of -2 2 = (-1, 1, -2, 2, -1,1); Sizequeue = 500; Sodo = 1=1; {in so do duong di} Fo =′ Ma. Out′; Type Size = 0 10; Oco = Record d,c : Size; End; Var A:Array{Size, Size} of Word; Q:Array{1 Sizequeue}ofoco; {queue} d1, c1, d2, c2, n : Size; 3 Maxqueue,l,r : Longint; Procedure Reađata; Var Filename : String [50]; f : Text; k, h : Size ; Begin Clrscr ; Write (′Ten tep du lieu: ′); Readln (Filename); Assign(f,Filename); Reset(f); Readln (f,n); Fillchar (A, Size of (A) , 1); For 1 : = 1 to n do Begin Read (f, k); For r : =1 to k do Begin Read (f, h) ; A [1,h] : = 0; End; Readln (f); End; Readln (f,d1,c1); Close (f) ; End; Procedure Put (oo: oco); Begin Inc(r); If r-1 > Maxqueue then Maxqueue : = r -1; Q{r-1) mod Sizequeue +1] : =oo; End; Procedure Get (Var oo: oco); Begin oo: =Q{ (1-1) mod Sizequeue+1]; Inc (1); End; Function Qempty: Boolean; Begin Qempty: =1>r ; End; Function Qfull: Boolean ; Begin Qfull : = r-1>Sizequeue; End; Function Thuchienduoc: Boolean; {Kiểm tra xem có đường di hay không} Var co,oo1: oco; i:Byte;d,c :Integer; Begin If A{d1,c1} = 0 then Begin Thuchienduoc : = False; Exit; End; Thuchienduoc: = True; 1: = 1; 4 r: = 0; oo. d:= d1; oo.c: = c1; A{d1, c1}:=2; Put (oo); Repeat Get (co); For i : = 1 to 8 do Begin d: = co.d + đ{1}; c : = oo. cc[i]; If (1≤d) and (d≤n) and (1≤c) and (c≤n) then If A[ d, c] = 1 then Begin A {d, c}; i = A[oo.d,oo.c ]+1; If (d=d2 )and (c=c2) then Exit; If qfull then ………… Begin Thuchienduoc : = False; Exit; End; oo1.d:= d; oo1.c:= c ; Put (oo1); End; End; Until Qempty ; Thuchienduoc : = False ; End; Procedure Path {d,c : Size } ; { Tim duong di} Var i , dx, cx : Integer ; Begin If A[d, c] > 2 then Begin For i:=8 Downto 1 do Begin dx : = d + đ [1] ; cx := c+ cc[i]; If (1 ≤ dx) and (dx ≤n) and (1≤ cx) and (cx ≤n) then If A {d,c} = A{x,cx}+1 then Break; End; Path (dx,cx); End; If sodo then Begin If A {d,c}>2 then Write (′——>′) ; Write (′(′ , d, ′, ′, c,′) ′); End ; A{d,c}:=A {d,c} + n * n ; End; 5 Procedure Inkq; Var i, j : Size; ff : Text; Begin Assign (ff,Fo) ; Write (ff) ; If sodo then Writeln; For i : = 1 to n do Begin For j : = 1 to n do If A{ i,j} > n * n then Write( ff,A,[i,j]-n*n -2 :3) Else If A [i,j]=0 then Write(ff, ′ * ′: 3) Else Write (ff,′ ,′:3) ; Writeln (ff) ; End; Close (ff) ; End ; {Main} Begin Reađata ; Repeat Cl r scr ; Writeln (′ Kich thuoc ban co la′ , n,′ x′ , n) ;Writeln (′ 0 xuat phat : (′ , d1,′ .′ , c1,′ )′ ) ; Write (′ 0 can toi: ′ ); Readln (d2, c2); For l: = 1 to n do If A {l, r} > 0 then A {l, r } : = 1 ; Maxqueue : = 0; If Thuchienduoc then Begin Path (d2,c2) ; Inkq ; end Else Writeln {′ khong duoc ! ′ }; Writeln ; Writeln (′ An ESC de thoat, phim khac de tiep tuc !′ ) ; Until Readkey = # 27 ; End. Nguyễn Tấn Thành (sưu tầm) 6 . 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: Procedure Push (N:Integer); {Đưa số N vào Stack} Begin Inc (P); Stack[ P]:=N;. {Lấy 1 phần tử ra khởi stack} Begin Pop: =Stack[ P]; Dec(P); End; Function StackEmpty:Boolean; {Kiểm tra stack có rỗng không} Begin StackEmpty:=P=0; End;

Ngày đăng: 25/08/2013, 22:10

Từ khóa liên quan

Tài liệu cùng người dùng

Tài liệu liên quan