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

Lập trình với các kiểu dữ liệu hàng đợi và ngăn xếp

17 264 0

Đ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 17
Dung lượng 111,15 KB

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

Nội dung

II, Một số thủ tục và hàm cần dùng : -Khởi tạo procedure init; begin dst:=0; end; -Kiểm tra xem Stack ñã rỗng chưa Function StackEmpty:Boolean; Begin StackEmpty:= dst=0; End; -ðưa phần t

Trang 1

1

2

n

Cấu trúc ngăn xếp và hàng ñợi

*****

Nguyễn ðức Huy Tin Lê Khiết 2006-2009

A - Cấu trúc ngăn xếp (stack) :

I, Khái niệm :

1, ðịnh nghĩa :

-ðây là kiểu dữ liệu mà việc cập nhật và truy nhập nó ñều theo nguyên tắc "Vào sau ra trước"( Last In, Firt Out)

2, Khai báo :

Var stack:array[1 1000] of byte;

Dst:integer;

Ý nghĩa : phần tử ñưa vào cuối cùng sẽ ñược lấy ra ñầu tiên

II, Một số thủ tục và hàm cần dùng :

-Khởi tạo

procedure init;

begin

dst:=0;

end;

-Kiểm tra xem Stack ñã rỗng chưa

Function StackEmpty:Boolean;

Begin

StackEmpty:= (dst=0);

End;

-ðưa phần tử mới vào

procedure push(x:byte);

begin

inc(dst);

stack[dst]:=x;

end;

-Lấy phần tử trên cùng ra

function pop:byte;

begin

pop:=stack[dst];

dec(dst);

end;

-ðọc phần tử trên cùng của ngăn xếp

function get:byte;

begin

get:=stack[dst];

end;

III, Ví dụ :

Trang 2

1 Dùng ngăn xếp ñể duyệt sâu

Procedure DFS;

Var x,i:integer;

Begin

Push(1);

Repeat

Pop(x);

For i:=n downto 1 do

If (a[x,i]=1)and(kt[i]=false) then

Begin

Push(i);

Kt[i]:=true;

End;

Until dst=0;

End;

2 ðường ñi ngắn nhất

Cho một lưới ô vuông m x n (1<m,n<=250) gồm các số 0,1 Từ 1 ô số 0 có thể ñi sang các ô 0 chung cạnh và không ñược qua các ô 1 Một người ở 1 ô số 0 bất kì, tìm ñường ngắn nhất ñể người ñó ra ngoài lưới ô vuông, biết ñộ dài ñường ñi là số ô vuông nó chiếm

Bài này mà dùng ñệ quy duyệt thì không tối ưu, ta có thể dùng 2 ngăn xếp chứa tọa ñộ thay vì ñệ quy, dữ liệu xử lí sẽ lớn hơn rất nhiều

Chương trình :

const u:array[1 4] of shortint=(0,0,-1,1);

v:array[1 4] of shortint=(1,-1,0,0);

var a:array[1 250,1 250] of shortint;

m,n,s,t:byte;

stx,sty:array[1 500] of integer; { -hai ngăn xếp -}

dst:integer;

{ -}

function inside(x,y:byte):boolean;

begin

inside:=true;

if (x<1)or(y<1)or(x>m)or(y>n) then inside:=false;

end;

{ -}

function fmin(x,y:byte):shortint;

var i:integer;

min:shortint;

begin

min:=125;

for i:=1 to 4 do

if inside(x+u[i],y+v[i]) then

if (a[x+u[i],y+v[i]]<min)and(a[x+u[i],y+v[i]]>0) then min:=a[x+u[i],y+v[i]];

fmin:=min;

Trang 3

end;

{ -}

procedure nhap;

var f:text;

i,j:integer;

c:char;

begin

assign(f,'path1.inp');

reset(f);

readln(f,m,n);

readln(f,s,t);

for i:=1 to n do

begin

for j:=1 to n do

begin

read(f,c);

if c='1' then a[i,j]:=-1;

end;

readln(f);

end;

close(f);

end;

{ -Lưu vào stack -}

procedure savst(x,y:byte);

begin

inc(dst);

stx[dst]:=x;

sty[dst]:=y;

