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

TÌM KIẾM THEO CHIỀU SÂU TRÊN ĐỒ THỊ CÓ HƯỚNG ĐƯỢC BIỂU DIỄN BỞI DANH SÁCH KỀ VÀ ỨNG DỤNG VÀO SẮP XẾP TÔPÔ

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 (360.21 KB, 17 trang )

TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI
Viện Công nghệ Thông tin và Truyền thông

BÀI TẬP LỚN
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT

ĐỀ TÀI: TÌM KIẾM THEO CHIỀU SÂU TRÊN ĐỒ THỊ CÓ HƯỚNG ĐƯỢC BIỂU DIỄN
BỞI DANH SÁCH KỀ VÀ ỨNG DỤNG VÀO SẮP XẾP TƠPƠ.

NHĨM 5
Giáo viên hướng dẫn: PGS Nguyễn Đức Nghĩa


Cấu trúc dữ liệu và giải thuật
HÀ NỘI – 2010

NỘI DUNG
A-

B-

Định nghĩa ADT
I- Đồ thị
II-Danh sách kề
Bài tốn tìm kiếm theo chiều sâu trên đồ thị có hướng biểu diễn bởi
danh sách kề
I-Phát biểu bài tốn
II-Ứng dụng bài tốn tìm kiếm theo chiều sâu

C-


Ứng dụng bài tốn tìm kiếm theo chiều sâu trên đồ thị có hướng
được biểu diễn bởi danh sách kề vào bài tốn sắp xếp tơpơ

A-Định nghĩa ADT
2


Cấu trúc dữ liệu và giải thuật

I-Đồ thị
1.Khái niệm đồ thị
Đồ thị G là cấu trúc rời rạc bao gồm hai tập
- Tập đỉnh V(G) là tập hữu hạn khác rỗng
- Tập cạnh E(G) là tập hữu hạn có thể là tập rỗng các cặp (u,v) trong đó u,v ∈V
Kí hiệu G=(V,E)
2. Các loại đồ thị
Phụ thuộc vào kiểu của cạnh nối và số lượng cạnh nối giữa hai đỉnh mà ta phân
biệt các loại đồ thị khác nhau.
2.1. Đồ thị vô hướng
Đơn (đa) đồ thị vô hướng G = (V,E) là cặp gồm:
- Tập đỉnh V là tập hữu hạn phần tử, các phần tử gọi là các đỉnh
- Tập cạnh E là tập (họ) các bộ khơng có thứ tự dạng
(u, v), u, v ∈ V, u≠v
2.2. Đồ thị có hướng
Đơn (đa) đồ thị có hướng G = (V,E) là cặp gồm:
Tập đỉnh V là tập hữu hạn phần tử, các phần tử gọi là các đỉnh
Tập cung E là tập (họ) các bộ có thứ tự dạng
(u, v), u, v ∈ V, u≠v
3.Biểu diễn đồ thị
3.1.Biểu diễn đồ thị bằng ma trận kề

3.2.Biểu diễn đồ thị bằng danh sách kề
3.3.Biểu diễn đồ thị bằng danh sách cạnh
4.Các thao tác cơ bản thường gặp khi xử lý đồ thị
- incidentEdge(v)- duyệt các đỉnh kề của đỉnh v
- areAdjacent(v,w)- trả lại giá trị true khi và chỉ khi v và w là kề nhau
- insertVertex(z)-bổ sung đỉnh z
- insertEdge(v)-bổ sung cạnh e=(v,w)
- removeVertex(v)-loại bỏ đỉnh v
- removeEdge(e)-loại bỏ cạnh e
5. Các thuật tốn duyệt đồ thị
5.1.Thuật tốn tìm kiếm theo chiều rộng (BFS)
5.2.Thuật tốn tìm kiếm theo chiều sâu (DFS)

II-Danh sách kề
Với mỗi đỉnh v cất giữ danh sách các đỉnh kề với nó.
3


Cấu trúc dữ liệu và giải thuật
-Là mảng Ke gồm có | V| danh sách .
-Mỗi đỉnh có một danh sách .
-Với mỗi u ∈V, Ke[u] bao gồm tất cả các đỉnh kề của u.
Ví dụ
a) Biểu diễn đồ thị vơ hướng G=(V,E) sử dung danh sách kề.
u

v

w


v

u

w

w

u

v

x

z

y

v

z

x

y

t

b)


Bộ nhớ địi hỏi = a|V|+2b|E|
Biểu diễn đồ thị có hướng G=(V,E) sử dụng danh sách kề.
a

b

b

e

c

b

c

d
e

b

f

f

