Danh sách k

Một phần của tài liệu Kỹ Thuật Lập Trình (Trang 111 - 156)

Trong r t nhi u ng d ng, cách bi u di n đ th d i d ng danh sách k th ng đ c s d ng. Trong bi u di n này, v i m i đnh v c a đ th chúng ta l u tr danh sách các đnh k v i nó mà ta ký hi u là Ke(v), ngh a là

Ke(v) = { u V: (u, v)E},

V i cách bi u di n này, m i đnh i c a đ th , ta làm t ng ng v i m t danh sách t t c các đnh k v i nó và đ c ký hi u là List(i). bi u di n List(i), ta có th dùng các ki u d li u ki u t p h p, m ng ho c danh sách liên k t.

Ví d 5. Danh sách k c a đ th vô h ng trong hình 5.8, đ th có h ng trong hình 5.9 đ c bi u di n b ng danh sách k nh sau: List(i) List(i) nh 1 2 3 nh 1 3 2 2 1 3 4 2 4 5 3 1 2 5 3 4 4 2 5 6 5 1 5 3 4 6 6 4 5

5.3. CÁC THU T TOÁN TÌM KI M TRÊN TH

5.3.1 Thu t toán tìm ki m theo chi u sâu

R t nhi u thu t toán trên đ th đ c xây d ng d a trên vi c duy t t t c các đnh c a đ th sao cho m i đnh đ c vi ng th m đúng m t l n. Nh ng thu t toán nh v y đ c g i là thu t toán tìm ki m trên đ th . Chúng ta c ng s làm quen v i hai thu t toán tìm ki m c b n, đó là duy t theo chi u sâu (Depth First Search) và duy t theo chi u r ng (Breath First Search).

T t ng c b n c a thu t toán tìm ki m theo chi u sâu là b t đ u t i m t đnh v0 nào đó, ch n m t đnh u b t k k v i v0 và l y nó làm đnh duy t ti p theo. Cách duy t ti p theo đ c th c hi n t ng t nh đ i v i đnh v0.

ki m tra vi c duy t m i đnh đúng m t l n, chúng ta s d ng m t m ng g m n

ph n t (t ng ng v i n đnh), n u đnh th i đã đ c duy t, ph n t t ng ng trong m ng có giá tr FALSE. Ng c l i, n u đnh ch a đ c duy t, ph n t t ng ng trong m ng có giá tr TRUE. Thu t toán tìm ki m theo chi u sâu b t đ u t đnh v nào đó s duy t t t c các đnh liên thông v i v. Thu t toán có th đ c mô t b ng th t c đ qui DFS()

trong đó: chuaxet - là m ng các giá tr logic đ c thi t l p giá tr TRUE void DFS(int v){

Th m_ nh(v); chuaxet[v] = FALSE; for u ∈ke(v) { if (chuaxet[u] ) DFS( v); } } Th t c DFS() s th m t t c các đnh cùng thành ph n liên thông v i v m i đnh đúng m t l n. đ m b o duy t t t c các đnh c a đ th (có th có nhi u thành ph n liên thông), chúng ta ch c n th c hi n :

for( i=1; i≤n; i++)

chuaxet[i] = TRUE; for( i:=1;i≤ n; i++)

if (chuaxet[i] )

DFS( i);

Chú ý: Thu t toán tìm ki m theo chi u sâu d dàng áp d ng cho đ th có h ng. i v i đ th có h ng, chúng ta ch c n thay các c nh vô h ng b ng các cung c a đ th có h ng.

Ví d 1. Áp d ng thu t toán tìm ki m theo chi u sâu v i đ th trong hình sau:

2 6 8 7 1 4 5 3 10 11 9 12 13 Hình 5.11. th vô h ng G K t qu duy t: 1, 2, 4 , 3, 6, 7, 8, 10, 5, 9, 13, 11, 12

5.3.2. Thu t toán tìm ki m theo chi u r ng (Breadth First Search)

