Tải bản đầy đủ (.docx) (259 trang)

cấu trúc dữ liệu và giải thuật lý thuyết neu

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (533.36 KB, 259 trang )

B mụn: Cu trỳc d liu v gii
thut
Chơng 6
cấu trúc dữ liệu kiểu Đồ
thị ( Graph )
Trong chơng 5 chúng ta
đã nghiên cứu một loại cấu
trúc phi tuyến là cây. Cây là
một trờng hợp đặc biệt của
một loại cấu trúc dữ liệu tổng
quát
hơn
,đó

đồ
thị( Graph). Trong chơng này,
chúng ta sẽ nghiên cứu hai loại
đồ thị là đồ thị có hớng và
đồ thị vô hớng.
6.1 Đồ thị có hớng
254


6.1.1 Khái niệm
Đồ thị có hớng ( Directed
graph ) gồm một tập hợp
hữu hạn các phần tử gọi là
nút hay đỉnh, cùng với một
tập hợp hữu hạn các cạnh có
hớng nối các cặp đỉnh với
nhau .


Chẳng hạn cho đồ thị sau
đây:

255


1

5

2

4

3

§å thÞ nµy gåm 5 nót ®îc ®¸nh sè 1,2,3,4,5 vµ 7 c¹nh
nèi c¸c nót tõ 1 ®Õn 2, 1 ®Õn
4, 1 ®Õn 5, 2 ®Õn 4, 3 ®Õn
chÝnh nã,4 ®Õn 2, vµ 4 ®Õn
3.
C©y cã thÓ coi lµ trêng
hîp ®Æc biÖt cña ®å thÞ cã h256


ớng và đợc đặc trng bởi tính
chất là một trong các nút, nút
gốc,không có cạnh nào hớng
đến nó, và tất cả các nút còn
lại có thể đạt đến từ nút gốc

bằng một đờng duy nhất .
Nghĩa là ,chỉ đi theo một và
chỉ một dãy các cạnh liên tiếp.
Đồ thị trên đây có một
nút "gần giống nh nút gốc"
( Không có cạnh nào hớng đến
nó) là nút 1, nhng có nhiều đờng khác nhau từ nút 1 đến
nút 3.
Ví dụ:
1 2 3
1 4 3
257


1 4 2 3
..........
Sau ®©y lµ mét vÝ dô kh¸c
vÒ ®å thÞ:
1

2
6

5

4

3

Trong trêng hîp nµy ta cã c¸c

®êng ®i nh sau:
1 5  4  3
1 2  6
1 4  3  3
258


.......
Đồ thị có rất nhiều ứng
dụng trong thực tiễn. Đồ thị
có hớng đợc dùng để thiết
kế,phân tích các sơ đồ mạng
điện, biểu diễn đờng găng
trình tự thực hiện các hạng
mục trong một công trình
xây dựng.
Ví dụ :
Đồ thị có hớng biểu diễn quá
trình lập kế hoạch sản xuất
trong một doanh nghiệp.

259


3.1
1

2

3


3.2

4

5

3.3

1 Đặ
t mục tiêu kếhoạch
2 Nghiên cứu thịtr ờng
3 Đ ánh giá các tiềmnăng của danh nghiệp
3.1 Lao đ
ộng
3.2 Khả năng tài chính
3.3 Năng lực sản xuất
4 Xâ
y dựng các chỉtiêu kếhoạch
5 Thực hiện kếhoạch

Trong sơ đồ này mỗi
hình chữ nhật biểu diễn một
công đoạn trong qui trình lập
kế hoạch ,bắt đầu từ công
đoạn tiền kế hoạch là nghiên
cứu thị trờng đến công đoạn

260



cuối cùng là thực hiện kế
hoạch.
6.1.2 Phơng pháp cài đặt
đồ thị có hớng
Một phơng pháp rất
thông dụng để cài đặt đồ
thị là sử dụng ma trận kề
( Adjacency matrix). Để xây
dựng ma trận kề ,trớc hết
chúng ta đánh số các nút của
đồ thị có hớng 1,2,2 ... n. Ma
trận kề là ma trận Adj bậc n x
n trong đó thành phần ở hàng
i, cột j có giá trị 1 nếu có một
cạnh từ i đến j ,và có giá trị o
nếu khác.
261