Bộ nhớ địi hỏi = a|V|+b|E|
Có thể sử dụng mô tả trên C sau đây để biểu diễn danh sách kề
#define MAX_ VERTICES 500
Typedef struct node*node_ptr;
Typedef struct node

{
int vertex;
node_ptr link;
} node;
node_ptr graph[MAX_VERTICES];

B-Bài tốn tìm kiếm theo chiều sâu trên đồ thị có hướng biểu
diễn bởi danh sách kề
4


Cấu trúc dữ liệu và giải thuật

I-Phát biểu bài toán
1.Ý tưởng chung cho các thuật tốn tìm kiếm
-Trong q trình thực hịện thuật tốn , ở mỗi đỉnh có một trong ba
trạng thái sau:
+ Chưa thăm thì thể hiện bằng màu trắng.
+ Đã thăm (nhưng chưa duyệt xong) thì thể hiện bằng màu xám.
+ Đã duyệt xong thể hiện bằng màu đen.
2. Thuật tốn tìm kiếm theo chiều sâu (depth first search)
Input: G=(V,E) – đồ thị vơ hướng hoặc có hướng
Output: Với mỗi v ∈V
d[v]= thời điểm bắt đầu thăm(v chuyển từ màu trắng sang xám)
f[v]= thời điểm kết thúc thăm(v chuyển từ màu xám sang đen)
π[v]: từ đỉnh đó ta đến thăm đỉnh v.
Rừng tìm kiếm theo chiều sâu(gọi tắt là rừng DFS – Forest of depth-first trees):
Gπ=(V,Eπ),
Eπ={(π[v] , v): v∈V và π[v] ≠ null}.
2.1.thuật tốn tìm kiếm theo chiều sâu bắt đầu từ đỉnh u

DFS-Visit(u)
1.color[u] ← GRAY
2.time ← time+1
3.d[u] ← time
4.for v ∈ Adj[u]
5.
do if color[v]=WHITE
6.
then π [v] ←u
7.
DFS-Visit(v)
8.color[u]← BLACK
9.f[u] ← time ← time+1
2.2.thuật toán theo chiều sâu trên đồ thị G
DFS(G)
1. for u ∈V[G]
2.
do color[u] ← white
3.
π[u] ← NULL
4. Time ← 0
5. for u ∈V[G]
6.
do if color[u] = white
7.
then DFS-Visit(u)
Q trình thực hiện thuật tốn được trình diễn trong các hình minh hoạ sau
5



Cấu trúc dữ liệu và giải thuật
u

v

w

1/

/

/

/

/

/

x

y

z

u

v

DFS(u): Thăm đỉnh u


DFS(n)

w
DFS(v): thăm đỉnh v

1/

2/

/

DFS(u)

DFS(v)

/

/

x

y

u

v

/
z

w
DFS(y): thăm đỉnh y

1/

2/

DFS(u)

/
DFS(v)

/

3/

/

x

y

z

DFS(y)

6


Cấu trúc dữ liệu và giải thuật

u

v

w
DFS(y): thăm đỉnh y

1/

2/

DFS(u)

/
DFS(v)

4/

3/

/

x

y

z

DFS(y)


DFS(x)

u

v

w
Kết thúc thăm đỉnh x

1/

2/

DFS(u)

/
DFS(v)

4/5

3/

x

y

/
z

DFS(y)


DFS(x)

7


Cấu trúc dữ liệu và giải thuật
u

v

w
Kết thúc thăm đỉnh y

1/

2/

DFS(u)

/
DFS(v)

4/5

3/6

/

x


y

z

DFS(y)

DFS(x)

u

v

w
Kết thúc thăm đỉnh v

1/

2/7

DFS(u)

/
DFS(v)

4/5

3/6

/


x

y

z

DFS(y)

DFS(x)

8


Cấu trúc dữ liệu và giải thuật
u

v

w
Kết thúc thăm đỉnh u

1/8

2/7

DFS(u)

/
DFS(v)


4/5

3/6

/

x

y

z

DFS(y)

DFS(x)

u

v

w
DFS(w): Thăm đỉnh w

1/8

2/7

9/


4/5

3/6

/

x

y

z

u

v

w
DFS(z): Thăm đỉnh z

1/8

2/7

9/

4/5

3/6

10/


x

y

z

9


Cấu trúc dữ liệu và giải thuật
u

v

w
Kết thúc thăm đỉnh z

1/8

2/7

9/

4/5

3/6

10/11


x

y

z

u

v

w

1/8

2/7

9/12

4/5

3/6

10/11

x

y

z


Kết thúc thăm đỉnh w
Kết thúc DFS(G)