ý r ng, v i thu t toán tìm ki m theo chi u sâu, đnh th m càng mu n s tr thành đnh s m đ c duy t xong. ó là k t qu t t y u vì các đnh th m đ c n p vào stack trong th t c đ qui. Khác v i thu t toán tìm ki m theo chi u sâu, thu t toán tìm ki m theo chi u r ng thay th vi c s d ng stack b ng hàng đ i queue. Trong th t c này, đnh đ c n p vào hàng đ i đ u tiên là v, các đnh k v i v v1, v2, . . ., vkđ c n p vào queue k ti p. Quá trình đ c th c t ng t v i các đnh trong hàng đ i. Thu t toán d ng khi ta đã duy t h t các đnh k v i đnh trong hàng đ i. Chúng ta có th mô t thu t toán b ng th t c BFS nh d i đây.

chuaxet- m ng ki m tra các đnh đã xét hay ch a;

queue – hàng đ i l u tr các đnh s đ c duy t c a đ th ;

void BFS(int u){

queue = φ;

u <= queue; (*n p u vào hàng đ i*)

chuaxet[u] = false; while (queue ≠φ ){ queue<=p; (* l y p ra t stack*) Th m_ nh(p); for v ke(p) { if (chuaxet[v] ) {

v<= queue; (*n p v vào hàng đ i*)

chuaxet[v] = false; } } } Th t c BFS s th m t t c các đnh dùng thành ph n liên thông v i u. th m t t c các đnh c a đ th , chúng ta ch c n th c hi n g i t i th t c BFS().

for( u=1; u≤n; u++)

chuaxet[u] = TRUE; for(u=1; u≤n; u++)

if (chuaxet[u])

BFS(u);

Ví d . Áp d ng thu t toán tìm ki m theo chi u r ng v i đ th trong hình 5.11 ta nh n đ c k t qu nh sau:

1, 2, 3, 11, 4, 6, 12, 13, 7, 8, 9, 10, 5;

5.3.3. Ki m tra tính liên thông c a đ th

M t đ th có th liên thông ho c có th không liên thông. N u đ th là liên thông (s thành ph n liên thông là 1), chúng ta ch c n g i t i th t c DFS() ho c BFS() m t l n. N u đ th là không liên thông, khi đó s thành ph n liên thông c a đ th chính b ng s l n g i t i th t c BFS() ho c DFS(). xác đnh s các thành ph n liên thông c a đ th , chúng ta s d ng m t bi n m i solt đ nghi nh n các đnh cùng m t thành ph n liên thông trong m ng chuaxet:

- N u đnh i ch a đ c duy t, chuaxet[i] có giá tr 0;

- N u đnh i đ c duy t thu c thành ph n liên thông th j=solt, ta ghi nh n

chuaxet[i]=solt;

- Các đnh cùng thành ph n liên thông n u chúng có cùng giá tr trong m ng chuaxet. void BFS(int u){

queue= φ;

u <= queue; (*n p u vào hàng đ i*)

solt = solt+1; chuaxet[u] = solt;(*solt là bi n toàn c c thi t l p giá tr 0*) while (queue ≠φ ) {

queue<=p; (* l y p ra t stack*) Th m_ nh(p);

for v ∈ ke(p) {

if (chuaxet[v] ){

v<= queue; (*n p v vào hàng đ i*)

chuaxet[v] = solt; } } } } 5.3.4. Tìm đ ng đi gi a hai đnh b t k c a đ th

Th t c BFS(s) ho c DFS(s) cho phép ta duy t các đnh cùng m t thành ph n liên thông v i đnh s. Nh v y, n u trong s các đnh liên thông v i s ch a t thì ch c ch n có đ ng đi t đnh sđ n đnh t. N u trong s các đnh liên thông v i đnh s không ch a đnh t

thì không t n t i đ ng đi t đnh s đ n đnh t. Do v y, chúng ta ch c n g i t i th t c

DFS(s) ho c BFS(s) và ki m tra xem đnh t có thu c thành ph n liên thông v i s hay không. D i đây là toàn v n ch ng trình tìm đ ng đi gi a hai đnh c a đ th .

#include <stdio.h> #include <conio.h> #include <io.h> #include <stdlib.h> #include <dos.h> #define MAX 100 #define TRUE 1

#define FALSE 0int n, truoc[MAX], chuaxet[MAX], queue[MAX]; int A[MAX][MAX]; int s, t;

/* Breadth First Search */ void Init(void){

FILE *fp; int i, j;

fp=fopen("lienth.IN", "r"); if(fp==NULL){

printf("\n Khong co file input"); delay(2000);return;

}

fscanf(fp,"%d", &n);

printf("\n Ma tran ke cua do thi:"); for(i=1; i<=n;i++){ printf("\n"); for(j=1; j<=n;j++){ fscanf(fp,"%d", &A[i][j]); printf("%3d", A[i][j]); } } for(i=1; i<=n;i++){ chuaxet[i]=TRUE; truoc[i]=0; } } void Result(void){ printf("\n\n"); if(truoc[t]==0){

printf("\n Khong co duong di tu %d den %d",s,t); getch();

return;

}

printf("\n Duong di tu %d den %d la:",s,t); int j = t;printf("%d<=", t); while(truoc[j]!=s){ printf("%3d<=",truoc[j]); j=truoc[j]; } printf("%3d",s); } void In(void){ printf("\n\n"); for(int i=1; i<=n; i++)

printf("%3d", truoc[i]); }

void BFS(int s) {

int dauQ, cuoiQ, p, u;printf("\n");

dauQ=1;cuoiQ=1; queue[dauQ]=s;chuaxet[s]=FALSE; while (dauQ<=cuoiQ){

u=queue[dauQ]; dauQ=dauQ+1; printf("%3d",u);

if(A[u][p] && chuaxet[p]){ cuoiQ=cuoiQ+1;queue[cuoiQ]=p; chuaxet[p]=FALSE;truoc[p]=u; } } } } void duongdi(void){

int chuaxet[MAX], truoc[MAX], queue[MAX]; Init();BFS(s);Result();

}