VÝ dô : Cho ®å thÞ cã híng
sau ®©y:
1

2
B

5

A


E
3

C

D

4

Ta cã ma trËn kÒ :

262


Adj =

0

1

1

0

1

0

0


1

0

0

0

0

0

1

0

0

0

0

1

0

Để xác định các giá trị
A,B,C ... của các nút chúng ta
sử dụng thêm một ma trận

Data chỉ gồm một cột chứa
các giá trị này , trong đó dữ
liệu của nút thứ i đợc lu trữ tại
Data[i]. Nh vậy chúng ta có
hai mảng :

263


Adj =

0

1

1

0

1

0

0

1

0

0


0

0

0

1

0

0

0

0

1

0

Data =

A
B
C
D
E

Thông thòng trong ma

trận kề có chứa rất nhiều
phần tử bằng không, do đó sẽ
tốn rất nhiều không gian nhớ
để lu trữ các phần tử này.
Chúng ta có thể sử dụng ph264


ơng pháp lu trữ ma trận kề
bằng danh sách liên kết theo
hàng( Linked Row List) chúng
ta sẽ có cách biểu diễn danh
sách kề cho một đồ thị có hớng.
Cho đồ thị có hớng sau
đây:
1

2
B

A

E
3

C

D

5


4

Danh sách kề của đồ thị này
nh sau:
265


V[1]
V[2]

Nút đ
ầu
A

2

B

3

V[3]

C

2

V[4]

D


4

V[5]

Nút dỉ
nh
3

5

4

E

Một đồ thị có hớng
đợc biểu diễn bởi một mảng
các
con
trỏ
V[1],V[2],
...V[n] ,mỗi con trỏ cho mỗi nút
trong đồ thị có hớng. Mỗi
phần tử mảng V[i] chỉ đến
266


một nút đầu lu trữ dữ liệu
cho nút ấy và chứa một con
trỏ chỉ đến một danh sách
liên kết của các nút kề ( Nút

đợc nối với i theo hớng từ i đi
ra). Mỗi nút kề có hai trờng :
trờng số nguyên ,lu trữ dữ
liệu của nút và một trờng liên
kết chỉ đến nút tiếp thẻo
trong danh sách kề này.
Cách biểu diễn đồ thị
có hớng bằng danh sách kề có
thể đợc cài đặt với các khai
báo nh sau:
Const
MaxVertices=.....( Số các nút
của đồ thị có hớng)
267


Type
DataType=.........( KiÓu d÷ liÖu
trong c¸c nót)
VertexNumber=
1..
MaxVertices;
AdjPointer =^. VertexNode;
VertexNode= Record
Vertex:
VertexNumber;
Next: AdjPointer
end;
HeadNode=Record
Data: DataType;

Next: AdjPointer
end;
HeadPointer=^. HeadNode;

268


ArrayOfPointers=
Array[VertexNumber]
HeadPointer;
Var
V: ArrayOfPointer;

of

6.1.3 Các giải thuật xử lý
danh sách kề
Để xây dựng các danh sách
kề cho một đồ thị có hớng
chúng ta phải thực hiện các
giải thuật cơ bản xử lý danh
sách kề.
Giải thuật thiết lập danh
sách kề
269


Gải thuật thiết lập danh sách
kề đợc biểu diễn nh sau:
For i:= 1 to MaxVertices thực

hiện các bớc sau đây:
1 - Lấy một nút đầu đợc chỉ
bởi V[i] và khởi động trờng
Next của nó tại giá trị Nil
2 - Đọc dữ liệu trong nút này
vào trờng dữ liệu V[i]^.Data
của nút đầu
3 - Với mỗi nút kề với nút i ( Có
hớng từ i đi ra) thực hiện các
bớc sau đây:
a. Đọc số của nút ấy
b. Chèn số này vào danh
sách liên kết của các nút kề
đợc chỉ bởi V[i]^.Next bằng
270