end;

{ -Lấy ra từ stack -}

procedure popst(var x,y:integer);

begin

x:=stx[dst];

y:=sty[dst];

dec(dst);

end;

{ -}

procedure duyet;

var x,y,i,j:integer;

begin

savst(s,t);

a[s,t]:=1;

repeat

popst(x,y);

Trang 4

for i:=1 to 4 do

if inside(x+u[i],y+v[i]) then

if a[x+u[i],y+v[i]]=0 then

begin

savst(x+u[i],y+v[i]);

a[x+u[i],y+v[i]]:=fmin(x+u[i],y+v[i])+1;

end;

until dst=0;

end;

{ -}

procedure xuat;

var i,min:integer;

f:text;

begin

assign(f,'path.out');

rewrite(f);

min:=maxint;

for i:=1 to m do

begin

if (a[i,1]<min)and(a[i,1]>0) then min:=a[i,1];

if (a[i,n]<min)and(a[i,n]>0) then min:=a[i,n];

end;

for i:=1 to n do

begin

if (a[1,i]<min)and(a[1,i]>0) then min:=a[1,i];

if (a[m,i]<min)and(a[m,i]>0) then min:=a[m,i];

end;

if min=maxint then write(f,-1)

else write(f,min);

close(f);

end;

{ -}

procedure work;

begin

if a[s,t]=-1 then

begin

writeln('Test sai');

readln;

halt;

end;

duyet;

end;

{ -}

BEGIN

Trang 5

nhap;

work;

xuat;

END

3 Tìm chu trình Euler trong một ñồ thị vô hướng bằng cách sử dụng Stack

Chương trình :

Var a:array[1 100,1 100] of integer;

N:byte;

Procedure nhap;

Begin

{ }

end;

function kiemtra:boolean;

var i,j:integer;

begin

kiemtra:=false;

for i:=1 to n do

begin

s:=0;

for j:=1 to n do

s:=s+a[i,j];

if s mod 2 =1 then exit;

end;

kiemtra:=true;

end;

{ -}

procedure euler;

var ce,stack:array[1 500] of byte;

d,top:byte;

begin

top:=1;

stack[top]:=1;

repeat

v:=stack[top];

x:=1;

while (x<=n)and(a[v,x]=0) do

inc(x);

if x>n then

begin

inc(d);

ce[d]:=x;

dec(top);

end

else

Trang 6

begin

inc(top);

stack[top]:=x;

a[v,x]:=0;

a[x,v]:=0;

end;

until top=0;

for x:=1 to d do

write(ce[x],’ ‘);

end;

{ -}

BEGIN

Nhap;

If kiemtra then euler

Else writeln(‘Khong co duong.’);

Readln;

End

4 Tô màu một hình kín

Chương trình :

Var a:array[1 250,1 250] of byte;

Stx,sty:array[1 1000] of byte;

Dst:integer;

x0,y0:byte;

{ -}

procedure push(x,y:byte);

begin

inc(dst);

stx[dst]:=x;

sty[dst]:=y;

end;

{ -}

procedure pop(var x,y:integer);

begin

x:=stx[dst];

y:=sty[dst];

dec(dst);

end;

{ -}

procedure fill(color:byte);

var x,y:integer;

begin

dst:=0;

push(x0,y0);

repeat

Trang 7

pop(x,y);

if (inside(x,y))and(a[x,y]<>color) then

begin

a[x,y]:=color;

if x<n then push(x+1,y);

if x>1 then push(x-1,y);

if y<n then push(x,y+1);

if y>1 then push(x,y-1);

end;

until dst=0;

end;

5 Cho ma trận 0,1 Có thể ñi qua các ô 0, cho tọa ñộ 2 ô 0, kiểm tra xem chúng có liên thông không

Chương trình :

Var a:array[1 100,1 100] of byte;

n:byte;

dst:integer;

x1,x2,y1,y2:byte;

stx,sty:array[1 1000] of byte;

{ -}

procedure push(x,y:byte);

begin

inc(dst);

stx[dst]:=x;

sty[dst]:=y;

end;

{ -}

procedure pop(var x,y:integer);

begin

x:=stx[dst];

y:=sty[dst];

dec(dst);

