Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 39 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
39
Dung lượng
458,5 KB
Nội dung
CẤU TRÚC DỮ LIỆU ĐỘNG
MỞ ĐẦU
Cấu trúc dữ liệu là một lĩnh vực nghiên cứu lâu đời của khoa học máy
tính. Hầu hết các chương trình được viết ra, chạy trên máy tính, dù lớn hay nhỏ,
dù đơn giản hay phức tạp, đều phải sử dụng cấu trúc dữ liệu. Việc hiểu biết về
các cấu trúc dữ liệu giúp các lập trình viên có nhiều lựa chọn hơn trong việc đưa
ra các giải pháp hiệu quả giải quyết các bài toán tin.
Với các cấu trúc dữ liệu được xây dựng từ các kiểu cơ sở như: kiểu thực,
kiểu nguyên, kiểu ký tự... hoặc từ các cấu trúc đơn giản như mẩu tin, tập hợp,
mảng... lập trình viên có thể giải quyết hầu hết các bài toán đặt ra. Các đối tượng
dữ liệu được xác định thuộc những kiểu dữ liệu này có đặc điểm chung là không
thay đổi được kích thước, cấu trúc trong quá trình sống, do vậy thường cứng
nhắc, gò bó khiến đôi khi khó diễn tả được thực tế vốn sinh động, phong phú.
Các kiểu dữ liệu kể trên được gọi là các kiểu dữ liệu tĩnh.
Một số đối tượng dữ liệu trong chu kỳ sống của nó có thể thay đổi về cấu
trúc, độ lớn, như danh sách các học viên trong một lớp học có thể tăng thêm,
giảm đi... Khi đó nếu cố tình dùng những cấu trúc dữ liệu tĩnh đã biết như mảng
để biểu diễn những đối tượng đó lập trình viên phải sử dụng những thao tác phức
tạp, kém tự nhiên khiến chương trình trở nên khó đọc, do đó khó bảo trì và nhất
là khó có thể sử dụng bộ nhớ một cách có hiệu quả.
Do bản chất của các dữ liệu tĩnh, chúng sẽ chiếm vùng nhớ đã dành cho
chúng suốt quá trình hoạt động của chương trình. Tuy nhiên, trong thực tế, có
thể xảy ra trường hợp một dữ liệu nào đó chỉ tồn tại nhất thời hay không thường
xuyên trong quá trình hoạt động của chương trình. Vì vậy việc dùng các CTDL
tĩnh sẽ không cho phép sử dụng hiệu quả bộ nhớ.
Do vậy, nhằm đáp ứng nhu cầu thể hiện sát thực bản chất của dữ liệu cũng
như xây dựng các thao tác hiệu quả trên dữ liệu, cần phải tìm cách tổ chức kết
hợp dữ liệu với những hình thức mới linh động hơn, có thể thay đổi kích thước,
cấu trúc trong suốt thời gian sống. Các hình thức tổ chức dữ liệu như vậy được
gọi là cấu trúc dữ liệu động. Trong khuôn khổ tài liệu này, tác giả sẽ giới thiệu
về một số cấu trúc dữ liệu động đặc biệt như danh sách liên kết, ngăn xếp và
hàng đợi và một số ứng dụng của chúng đặc biệt trong việc khử đệ qui.
Tác giả rất mong nhận được những đóng góp của các thầy, cô giáo và học
sinh để chuyên đề này được hoàn thiện hơn.
Xin trân trọng cảm ơn.!
MỤC LỤC
1. DANH SÁCH LIÊN KẾT.......................................................................................................3
1.1 Khái niệm..........................................................................................................................3
1. 2 Cấu tạo của danh sách liên kết.........................................................................................4
1.3 Các thao tác cơ bản với danh sách liên kết........................................................................4
1. 3. 1 Khai báo....................................................................................................................4
1.3.2 Khởi tạo danh sách.....................................................................................................4
1.3.3 Bổ sung một nút vào đầu danh sách...........................................................................4
1.3.4. Bổ sung một nút vào cuối danh sách.........................................................................5
1.3.5 Duyệt danh sách.........................................................................................................5
1.3.6 Bổ sung một nút vào sau nút được trỏ bởi p...............................................................5
1.3.7. Xoá một nút khỏi danh sách......................................................................................6
1.4. Mảng hay danh sách liên kết?..........................................................................................6
1.5. Ví dụ làm việc với danh sách liên kết..............................................................................7
2. NGĂN XẾP – STACK..........................................................................................................14
2.1. Khái niệm.......................................................................................................................14
2.2 Các thao tác cơ bản của ngăn xếp....................................................................................14
2.4. Ứng dụng Stack..............................................................................................................15
2.4.1 Ứng dụng Stack khử đệ quy.....................................................................................15
2.4.2 Tính giá trị một biểu thức dạng hậu tố.....................................................................22
2.4.3 Chuyển biểu thức từ trung tố sang hậu tố.................................................................25
3. HÀNG ĐỢI – Queue.............................................................................................................27
3.1. Khái niệm.......................................................................................................................27
3.2 Các thao tác cơ bản của hàng đợi....................................................................................28
3.3. So sánh việc cài đặt Queue bằng mảng và danh sách liên kết........................................31
3.4 Ứng dụng.........................................................................................................................31
2
1. DANH SÁCH LIÊN KẾT
Danh sách là một dãy hữu hạn các phần tử thuộc cùng một lớp đối tượng
nào đó. Ví dụ : danh sách sinh viên, danh sách vật tư, danh sách các hoá đơn,
danh sách các số thực. Chúng ta đã dùng mảng để biểu thị một danh sách, cách
này có các nhược điểm: kích thước của mảng phải định trước nên tốn bộ nhớ (số
phần tử thực tế dùng nhiều khi rất ít so với khai báo), khi thêm một phần tử vào
mảng hoặc xoá một phần tử ra khỏi mảng ta phải mất nhiều thời gian để dồn
mảng.
Danh sách liên kết dùng để cài đặt một danh sách sẽ khắc phục được các
nhược điểm trên của mảng.
1.1 Khái niệm
R. Sedgewick (Alogrithms in Java – 2002) định nghĩa danh sách liên kết
như sau: Danh sách liên kết là một cấu trúc dữ liệu bao gồm một tập các phần tử,
trong đó mỗi phần tử là một phần của một nút có chứa liên kết đến phần tử kế
tiếp.
“Mối phần tử là một phần của một nút” vì mỗi nút có ít nhất hai trường,
một trường gọi là dữ liệu (data), trường còn lại là trường liên kết trỏ đến nút tiếp
theo trong danh sách.
Trường liên kết của phần tử thứ i của danh sách sẽ trỏ tới phần tử thứ
(i+1) của danh sách. Tuy nhiên nó cũng có thể trỏ đến chính nó.
Có thể nói danh sách liên kết là một cấu trúc dữ liệu được định nghĩa kiểu
đệ quy, vì trong định nghĩa một nút của danh sách có tham chiếu tới khái niệm
nút.
Có nhiều loại danh sách liên kết khác nhau tùy thuộc vào cấu trúc của mỗi
phần tử trong danh sách (số trường liên kết với các phần tử khác trong danh
sách) nhưng cơ bản nhất là danh sách liên kết đơn (single linked list), mỗi phần
tử có một trường liên kết như trên hình vẽ minh họa, và khi chúng ta nói đến
danh sách liên kết, nếu không có các chú giải đi kèm thì ngầm hiểu đó là danh
sách liên kết đơn.
Danh sách liên kết kép: mỗi phần tử liên kết với các phần tử đứng trước và sau
nó trong danh sách:
Danh sách liên kết vòng : phần tử cuối danh sách liên kết với phần tử đầu danh
sách:
3
1. 2 Cấu tạo của danh sách liên kết
Cấu tạo của danh sách liên kết: có một con trỏ First chứa địa chỉ của phần
tử đầu tiên của danh sách, phần tử đầu có phần dữ liệu và một con trỏ Next để
chứa địa chỉ của phần tử thứ hai, tổng quát phần tử thứ i có phần dữ liệu và một
con trỏ next để chứa địa chỉ của phần tử thứ i+1, đối với phần tử cuối cùng giá
trị của con trỏ next bằng NIL. Để thuận tiện khi thêm phần tử mới vào cuối danh
sách liên kết ta dùng một con trỏ Last chứa địa chỉ của phần tử cuối cùng. Khởi
tạo một danh sách rỗng first = NIL.
Nhắc lại 2 thủ tục cơ bản với biển trỏ:
+ Cấp phát vùng nhớ cho biến trỏ p: New(p)
+ Giải phóng vùng nhớ cho biến trỏ p: Dispose(p)
1.3 Các thao tác cơ bản với danh sách liên kết
1. 3. 1 Khai báo
Để khai báo một danh sách động trước hết ta khai báo kiểu của mỗi nút
trong danh sách.
Type = ^ ;
= Record
Data: DataType;
Next: ;
End;
Var
First: ;
First là địa chỉ của nút đầu tiên trong danh sách, dựa vào trường next của
nút này ta bết được địa chỉ của nút thứ hai, cứ như vậy ta biết được địa chỉ của
tất cả các nút trong danh sách.
1.3.2 Khởi tạo danh sách
First : =Nil;
1.3.3 Bổ sung một nút vào đầu danh sách
+Tạo ra nút mới
New(p);
p^.Data :=X;
+ Bổ sung vào đầu danh sách
p^.Next :=First;
4
First :=p;
1.3.4. Bổ sung một nút vào cuối danh sách
Xuất phát danh sách không có nút nào cả. Nút mới thêm vào sẽ nằm cuối
danh sách. Khi đó ta cần hai biến con trỏ First và Last lần lượt trỏ đến các nút
đầu và cuối danh sách.
Procedure Khoitao;
var p: TroNut;
Begin
First := nil; Last:= nil;
While do
Begin
New(p);
Readln(p^.data);
p^.Next := Nil;
If First = Nil then First := p
Else Last^.next := p;
Last := p;
End;
End;
1.3.5 Duyệt danh sách
Duyệt danh sách là thăm và xử lý từng nút trong danh sách.
Procedure Duyet;
Var p: TroNut;
Begin
P := First;
While p nil do
Begin
;
P := p^.Next; {duyệt qua nút tiếp
theo}
End;
End;
1.3.6 Bổ sung một nút vào sau nút được trỏ bởi p
Thủ tục sau thực hiện việc bổ sung một nút có nội dung x vào sau nút
được trỏ bởi p.
Procedure Bosung(p,x);
Var
q: TroNut;
Begin
New(q);
q^.data:=x;
if first = nil then
begin
q^.next := nil;
5
end
else
begin
first := q;
q^.next:= p^.next;
p^.next:= q;
End;
end;
1.3.7. Xoá một nút khỏi danh sách
Thủ tục sau thực hiện việc xóa một nút trỏ bởi p ra khỏi danh sách.
Procedure Xoa(p);
Var
q: TroNut;
Begin
if First = nil then exit;
if p = First then
First := First^.next
else
begin
q:= First;
While q^.next p do
q:= q^.next;
q^.next:= p^.next;
end;
Dispose(p);
End;
1.4. Mảng hay danh sách liên kết?
Chúng ta đã từng làm quen với kiểu mảng, lưu danh sách gồm nhiều thành
phần có cùng kiểu. Mỗi thành phần là một biến tĩnh và số lượng thành phần của
danh sách là cố định. Tuy nhiên việc sử dụng mảng có các nhược điểm: kích
thước của mảng phải định trước nên tốn bộ nhớ (số phần tử thực tế dùng nhiều
khi rất ít so với khai báo), khi thêm một phần tử vào mảng hoặc xoá một phần tử
ra khỏi mảng ta phải mất nhiều thời gian để dồn mảng. Danh sách liên kết dùng
để cài đặt một danh sách sẽ khắc phục được các nhược điểm trên của mảng.
Tuy nhiên không thể kết luận phương pháp cài đặt nào hiệu quả hơn, mà
nó hoàn toàn tuỳ thuộc vào từng ứng dụng hay tuỳ thuộc vào các phép toán trên
danh sách. Tuy nhiên ta có thể tổng kết một số ưu nhược điểm của từng phương
pháp làm cơ sở để lựa chọn phương pháp cài đặt thích hợp cho từng ứng dụng:
Cài đặt bằng mảng đòi hỏi phải xác định số phần tử của mảng, do đó nếu
không thể ước lượng được số phần tử trong danh sách thì khó áp dụng cách cài
đặt này một cách hiệu quả vì nếu khai báo thiếu chỗ thì mảng thường xuyên bị
đầy, không thể làm việc được còn nếu khai báo quá thừa thì lãng phí bộ nhớ.
6
Cài đặt bằng con trỏ thích hợp cho sự biến động của danh sách, danh sách
có thể rỗng hoặc lớn tuỳ ý chỉ phụ thuộc vào bộ nhớ tối đa của máy. Tuy nhiên
ta phải tốn thêm vùng nhớ cho các con trỏ (trường next).
Cài đặt bằng mảng thì thời gian xen hoặc xoá một phần tử tỉ lệ với số phần
tử đi sau vị trí xen/ xóa. Trong khi cài đặt bằng con trỏ các phép toán này mất
chỉ một hằng thời gian.
Phép truy nhập vào một phần tử trong danh sách chỉ tốn một hằng thời
gian đối với cài đặt bằng mảng, trong khi đối với danh sách cài đặt bằng con trỏ
ta phải tìm từ đầu danh sách cho đến vị trí trước vị trí của phần tử hiện hành. Nói
chung danh sách liên kết thích hợp với danh sách có nhiều biến động, tức là ta
thường xuyên thêm, xoá các phần tử.
1.5. Ví dụ làm việc với danh sách liên kết
Xét danh sách liên kết đơn biểu diễn một dãy số nguyên. Nút đầu tiên trong
danh sách được trỏ bởi First. Cho khai báo mỗi nút trong danh sách như sau:
Type TroNut = ^ Nut;
Nut = Record
Data: Integer;
Next: TroNut;
End;
Var
First: TroNut;
Viết chương trình thực hiện các yêu cầu sau:
a. Nhập dãy các số nguyên và lưu vào danh sách có nút đầu trỏ bởi First, quá
trình nhập dừng khi dữ liệu đưa vào không phải là số nguyên.
Program Vi_du_1;
Type TroNut = ^ Nut;
Nut = Record
Data: Integer;
Next: TroNut;
End;
Var First: TroNut;
p: pointer;
Procedure Nhap;
Var
n:integer;
kq:boolean;
last,p: tronut;
begin
first:=nil;
last:= nil;
repeat
7
write(‘Nhap gia tri mot nut – Ket thuc
bang ky tu Q: ‘);
{$I-}
readln(n);
{$I+}
kq:= IOResult=0;
if kq then
begin
new(p);
p^.Data:=n;
p^.Next:=nil;
if first = nil then
first:= p;
else
last^.Next:= p;
last:=p;
end;
until not kq;
end;
b. In ra màn hình giá trị các nút lớn hơn 0.
Procedure In_so_duong;
Var
p: Tronut;
begin
p:= first;
while p nil do
begin
if p^.Data > 0 then
write(p^.Data:8);
p:=p^.Next;
end;
end;
Begin
Mark(p);
Nhap;
In_so_duong;
Release(p);
Readln;
End.
c. Viết thủ tục đếm số nút có giá trị lớn hơn 0 và tính giá trị trung bình cộng
của các nút đó.
8
Procedure Nut_duong(var dem: word; tb:real);
Var
p: Tronut;
tong:longint;
begin
dem:=0;
tong:=0;
p:= first;
while p nil do
begin
if p^.Data > 0 then
begin
inc(dem);
tong:=tong+p^.Data;
end;
p:=p^.Next;
if dem = 0 then
tb:=0
else
tb:= tong /dem;
end;
d. Giả sử dãy giá trị các nút trong danh sách đã được sắp tăng dần. Viết các
thủ tục và hàm sau:
Procedure Insert(var first: TroNut; m: integer) thực hiện việc bổ sung một
nút vào danh sách sao cho tính tăng dần được bảo toàn.
Procedure Insert(var first: TroNut; m: integer);
Var
p,q: Tronut;
begin
new(p);
p^.Data:= m;
if (first = nil) or (first^.Data < m ) then
begin
p^.Next:=nil;
first:= p;
end
else
begin
q:= first;
while (q^.Next nil) and
((q^.Next)^.Data < m) do
q:= q^.Next;
9
end;
p^.Next:= q^.Next;
q^.Next:= p;
end;
Procedure InitList thực hiện việc tạo danh sách có tính chất trên bằng cách
nhập dữ liệu từ bàn phím và quá trinh nhập dừng khi nhấn phím ESC (yêu cầu:
sử dụng thủ tục Insert).
Procedure InitList;
Var
m: integer;
Begin
first:= nil;
repeat
write(‘Nhap gia tri cua mot nut: ‘);
readln(m);
insert(first,m);
until readkey = #27;
end;
Procedure List(First: TroNut) in dãy giá trị các nút trong danh sách.
Procedure List(First: Tronut);
Var
p:Tronut;
begin
p:= first;
while p nil do
begin
write(p^.Data);
p:=p^.Next;
end;
end;
Procedure DeleteZero( Var First: TroNut) thực hiện việc xoá tất cả các nút có
giá trị 0 trong danh sách.
Procedure DeleteZero(Var First: TroNut);
var
p,q: Tronut;
begin
p:= first;
while (p nil) and (p^.Data < 0) do
begin
q:= p;
p:= p^.Next;
10
end;
while (p nil) and (p^.Data = 0) do
begin
q^.Next:= p^.Next;
dispose(p);
p:= q^.Next;
end;
end;
Function TroMax(First: TroNut): TroNut trả về địa chỉ của nút đầu tiên đạt
giá trị lớn nhất (tính từ đầu danh sách, nếu có, ngược lại hàm trả về giá trị Nil).
Function Tromax(First: TroNut);
var
p.q: Tronut;
m:integer;
begin
if first = nil then
TroMax:= nil
else
begin
p:= first;
m:= p^.Data;
q:= p^.Next;
while (q nil) do
begin
if q^.Data > m then
begin
p:= q;
m:= p^.Data;
end;
q:= q^.Next;
end;
TroMax:=p;
end;
end;
e. Giả sử danh sách khác rỗng. Viết các thủ tục và hàm sau:
Function DataMax(First: TroNut): integer trả về giá trị lớn nhất của nút có
trong danh sách.
Function DataMax(First: TroNut): integer;
var
m: integer;
p, q: Tronut;
begin
11
p:= first;
m:= p^.Data;
q:= p^.Next;
while q nil do
begin
if q^.Data > m then
m:=q^.Data;
q:= q^.Next;
DataMax:= m;
end;
Function DataMin(First: TroNut): Integer trả về giá trị nhỏ nhất của nút có
trong danh sách.
Function DataMax(First: TroNut): integer;
var
m: integer;
p,q: Tronut;
begin
p:= first;
m:= p^.Data;
q:= p^.Next;
while q nil do
begin
if q^.Data < m then
m:=q^.Data;
q:= q^.Next;
DataMin:= m;
end;
f. Cho danh sách liên kết đơn có nút đầu trỏ bởi First, được khai báo như
sau
Type
TroNut = ^nut;
Nut = Record
Data: real;
Next: TroNut;
End;
Var
First: Tronut;
Viết các thủ tục và hàm sau:
Function Search(First: TroNut; k: word): TroNut trả về địa chỉ của nút thứ k
(nếu có, ngược lại, hàm trả về giá trị Nil).
Function Search(First: TroNut; k: word): Tronut;
Var
d: word;
12
Begin
p: Tronut;
d:=0;
p:=first;
while (p nil) do
begin
inc(d);
if d = k then
break;
p:= p^.next;
end;
Search:= p;
End;
Procedure Delete_K(Var First: TroNut; k: word) thực hiện việc xoá nút thứ k
trong danh sách (nếu có).
Procedure Delete_K(Var first: Tronut; k:word);
var
d: word;
p,q: Tronut;
begin
d:=1;
p:= first;
while (p nil) and (d Nil Do
Begin
GT:=GT* Top(S);
Pop(S);
End;
Writeln (GT);
End;
b) Bài toán tính số Fibonaci
Dãy số Fibonaci xác định như sau: Bắt đầu từ 2 số 0 và 1 tiếp sau đó là
các số Fibonaci sau bằng tổng của 2 số Fibonaci trước đó.
F1=0; F2=1; FN = FN-1+ FN-2 ∀ N ≥ 2
Ví dụ dãy số Fibonaci: 0 1 1 2 3 5 8…
Đệ quy hàm Fibonaci như sau:
Function Fibo(N:Integer): Longint;
16
Begin
If N=1 then Fibo:=0
Else If N=2 then Fibo:=1
Else Fibo:=Fibo(N-1) * Fibo(N-2);
End;
Khử đệ quy bằng Stack:
S: Stack;
Fibo: Longint;
Khoitao(S);
If (N=0) or (N=1) then Fibo:=N
Else
Begin
Push(N,S);
While N0 Do
Begin
N:=N-1;
Push(N,S);
End;
If Top(S) 2 then
Begin
T:=0;
Pop(S);
K:= 1;
Pop(S);
End;
Whike Not Stack_empty Do
Begin
Fibo:=T+K;
T:=K;
K:=Fibo;
Pop(S);
End;
End;
Writeln(Fibo);
c) Khử đệ quy thuật toán sắp xếp Quicksort
B1: Khởi tạo một stack rỗng
B2: Mảng A ta đang xét từ phần tử thứ 1 đến phần tử thứ N, gán L:=1,
R:=N, đẩy hai giá trị 1 và N vào Stack.
B3: Lấy lại L, R từ Stack ra
B4: Phân hoạch dãy A[L]..A[R] thành hai dãy: A[L]..A[j-1] và dãy
A[j+1]...A[R]
B5: Nếu j+1 < R thì đẩy (j+1) và R vào Stack.
17
B6: Nếu L< j-1 thì quay lại bước 4 để phân hoạch dãy A[L]..A[j-1] nếu
không chuyển sang bước 7.
B7: Nếu Stack khác rỗng thì quay lại B3 để phân hoạch tiếp, nếu Stack
rỗng thì kết thúc.
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
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].1: = 1;
Stack [s].r:=r;
End;
r:=j;
Until 1>r ;
Until S=0;
End;
e) Cài đặt thuật toán Tìm kiếm theo chiều sâu bằng ngăn xếp
18
Cho đơn đồ thị vô hướng G=(V,E) gồm N đỉnh, M cạnh. Các đỉnh được
đánh số thứ tự từ 1 đến N. Xuất phát tại đỉnh S, Tìm đường đi từ đỉnh xuất phát
S đến đỉnh kết thúc F;
Tư tưởng dùng đệ quy của thuật toán tìm kiếm theo chiều sâu (DFS):
Trước hết, mọi đỉnh x kề với S tất nhiên sẽ đến được từ S. Với mỗi đỉnh x kề với
S đó thì tất nhiên những đỉnh y kề với x cũng đến được từ S. Điều đó gợi ý cho
ta viết một thủ tục đệ quy DFS(u) mô tả việc duyệt từ đỉnh u bằng cách thông
báo thăm đỉnh u và tiếp tục quá trình duyệt DFS(v), với v là một đỉnh chưa thăm
kề với u. Để không một đinh nào bị liệt kê tới 2 lần, ta sử dụng kĩ thuật đánh
dấu, mỗi lần thăm một đỉnh, ta đánh dẫu đỉnh đó lại để các bước duyệt đệ quy kế
tiếp không duyệt lại đỉnh đó nữa. Để lưu lại đường đi từ đỉnh xuất phát S, trong
thủ tục DFS(u), trước khi gọi đệ quy DFS(v), với v kề với u mà chưa đánh dấu,
ta lưu lại vết đường đi từ u->v bằng cách Trace[v]:=u, tức là trước khi đến đỉnh
v là đỉnh u.
Procedure DFS(u:integer);
Var v: Integer;
Begin
Begin
Trace[v]:=u;
DFS(v);
End;
End;
Khi mô tả quá trình đệ quy bằng ngăn xếp, ta luôn luôn để cho ngăn xếp
để lưu lại dây chuyền duyệt sâu từ nút gốc (đỉnh xuất phát S).
< Thăm S, đánh dấu S đã thăm>
< Đẩy S vào ngăn xếp>
Repeat
< Lấy u khỏi ngăn xếp>
If < u có đỉnh kề chưa thăm> then
Begin
< Chỉ chọn một đỉnh v, là đỉnh đầu tiên
kề với u mà chưa thăm>
< Thông báo thăm v>
< Đẩy u trở lại ngăn xếp>
19
< Đẩy tiếp v vào ngăn xếp>
End;
Until < Ngăn xếp rỗng>
Chương trình cài đặt
Program Depth_First_Search;
const
max = 100;
var
a: array[1..max, 1..max] of Boolean;
Free: array[1..max] of Boolean;
Trace: array[1..max] of Integer;
Stack: array[1..max] of Integer;
n, S, F, Last: Integer;
procedure Enter;
var
i, u, v, m: Integer;
begin
FillChar(a, SizeOf(a), False);
Readln(n, m, S, F);
for i := 1 to m do
begin
Readln(u, v);
a[u, v] := True;
a[v, u] := True;
end;
end;
procedure Init;
begin
FillChar(Free, n, True);
Last := 0;
end;
procedure Push(V: Integer);
begin
20
Inc(Last);
Stack[Last] := V;
end;
function Pop: Integer;
begin
Pop := Stack[Last];
Dec(Last);
end;
procedure DFS;
var
u, v: Integer;
begin
Write(S, ', '); Free[S] := False;
Push(S);
repeat
u := Pop;
for v := 1 to n do
if Free[v] and a[u, v] then
begin
Write(v, ', '); Free[v] := False;
Trace[v] := u;
Push(u); Push(v);
Break;
end;
until Last = 0;
end;
procedure Result;
begin
Writeln;
if Free[F] then
', F)
Writeln('Not found any path from ', S, ' to
else
21
begin
while F S do
begin
Write(F, '[...]... lấy ra khỏi hàng đợi Xếp hàng mua vé xem phim là một hình ảnh trực quan của khái niệm trên, người mới đến thêm vào cuối hàng còn người ở đầu hàng mua vé và ra khỏi hang, vì vậy hàng còn được gọi là cấu trúc FIFO (first in - first out) hay "vào trước - ra trước" 3.2 Các thao tác cơ bản của hàng đợi 3.2.1 Cài đặt hàng đợi bằng mảng Ta dùng một mảng để chứa các phần tử của hàng, khởi đầu phần tử đầu tiên... hệ điều hành, tổ chức bộ đệm bàn phím, … Ví dụ rất dễ thấy là quản lí in trên mạng, nhiều máy tính yêu cầu in đồng thời và ngay cả một máy tính cũng yêu cầu in nhiều lần Nói chung có nhiều yêu cầu in dữ liệu, nhưng máy in không thể đáp ứng tức thời tất cả các yêu cầu đó nên chương trình quản lí in sẽ thiết lập một hàng đợi để quản lí các yêu cầu Yêu cầu nào mà chương trình quản lí in nhận trước nó sẽ... minh rằng biểu thức hậu tố không cần phải có dấu ngoặc vẫn có thể tính được một cách đúng đắn bằng cách đọc lần lượt biểu thức từ trái qua phải và dùng một Stack để lưu kết quả trung gian Bước 1: Khởi động Stack rỗng Bước 2: Đọc lần lượt các phần tử của biểu thức từ trái qua phải, với mỗi phần tử đó ta kiểm tra: - Nếu phần tử này là một toán hạng thì đẩy giá trị của nó vào Stack - Nếu phần tử này là... (Pop) khỏi stack 2.2 Các thao tác cơ bản của ngăn xếp Đối với một ngăn xếp chỉ có hai thao tác cơ bản: thao tác thêm một phần tử vào Stack và thao tác loại bỏ một phần tử khỏi Stack Trong khuôn khổ tài liệu này tác giả chỉ đưa ra cách cài đặt Stack bằng DSLK Stack dùng danh sách liên kết hoàn toàn giống danh sách liên kết thuận, nhưng chỉ có điều khác là khi thêm phần tử mới hay huỷ một phần tử ta luôn... 2.4.2 Tính giá trị một biểu thức dạng hậu tố Biểu thức trung tố, hiểu đơn giản tức là toán tử sẽ được đặt giữa hai toán hạng, dĩ nhiên đây phải là toán tử hai ngôi Vậy dựa vào vị trí của của toán tử, liệu ta có thể biểu diễn biểu thức đại số dưới dạng khác? Câu trả lời là được, và như đã nói, ta có ba cách là biểu thức tiền tố (prefix), trung tố (infix) và hậu tố (postfix) Hãy xem một chút giới thiệu... Trace[F]; end; Writeln(S); end; end; 33 begin Assign(Input, 'GRAPH.INP'); Reset(Input); Assign(Output, 'GRAPH.OUT'); Rewrite(Output); Enter; Init; BFS; Result; Close(Input); Close(Output); end 34 TÀI LIỆU THAM KHẢO PHỤ LỤC Một số bài ứng dụng stack hoặc Queue trên SPOJ: 1 Huyền thoại Lục Vân Tiên (http://vn.spoj.com/problems/MINK/) MINK Dạo này tivi cũng đang chiếu phim Lục Vân Tiên, sẵn tiện lấy luôn ... TÀI LIỆU THAM KHẢO Lê Minh Hoàng; “chuyên đề Cấu trúc liệu Giải thuật” Nguyễn Hữu Tuân, 2007; “Bài giảng Cấu trúc liệu Gải thuật” “Chuyên đề Cấu trúc liệu ; Đại học cần thơ, 2003 Cấu trúc liệu. .. nói danh sách liên kết cấu trúc liệu định nghĩa kiểu đệ quy, định nghĩa nút danh sách có tham chiếu tới khái niệm nút Có nhiều loại danh sách liên kết khác tùy thuộc vào cấu trúc phần tử danh sách... kết sau: Danh sách liên kết cấu trúc liệu bao gồm tập phần tử, phần tử phần nút có chứa liên kết đến phần tử “Mối phần tử phần nút” nút có hai trường, trường gọi liệu (data), trường lại trường