void main(void){ clrscr();

printf("\n Dinh dau:"); scanf("%d",&s); printf("\n Dinh cuoi:"); scanf("%d",&t); Init();printf("\n");BFS(s);

n();getch(); Result();getch(); }

5.4. NG I VÀ CHU TRÌNH EULER

Chu trình đ n trong đ th Gđi qua m i c nh c a đ th đúng m t l n đ c g i là chu trình Euler. ng đi đ n trong G đi qua m i c nh c a nó đúng m t l n đ c g i là đ ng đi Euler. th đ c g i là đ th Euler n u nó có chu trình Euler. th có đ ng đi Euler đ c g i là n a Euler.

Rõ ràng, m i đ th Euler đ u là n a Euler nh ng đi u ng c l i không đúng.

Ví d 1. Xét các đ th G1, G2, G3 trong hình 5.12. a b a b a b e e d c d c c d e G1 G2 G3 Hình 5.12. th vô h ng G1, G2, G3.

th G1 là đ th Euler vì nó có chu trình Euler a, e, c, d, e, b, a. th G3 không có chu trình Euler nh ng ch a đ ng đi Euler a, c, d, e, b, d, a, b vì th G3 là n a Euler. G2 không có chu trình Euler c ng nh đ ng đi Euler.

nh lý. th vô h ng liên thông G=<V, E> là đ th Euler khi và ch khi m i đnh c a Gđ u có b c ch n. th vô h ng liên thông G=<V, E> là đ th n a Euler khi và ch khi nó không có quá hai đnh b c l .

tìm m t chu trình Euler, ta th c hi n theo thu t toán sau:

̇ T o m t m ng CE đ ghi đ ng đi và m t stack đ x p các đnh ta s xét. X p vào đó m t đnh tu ý u nào đó c a đ th , ngh a là đnh u s đ c xét đ u tiên.