end;

{ -}

function kiemtra:boolean;

var x,y,i,j:byte;

begin

push(x1,y1);

repeat

pop(i,j); x:=i; y:=j;

{ -}

while (a[x,y-1]=0)and(y-1>0) do

begin

a[x,y]:=1; dec(y);

Trang 8

end; push(x,y); y:=j

{ -}

while (a[x,y+1]=0)and(y<n) do

begin

a[x,y]:=1; inc(y);

end; push(x,y); y:=j;

{ -}

while (a[x-1,y]=0)and(x-1>0) do

begin

a[x,y]:=1; dec(y);

end; push(x,y); x:=i;

{ -}

while (a[x+1,y]=0)and(x<0) do

begin

a[x,y]:=1; inc(y);

end; push(x,y);

{ -}

until (dst=0)or((stx[dst]=x2)and(sty[dst]=y2));

if dst=0 then kiemtra:=false

else kiemtra:=true;

end;

6 Khử ñệ quy thuật toán sắp xếp Quicksort

Chương trình :

{=======================}

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 1 , r : Integer; End;

Procedure Sort;

Begin

S:=1;

Stack [s] 1:=1;

Stack [s] r :=n ;

Repeat

1:=Stack[s] 1 ;

r: = Stack [s] r;

Dec(s);

Repeat

x:=A[ (1+r)div 2];

While a[i] < x Do Inc(i);

Trang 9

While a [j] > x Do Dec (j);

Until i >j;

If i < r then

Stack [s] 1 : = 1;

Until 1> r ;

Until S= 0;

End;

7 Thuật toán tô màu ñồ thị

Bài tập áp dụng :

1 Cho bảng vuông n x n Tại ô (i,j) là ô ñen, còn lại ñều là ô trắng Tìm cách ñặt sau cho mỗi dòng, mỗi cột có ñúng 1 ô ñen

B - Cấu trúc hàng ñợi (queue) :

B1 – Hàng ñợi bình thường :

I, Khái niệm:

1, ðịnh nghĩa :

-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 và truy xuất xảy

ra ở hai ñầu khác nhau và theo quy tắc vào trước ra trước ( First In - First Out)

2, Khai báo :

Var queue:array[1 1000] of byte;

Last, first:integer;

Ý nghĩa : với cấu trúc này, phần tử ñưa vào trước ñược lấy ra trước

* Khuyết ñiểm :ðối với hàng ñợi thường khi thêm vào ở Last và loại bỏ ở First, phần sử dụng của hàng có khuynh hướng di chuyển về phía dưới, và ñến một lúc nào ñó thì ta không thể thêm phần tử mới vào hàng nữa (vì số phần tử tối ña của hàng là cố ñịnh) Khi

ñó ta nói rằng hàng bị tràn

II, Một số thủ tục và hàm cần dùng :

-Khởi tạo

Procedure Init;

Begin

First:=1; Last:=0;

End;

Trang 10

1

2

n

-Kiểm tra xem hàng ñợi ñã rỗng chưa

Function QueueEmpty : Boolean;

Begin

QueueEmpty : =First>last;

End;

-ðưa phần tử mới vào

procedure push(x:byte);

begin

inc(last);

queue[last]:=x;

end;

-Lấy phần tử dưới cùng ra

function pop:byte;

begin

If not QueueEmpty then

begin

pop:=queue[first];

inc(first);

end;

end;

B2 – Hàng ñợi vòng :

I, Khai báo :

Var queue:array[1 max] of byte;

Last, first:integer;

Hàng ñợi vòng là cải tiến của hàng ñợi bình thường ñể sử dụng tối ña mảng hàng ñợi

II, Các thủ tục ñược cải tiến :

-ðưa phần tử mới vào

procedure push(x:byte);

begin

last:=(last+1) mod max; { Ta cho vị trí của n quay 1 vòng }

queue[last]:=x; { giống như 1 cây kim ñồng hồ }

end; { sau 1 vòng trở về chỗ cũ, ñi hết n vị trí }

-Lấy phần tử dưới cùng ra

function pop:byte;

begin

If not QueueEmpty then

begin

pop:=queue[first];

first:=(first+1) mod max;

end;

end;