cách dùng một trong các giải
thuật chèn trong danh sách đã
xét trong chơng 5.
Giải thuật tìm theo chiều
sâu
Để hiểu rõ bản chất của
giải thuật tìm theo chiều sâu
( Depth- First Search) chúng ta
xét đồ thị có hớng sau đây:

271



A
B
E

C
F

D
G

H

Tríc hÕt chóng ta th¨m
gèc råi chä mét trong c¸c nót
con cña nã ch¼ng h¹n nót B
vµ th¨m nót nµy. Tuy nhiªn ,tríc
khi th¨m c¸c nót con kh¸c
,chóng ta th¨m c¸c nót con
cña B theo chiÒu s©u. Chóng
ta chän mét trong c¸c con cña
272


B chẳng hạn nút E và thăn nó:
Ta có trình tự sau đây:
A,B,E
Ta tiếp tục thăm các nút
con của E nhng vì E không có
các nút con nên ta trở lại thăm
các nút con của nút B . Ta thăm

nút F và nút con của nó là H.
Ta có:
A,B,E,F,H
Nh vậy, chúng ta đã
xem xét xong nút B và các con
cháu của nó. Chúng ta trở lại
nút A và tiếp tục thăm các nút
con ( C và D ) của nó. Ta có
các trình tự sau đây:
A,B,E,F,
H,C
273


A,B,E,F,H,C
,D,G
Giải thuật sau đây
thực hiện việc tìm theo
chiều sâu trong một đồ thị
có hớng ,đợc biểu diễn bắng
các danh sách kề , bắt đầu
từ nút Start . Tập hợp Unvisited
chứa các số của các nút cha đợc thăm :
Procedure
DepthFirstSearch(
V:
ArrayOfPointers;
Var
Unvisited: SetOfVertices);
Start : VertexNumber);

Var
CurrPtr: AdjPointer;
274


NewStart: VertexNumber;
Begin
(* ChÌn c¸c lÖnh ®Ó x lý
V[Start]^.Data*)
Unvisited:=
UnvisitedV[Start];
(* QuÐt danh s¸ch kÒ t×m
theo chiÒu s©u*)
CurrPtr:= V[Start]^.Next;
While CurrPtr <> Nil do
Begin
NewStart := CurrPtr^.Vertex;
if ( NewStart in Unvisited) then
DepthFirstSeach (V ,Unvisited,
NewStart);
CurrPtr:= CurrPtr^.Next
end;
end;
275


Trong giải thuật này Unvisited
là một tập hợp có kiểu
SetOfVertices=
Set

of
VertexNumber . Nó có thể đợc
khởi động bằng lệnh:
Unvisited:= [1.. NumVertices]
trớc
khi
gọi
thủ
tục
DepthFirstSearch, trong đó
NumVertices là số các nút
trong đồ thị có hớng.
Giải thuật tìm theo chiều
rộng
Xét đồ thị có hớng:

276


A
B
E

C
F

D
G

H


Chúng ta xem xét việc quét
đồ thị này theo chiều rộng .
Trớc hết chúng ta bắt đầu từ
gốc, thăm gốc và các con của
nó , chẳng hạn từ phải sang
trái:
A,B,C,D
Sau đó tiến hành thăm các
con của các nút trong mức
đầu tiên này:
277


A,B,C,D,E,F,G
và cuối cùng chúng ta thăm các
nút con của các nút trong mức
thứ hai:
A,B,C,D,E,F,G,H
Giải thuật sau đây thực hiện
việc tìm theo chièu rộng trong
một đồ thị có hớng :
Bớc 1 Thăm nút xuất phát
Bớc 2 Khởi động một Queue
chỉ chứa nút xuất phát
Bớc 3
While( Queue không
rỗng) thực hiện các bớc sau
đây:
* Lấy một nút V từ hàng

đợi

278


×