Rừng tìm kiếm gồm 2 cây: cây DFS(u) và cây DFS(w)
u

v

w

1/8

2/7

9/12

4/5

3/6

10/11

x

y
cây DFS(u)

z
cây DFS(w)


3.Các tính chất của DFS
10


Cấu trúc dữ liệu và giải thuật
- Rừng DFS là phụ thuộc vào thứ tự các đỉnh được duỵêt trong vòng lặp for duyệt
đỉnh trong DFS(G) và DFS_Visit(u)
- Để gỡ đệ quy có thể sử dụng ngăn xếp. Và có thể nói, điểm khác biệt cơ bản của
DFS với BFS là các đỉnh đang được thăm trong DFS được cất giữ vào ngăn xếp
thay vì hàng đợi trong BFS.
- Các khoảng thời gian thăm [d[v],f[v]]
(parenthesis structure).

của các đỉnh có cấu trúc lồng nhau

4.Cấu trúc lồng nhau (parenthesis structure)
Định lý: Với mọi u,v chỉ có thể xảy ra một trong các tình huống sau:
1.d[u] < f[u] < d[v] < f[v] hoặc d[v] < f[v] < d[u] < f[u] ( nghĩa là hai khoảng
thời gian thăm của u và v là dời nhau) và khi đó u và v là khơng có quan hệ tổ tiênhậu duệ.
2.d[u] < d[v] < f[v] < f[u] ( nghĩa là khoảng thời gian thăm của v là lồng trong
khoảng thời gian thăm của u) và khi đó v là hậu duệ của u.
3.d[v] < d[u] < f[u] < f[v] (nghĩa là khoảng thời gian thăm của u là lồng trong
khoảng thời gian thăm của v) và khi đó u là hậu duệ của v.
Ví dụ: Xét việc thực hiện thuật tốn tìm kiếm theo chiều sâu trên đồ thị cho trong
hình vẽ dưới đây
2/15

3/14

a


b

4/5
c

DFS(s) Tree

1/16
s
8/9
t

d
11/12

e
6/13

Time stamps:
d[]/t[]

f
7/10

Hình vẽ sau đây minh hoạ cho định lý về cấu trúc lồng nhau:
11


Cấu trúc dữ liệu và giải thuật

s
a
b
c

e
f

d

t

1

2

3

4

5

6

7

8

9


10

11

12

(s

(a

(b

(c

c)

(e

(f

(t

t)

f)

(d

d)


13 14
e)

15

16

b) a) s)

5.Độ phức tạp của DFS
-Thuật toán thăm mỗi đỉnh v∈ V đúng một lần →Θ (|V|)
- Với mỗi đỉnh v duyệt qua tất cả các đỉnh kề, với mỗi đỉnh kề thực hiện thao tác
với thời gian hằng số. Do đó việc duyệt qua tất cả các đỉnh mất thời gian
Σv∈V|neighbors[v]| =Θ (|E|)
- Tổng cộng Θ(|V|)+Θ (|E|) = Θ (|V|+|E|), hay Θ (|V|2)
Như vậy, DFS có cùng độ phức tạp như BFS
6.Phân loại cạnh
DFS tạo ra một cách phân loại các cạnh của đồ thị đã cho:
- Cạnh của cây(Tree edge): là cạnh mà theo đó từ một đỉnh ta đến thăm một đỉnh
mới
- Cạnh ngược (Back edge): đi từ con cháu (descendent) đến tổ tiên(ancestor)
- Cạnh tới (Forward edge): đi từ tổ tiên đến hậu duệ
- Cạnh vòng (Cross edge): cạnh nối hai đỉnh ko có quan hệ họ hàng
Để nhận biết cạnh (u,v) thuộc loại cạnh nào, ta dựa vào màu của đỉnh v khi lần đầu
trên cạnh (u,v) được khảo sát. Cụ thể, nếu màu của đỉnh v làp
12


Cấu trúc dữ liệu và giải thuật
Trắng thì (u,v) là cạnh của cây

Xám thì (u,v) là cạnh ngược
Đen thì (u,v) là cạnh tới hoặc vòng. Trong trường hợp này để phân biệt cạnh
tới và cạnh vòng ta cần xét xem hai đỉnh u và v có quan hệ họ hàng hay
không nhờ sử dụng kết quả của định lý về cấu trúc lồng nhau.
Nhiều ứng dụng của DFS chỉ đòi hỏi nhận biết cạnh của cây và cạnh ngược, Hơn
nữa, đối với đồ thị vô hướng, DFS chỉ sản sinh ra hai loại cạnh này như chỉ ra trong
khẳng định của định lý sau đây.
-