B3, Bài tập ví dụ :

1 Dùng hàng ñợi ñể duyệt rộng trên ñồ thị

N=1 N-1

Trang 11

var a:array[1 250,1 250] of byte;

kt:array[1 250] of boolean;

Procedure BFS;

Var x,i:integer;

Begin

Push(1);

Repeat

Pop(x);

For i:=1 to n do

If (a[x,i]=1)and(kt[i]=false) then

Begin

Push(i);

Kt[i]:=true;

End;

Until first>last;

End;

2 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ứ i 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ố x1, y1,x2, y2:

* (x1,y1): toạ ñộ ô xuất phát

* (x2,y2) : Toạ ñộ ô ñích

Chương trình :

const fi='baimin.inp';

u:array[1 8] of -2 2 =(1,2,2,1,-1,-2,-2,-1);

v:array[1 8] of -2 2 =(2,1,-1,-2,-2,-1,1,2);

type oo=record

x,y:shortint;

end;

var a:array[-1 50,-1 50] of oo; { ô a[i,j] =(0,0) nếu không có mìn và

n,kq:byte; chưa ñược ñi qua, (x,y) nếu từ ô (x,y)

q:array[1 2500] of oo; ngựa nhảy tới ô (i,j) và (100,100)

first,last:integer; nếu có mìn }

xp,fn:oo;

procedure nhap;

var f:text;

tg:oo;

i,k,j,t:integer;

begin

Trang 12

kq:=0;

tg.x:=100;

tg.y:=100;

assign(f,fi);

reset(f);

readln(f,n);

for i:=1 to n do

begin

read(f,k);

for j:=1 to k do

begin

read(f,t);

a[i,t]:=tg;

end;

end;

read(f,xp.x,xp.y);

a[xp.x,xp.y]:=tg;

read(f,fn.x,fn.y);

close(f);

last:=0;

first:=1;

end;

function empty:boolean;

begin

empty:= first>last;

end;

procedure push(m:oo);

begin

last:=(last+1)mod 2500;

q[last]:=m;

end;

procedure pop(var x:oo);

begin

if not empty then

begin

x:=q[first];

first:=(first+1) mod 2500;

end;

end;

function inside(o:oo):boolean;

begin

inside:=(1<=o.x)and(o.x<=n)and(1<=o.y)and(o.y<=n);

end;

function ok(o:oo):boolean;

x

x

x

x

x

x

ð

ð

S

F

(1,1)->(2,3)->(3,1)->(4,3)

Trang 13

begin

ok:=(a[o.x,o.y].x=0)and(a[o.x,o.y].y=0)and(inside(o));

end;

procedure xuat;

var o:oo;

begin

o:=fn;

kq:=1;

while (o.x<>xp.x)or(o.y<>xp.y) do

begin

write('(',o.x,',',o.y,') <-');

o:=a[o.x,o.y];

end;

write('(',o.x,',',o.y,')');

end;

procedure main;

var o,otg:oo;

i:integer;

b,dc:byte;

procedure restore;

begin

first:=first-1;

if first=0 then first:=2500;

a[q[first].x,q[first].y].x:=0;

a[q[first].x,q[first].y].y:=0;

first:=(first+1) mod 2500;

end;

begin

push(xp);

repeat

pop(o);

dc:=0;

inc(b);

for i:=1 to 8 do

begin

otg.x:=o.x+u[i];

otg.y:=o.y+v[i];

if ok(otg) then

begin

a[otg.x,otg.y]:=o;

if(otg.x=fn.x)and(otg.y=fn.y) then

begin

xuat;

break;

Trang 14

end;

dc:=1;

push(otg);

end;

end;

if(i=8)and(dc=0) then

restore;

until empty;

if kq=0 then writeln('Can not');

end;

Begin

nhap;

main;

readln;

end

3 Bài toán ñong nước :

Cho 2 bình dung tích lần lượt là m và n ( lít) Với nguồn nước không hạn chế, dùng 2 bình trên ñể ñong k lít nước với k<min(m,n)

Ví dụ : m = 5, n = 4, k =3

(0,0) -> (0,4) -> (4,0) -> ( 4,4) -> (5,3)

Chương trình :