̇ Xét đnh trên cùng c a ng n x p, gi s đnh đó là đnh v; và th c hi n: X N u v là đnh cô l p thì l y v kh i ng n x p và đ a vào CE;

X N u v là liên thông v i đnh x thì x p x vào ng n x p sau đó xoá b c nh (v, x); ̇ Quay l i b c 2 cho t i khi ng n x p r ng thì d ng. K t qu đ ng đi Euler

đ c ch a trong CE theo th t ng c l i.

Th t c Euler_Cycle sau s cho phép ta tìm chu trình Euler. void Euler_Cycle(int u){

Stack=φ; CE=φ;

u=>Stack; { n p u vào stack}; while (Stack≠φ) {

x= top(Stack); { x là ph n t đ u stack } if (ke(x) ≠φ) {

y = nh đ u trong danh sách ke(x); Stack<=y; { n p y vào Stack}; Ke(x) = Ke(x) \{y};

Ke(y) = Ke(y)\{x}; {lo i c nh (x,y) kh i đ th };

} else { x<= Stack; {l y x ra kh i stack}; CE <=x; { n p x vào CE;} } }

Ví d . Tìm chu trình Euler trong hình 5.13.

a b

4

1 2 3 5 6 7

f 8 c 9 d 10 e

Các b c th c hi n theo thu t toán s cho ta k t qu sau:

B c Giá tr trong stack Giá tr trong CE C nh còn l i

1 F 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 2 f, a 2, 3, 4, 5, 6, 7, 8, 9, 10 3 f, a, c 3, 4, 5, 6, 7, 8, 9, 10 4 f,a,c,f 3, 4, 5, 6, 7, 9, 10 5 f, a, c f 3, 4, 5, 6, 7, 9, 10 6 f, a, c, b f 3, 4, 6, 7, 9, 10 7 f, a, c, b, d f 3, 4, 7, 9, 10 8 f, a, c, b, d,c f 3, 4, 7, 10 9 f, a, c, b, d f, c 3, 4, 7, 10 10 f, a, c, b, d, e f, c 3, 4, 7 11 f, a, c, b, d, e, b f, c 3, 4 12 f, a, c, b, d, e, b, a f, c 3 13 f, a, c, b, d, e, b, a, d f, c 14 f, a, c, b, d, e, b, a f, c, d 15 f, a, c, b, d, e, b f,c,d,a 16 f, a, c, b, d, e f,c,d,a,b 17 f, a, c, b, d f,c,d,a,b,e 18 f, a, c, b f,c,d,a,b,e,d 19 f, a, c f,c,d,a,b,e,d,b 20 f, a f,c,d,a,b,e,d,b,c 21 f f,c,d,a,b,e,d,b,c,a 22 f,c,d,a,b,e,d,b,c,a,f

M t đ th không có chu trình Euler nh ng v n có th có đ ng đi Euler. Khi đó, đ th có đúng hai đnh b c l , t c là t ng các s c nh xu t phát t m t trong hai đnh đó là s l . M t đ ng đi Euler ph i xu t phát t m t trong hai đnh đó và k t thúc đnh kia. Nh v y, thu t toán tìm đ ng đi Euler ch khác v i thu t toán tìm chu trình Euler ch ta ph i xác đnh đi m xu t phát c a đ ng đi.

tìm t t c các đ ng đi Euler c a m t đ th n đnh, m c nh, ta có th dùng k thu t đ qui nh sau:

̇B c 1. T o m ng b có đ dài m + 1 nh m t ng n x p ch a đ ng đi. t b[0]=1, i=1 (xét đnh th nh t c a đ ng đi);

̇B c 2. L n l t cho b[i] các giá tr là đnh k v i b[i-1] mà c nh (b[i-1],b[i])

không trùng v i nh ng c nh đã dùng t b[0] đ n b[i-1]. V i m i giá tr c a b[i], ta ki m tra:

X N u i<m thì t ng i lên 1đ n v (xét đnh ti p theo) và quay l i b c 2. X N u i=m thì dãy b chính là m t đ ng đi Euler.

5.5. NG I VÀ CHU TRÌNH HAMILTON

V i đ th Euler, chúng ta quan tâm t i vi c duy t các c nh c a đ th m i c nh đúng m t l n, thì trong m c này, chúng ta xét đ n m t bài toán t ng t nh ng ch khác nhau là ta ch quan tâm t i các đnh c a đ th , m i đnh đúng m t l n. S thay đ i này t ng nh không đáng k , nh ng th c t có nhi u s khác bi t trong khi gi i quy t bài toán.

nh ngh a. ng đi qua t t c các đnh c a đ th m i đnh đúng m t l n đ c g i là đ ng đi Hamilton. Chu trình b t đ u t i m t đnh v nào đó qua t t c các đnh còn l i m i đnh đúng m t l n sau đó quay tr l i vđ c g i là chu trình Hamilton. th đ c g i là đ th Hamilton n u nó ch a chu trình Hamilton. th ch a đ ng đi Hamilton đ c g i là đ th n a Hamilton.

Nh v y, m t đ th Hamilton bao gi c ng là đ th n a Hamilton nh ng đi u ng c l i không luôn luôn đúng. Ví d sau s minh h a cho nh n xét này.

Ví d . th đ thi hamilton G3, n a Hamilton G2 và G1.

a a b a b

b c c d c d

G1 G2 G3

Hình 5.14. th đ thi hamilton G3, n a Hamilton G2 và G1.

Cho đ n nay, vi c tìm ra m t tiêu chu n đ nh n bi t đ th Hamilton v n còn m , m c dù đây là v n đ trung tâm c a lý thuy t đ th . H n th n a, cho đ n nay c ng v n ch a có thu t toán hi u qu đ ki m tra m t đ th có ph i là đ th Hamilton hay không.

li t kê t t c các chu trình Hamilton c a đ th , chúng ta có th s d ng thu t toán sau: void Hamilton(int k){

(* Li t kê các chu trình Hamilton c a đ th b ng cách phát tri n dãy đnh (X[1], X[2], . . ., X[k-1] ) c a đ th G = (V, E) *)

for y∈ Ke(X[k-1]) {

if ((k==n+1) && (y == v0)) Ghinhan(X[1], X[2], . . ., X[n], v0);

else {

X[k]=y; chuaxet[y] = false; Hamilton(k+1); chuaxet[y] = true;

};

5.6. CÂY BAO TRÙM

5.6.1. Khái ni m và đnh ngh a

nh ngh a 1. Ta g i cây là đ th vô h ng liên thông không có chu trình. th không có chu trình đ c g i là r ng.

Nh v y, r ng là đ th mà m i thành ph n liên thông c a nó là m t cây. Ví d . R ng g m 3 cây trong hình 5.15.

T1 T2 T3

Hình 5.15 . R ng g m 3 cây T1, T2, T3.

Cây đ c coi là d ng đ th đ n gi n nh t c a đ th . nh lý sau đây cho ta m t s tính ch t c a cây.

nh lý. Gi s G=<V, E> là đ th vô h ng n đnh. Khi đó nh ng kh ng đnh sau là t ng đ ng

a. G là m t cây.

b. G là đ th vô h ng liên thông không có chu trình. c. G liên thông và có đúng n-1 c nh.

d. Gi a hai đnh b t k c a G có đúng m t đ ng đi. e. G liên thông và m i c nh c a nó đ u là c u.

f. G không ch a chu trình nh ng h c thêm vào nó m t c nh ta thu đ c đúng m t chu trình.

nh ngh a 2.Cho G là đ th vô h ng liên thông. Ta g i đ th con T c a G là m t cây bao trùm hay cây khung n u T tho mãn hai đi u ki n:

g. T là m t cây;

h. T p đnh c a T b ng t p đnh c a G.

i v i cây bao trùm, chúng ta quan tâm t i nh ng bài toán c b n sau:

Một phần của tài liệu Kỹ Thuật Lập Trình (Trang 111 - 156)

Tải bản đầy đủ (PDF)

(156 trang)