Định lý: nếu G là đồ thị vơ hướng, thì DFS chỉ sản sinh ra cạnh của cây và cạnh
ngược.

II-Ứng dụng của thuật tốn tìm kiếm theo chiều sâu (DFS)






Tính liên thơng của đồ thị
Tìm đường đi từ s đến t
Phát hiện chu trình
Kiểm tra tính liên thơng mạnh
Định hướng đồ thị

C- Ứng dụng thuật tốn tìm kiếm theo chiều sâu trên đồ thị
có hướng sử dụng danh sách kề vào bài tốn sắp xếp tơpơ
I- Phát biểu bài toán
Bài toán đặt ra là : Cho đồ thị có hướng khơng có chu trình G=(V,E). hãy tìm cách
sắp xếp các đỉnh sao cho nếu có cạnh (u,v) thì u phải đi trước v trong thứ tự đó (nói

cách khác, cần tìm cách đánh số các đỉnh của đồ thị sao cho mỗi cung của đồ thị
luôn hướng từ đỉnh có chỉ số nhỏ hơn đến đỉnh có chỉ số lớn hơn)

II-Thuật tốn sắp xếp tơpơ
Thuật tốn có thể viết vắn tắt như sau: Thực hiện DFS(G), khi mỗi đỉnh được duyệt
xong ta đưa nó vào đầu danh sách lien kết (điều đó có nghĩa là những đỉnh kết thúc
thăm càng muộn sẽ càng ở đầu danh sách hơn). Danh sách lien kết thu được khi kết
thúc DFS(G) sẽ cho ta thứ tự cần tìm.

TopoSort(G)
1.

for u∈ V color[u]=white;

//khởi tạo
13


Cấu trúc dữ liệu và giải thuật
L = new(linked_list);
//khởi tạo danh sách liên kết rỗng
3. for u∈ V
4.
if (color[u] == white) TopVisit(u);
5. return L
// L cho thứ tự cần tìm
TopVisit(u){
2.

1.

2.
3.
4.

color[u] = gray;
//bắt đầu tìm kiếm từ u
for v ∈ Adj(u)
//đánh dấu u đã thăm
if (color[v]==white)TopVisit(v);
Nạp u vào đầu danh sách L
// u đã duyệt xong

Cài đặt trên C
void DFS(int vertex)
{
//printf(" %d ", vertex);
pListIt p;
color[vertex] = GRAY; // visited
for (p = adjacencyList[vertex]; p != NULL; p = p -> p_next)
if (!color[p -> value])
{
ancient[p->value] = vertex;
distance[p->value] = distance[vertex] +1;
p->type = TREE_EDGE;
DFS(p -> value);
}
else
{
if( color[p->value] == GRAY)
{

p->type = BACK_EDGE;
isCircle = true;
// print the circle
printf(" \n Circle: ");
int l = vertex;
while(l != p->value)
{
printf( " %d ", l);
l = ancient[l];
14


Cấu trúc dữ liệu và giải thuật
}
printf( " %d ", l);
}
else
if (distance[p->value] > distance[vertex])
{
p->type = AHEAD_EDGE ;
}
else
p->type = CROSS_EDGE ;
}
// add to the topological order
++atPos;
topological_order[n-atPos] = vertex;
color[vertex] = BLACK;
}


A

B

D

A

B

1/

D
1/

2/
C

E

Linked list:∅

A

C

E

Linked list:∅


B

D
1/

A

B

D
1/4
15


Cấu trúc dữ liệu và giải thuật

2 /3
C

E

Linked list:

A

C

E

Linked list:

2/3

1/4

2/3

E

D

E

B

D

5/

1/4

C

A

B

D

5/


1/4

2 /3

6/

2/3

E

C

E

Linked list:

A

2/3

Linked list:
1/4

2/3

1/4

2/3

D


E

D

E

B

D

5/

1/4

A

B

D

5/8

1/4
16


Cấu trúc dữ liệu và giải thuật

6/7


2 /3

C

6/7

E

2/3

C

Linked list:

E

Linked list:

6/7

1/4

C

2/3

D

E


5/8

6/7

1/4

2/3

B

C

D

E

A

B

D

A

B

D

9/


5/8

1/4

9/10

5/8

1/4

6/7

2 /3

C

6/7

E

2/3

C

Linked list:

E

Linked list:


5/8

6/7

1/4

B

C

D

2/3
E

9/10

5/8

6/7

1/4

2/3

A

B


C

D

E

III-Đánh giá độ phức tạp của thuật toán
Thời gian tính của TopoSort(G) là O(|V|+|E|)
17


Cấu trúc dữ liệu và giải thuật

18



×