Program donuoc;

type

trangthai = record

x,y,tt,truoc: integer;

end;

maxQ=0 1000;

mangTT=array[maxQ] of trangthai;

var

n, m, k: byte;

MO,DONG,Stack: mangtt;

topM,bottomM,topD,bottomD,top:maxQ;

xp:trangthai;

procedure sPush(var s:mangTT;var top:maxQ;u:trangthai);

begin

top:=top+1;

s[top]:=u;

end;

procedure sPop(s:mangtt;var top:maxQ;var u:trangthai);

begin

u:=s[top];

top:=top-1;

Trang 15

end;

procedure qPush(var Q:mangTT;var top,bottom:maxQ;u:trangthai);

begin

top:=top+1;

Q[top]:=u;

if bottom=0 then bottom:=1;

end;

procedure qPop(Q:mangtt;var top,bottom:maxQ;var u:trangthai);

begin

u:=Q[bottom];

if bottom=top then begin bottom:=0;top:=0;end

else bottom:=bottom+1;

end;

function ktThuocHD(x,y:byte;top,bottom:maxq;Q:mangtt):boolean;

var i:maxQ;

begin

if bottom=0 then ktthuocHD:=false

else

begin

i:=bottom;

While (i<=top) and ((q[i].x<>x) or (q[i].y<>y )) do

i:=i+1;

ktthuochd:=(i<=top);

end;

end;

procedure ChuyenTT(u:trangthai;var v:trangthai;i:byte);

begin

case i of

1: begin v.x:=n; v.y:=u.y;end;

2: begin v.x:=u.x; v.y:=m; end;

3: begin v.x:=0; v.y:=u.y;end;

4: begin v.x:=u.x; v.y:=0;end;

5: if (u.x+u.y <= m) then begin v.x:=0; v.y:=u.x+u.y;end

else begin v.x:= u.x+u.y-m; v.y:=m;end;

6: if u.x+u.y <= n then begin v.x:=u.x+u.y; v.y:=0; end

else begin v.y:=u.x+u.y-n; v.x:=n;end

end;

end;

Procedure inkq;

var i,j:maxq;u:trangthai;

begin

Trang 16

i:=topd;

while dong[i].tt<>0 do

begin

j:=dong[i].truoc;

spush(mo,top,dong[i]);

while dong[i].tt<>j do i:=i-1;

end;

{ spush(mo,top,dong[i]);}

while Top<>1 do

begin

spop(mo,top,u);

write('(',u.x,',',u.y,') >');

end;

spop(mo,top,u);

writeln('(',u.x,',',u.y,')');

end;

procedure bfs(u: trangthai);

var

n,m:trangthai;

tt:maxq;i:byte;

begin

qPush(MO,topm,bottomM,u);

tt:=1;

while bottomM<>0 do

begin

qPop(Mo,topm,bottomM,n);

qPush(Dong,topd,bottomd,n);

for i:=1 to 6 do

begin

chuyenTT(n,m,i);

if (not ktthuochd(m.x,m.y,topm,bottomM,Mo) ) and

(not ktthuochd(m.x,m.y,topd,bottomd,dong) ) then

begin

tt:=tt+1;

m.tt:=tt;

m.truoc:=n.tt;

qPush(Mo,topm,bottomM,m);

if (m.x=k) or (m.y=k) then

begin qpush(dong,topd,bottomd,m);inkq; exit; end;

end;

end;

end;

writeln('Khong thanh cong');

Trang 17

end;

procedure KhoiTao;

begin

write('Nhap n, m va k:');

readln(n,m,k);

xp.x:=0;xp.y:=0;xp.tt:=1;xp.truoc:=0;

topm:=0;bottomm:=0;topd:=0;bottomd:=0;

top:=0

end;

BEGIN

khoitao;

bfs(xp);

readln;

END

Bài tập áp dụng :

1 Bài toán mã ñi tuần : Cho bàn cờ n x n Con mã ñứng tại ô (x0,y0), hãy tìm một ñường

ñi ñể con mã ñi qua tất cả các ô bàn cờ, mỗi ô một lần

Ngày đăng: 03/01/2016, 18:53

TỪ KHÓA LIÊN QUAN

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

w