Một số bài hướng dẫn thực hành Lý thuyết đồ thịCreated by NgoHung Vấn đề 1: Biểu diễn đồ thị và duyệt đồ thị 1.. Biểu diễn đồ thị Xây dựng các hàm phục vụ cho việc tạo ma trận kề của đồ
Trang 1Một số bài hướng dẫn thực hành Lý thuyết đồ thị
Created by NgoHung
Vấn đề 1: Biểu diễn đồ thị và duyệt đồ thị
1 Biểu diễn đồ thị
Xây dựng các hàm phục vụ cho việc tạo ma trận kề của đồ thị cần biễu diễn, gồm có:
- Nhập ma trận kề: Cho phép nhập thông tin về đồ thị bằng tay gồm số đỉnh N, các giá trị Ai,j của ma trận kề
- Đọc ma trận kề từ file: Cho phép nhập thông tin về đồ thị từ file chứa các giá trị của
ma trận kề gồm số đỉnh N, các giá trị Ai,j
- Xuất ma trận kề: In thông tin về đồ thị ở dạng ma trận kề gồm các giá trị Ai,j
Source code :
#define MaxV 20 //Define su dung cho so dinh cuc dai cua do thi
int A[MaxV][MaxV]; //Ma tran ke
int V = 0; //So dinh cua do thi
int ChuaXet[MaxV];
//Thu tuc nhap matran ke bang ban phim
void NhapMTKe(int A[][MaxV], int &V)
{
printf("Nhap V:");
scanf("%d", &V);
for (int i=0; i<V; i++)
{
Trang 2for (int j=0; j<V; j++)
{
printf("A[%d,%d] = ", i+1, j+1);
scanf("%d", &(A[i][j]));
}
}
}
// Xuat ket qua ma tran ke cua do thi ra man hinh
void XuatMTKe(int A[][MaxV], int V)
{
printf("\nMa tran ke:\n");
for (int i=0; i<V; i++)
{
for (int j=0; j<V; j++)
printf("%3d ", A[i][j]);
printf("\n");
}
}
//Doc du lieu ma tran ke cua do thi da duoc tao thanh file text luu san tren dia
int DocMTKe(char *fileName, int A[][MaxV], int &V)
{
FILE *f = fopen(fileName, "rt");
if (f == NULL)
Trang 3{
printf("Doc file loi !!!");
return 0;
}
fscanf(f, "%d", &V);
for (int i=0; i<V; i++)
{
for (int j=0; j<V; j++)
{
fscanf(f, "%d", &(A[i][j]));
}
}
return 1;
}
2 Duyệt đồ thị
Sử dụng các phương pháp duyệt đồ thị để cài đặt thành các hàm duyệt đồ thị:
- Duyệt theo chiều sâu có sử dụng đệ quy
- Duyệt theo chiều sâu không sử dụng đệ quy, sử dụng STACK thay thế
- Duyệt theo chiều rộng sử dụng cấu trúc QUEUE
Source code các hàm
//Thu tuc duyet DFS, duyet theo chieu sau su dung ky thuat de quy
void DFS(int v)
{
ChuaXet[v] = 1;
for ( int u=0; u<V; u++ )
Trang 4if ( A[v][u]!=0 ) //The hien u la dinh ke cua v
if ( ChuaXet[u]==0 )
DFS( u ); //Dinh u chua duoc duyet qua==> Duyet u }
//Thu tuc duyet DFS, duyet theo chieu sau su dung STACK de khu de quy
void DFS0DeQuy(int v)
{
int STACK[MaxV], topS = 0; //Khoi tao STACK voi mot STACT rong
STACK[topS++] = v; //Dua dinh v vao dinh STACK
ChuaXet[v] = 0; //Xem nhu da duyet dinh v
while(topS > 0) //Lap trong khi STACK khac rong
{
v = STACK[ topS]; //Lay mot dinh v tu dinh cua STACK ra
for (int u=V-1; u>=0; u )
if (A[v][u] != 0) //Xet dinh u ke voi dinh v
if ( ChuaXet[u]==0 )
{
STACK[topS++] = u; //Dua u vao dinh STACK ChuaXet[u] = 1; //Xem dinh nay la da xet }
}
Trang 5//Thu tuc duyet DFS, duyet theo chieu rong su dung QUEUE de chay khong de quy
void BFS0DeQuy(int v)
{
int QUEUE[MaxV], topQ=0, bottomQ=0; //Khoi dau voi mot QUEUE rong
QUEUE[topQ++] = v; //Dua dinh v vao QUEUE, xem no nhu la da xet
ChuaXet[v] = 1;
while ( bottomQ < topQ ) //Lap trong khi QUEUE khac rong
{
v = QUEUE[bottomQ++]; //Lay dinh v tu day cua QUEUE
for (int u=0; u<V; u++)
if ( A[v][u] != 0 ) //The hien u ke voi dinh v
if ( ChuaXet[u]==0 )
{
QUEUE[topQ++] = u; // Dua u vao dinh cua QUEUE ChuaXet[u] = 1;
}
}
}
Trang 6Xây dựng hàm main( ) tiến hành gọi thuật toán duyệt đồ thị:
+ Gọi hàm đọc, xuất ma trận kề của đồ thị
+ Gọi hàm duyệt đồ thị với đỉnh bất kỳ, ví dụ như đỉnh đầu tiên ( đỉnh 0 ) + In ra các thành phần đã duyệt được trong đồ thị bơi
Source code hàm main( )
int main(int argc, char* argv[])
{
DocMTKe("D:\\Dothi_1.txt", A, V);
XuatMTKe(A, V);
memset(ChuaXet, 0, sizeof(ChuaXet) );
DFS0DeQuy(v);
printf( "Các dinh da duyet: " );
if (ChuaXet[j] == tp)
printf( "%d ", v+1 );
getch ( );
}
Tạo mới file đồ thị D:\\Graph_1.TXT ở dạng ma trận kề, ví dụ:
13
0 1 0 1 0 0 0 0 0 0 0 1 0
1 0 0 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0 0
1 1 0 0 0 1 1 0 0 0 0 0 0
0 0 0 0 0 1 0 1 1 0 0 0 0
Trang 70 0 0 0 1 0 1 0 0 0 0 0 1
0 0 1 1 0 1 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 1 0 0 0 0
0 0 0 0 1 0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 1 0
0 0 0 0 0 0 0 0 0 1 0 1 0
1 0 0 0 0 0 0 0 0 1 1 0 0
0 0 0 0 0 1 0 0 0 0 0 0 0
3 Thành phần liên thông
Để tìm số thành phần liên thông, thì mỗi lầ duyệt hãy gán cho mỗi thành phần liên thông một chỉ
số vào giá trị của mảng ChuaXet, thay vì luôn ghi giá trị là 1 Các đỉnh của cùng thành phần liên thông sẽ có giá trị lưu trong ChuaXet giống nhau
Các bước tiến hành:
1. Truyền tham so nSoTPLT ve thành phần liên thông đang duyệt cho các hàm duyệt, cụ thể là:
void DFS0DeQuy(int v, int nSoTPLT)
void BFS0DeQuy(int v, int nSoTPLT)
void DFS0DeQuy(int v, int nSoTPLT)
2. Thay thế chỉ số index cho các thành phần liên thông trong các hàm duyệt:
Thay thế các dòng gán ChuaXeti = 0 thành ChuaXet[i ] = nSoTPLT
Ví dụ:
ChuaXet[v] = nSoTPLT; //Xem dinh nay la da xet
Chỉnh sửa lại hàm main ( ) để in ra tất cả các đỉnh của từng thành phần liên thông
int main(int argc, char* argv[])
{
int nSoTPLT = 0;
Trang 8DocMTKe("D:\\Graph_1.TXT", A, V);
XuatMTKe(A, V);
for (int v=0; v<V; v++)
if (ChuaXet[v] == 0)
DFS0DeQuy(v, ++nSoTPLT);
for (int tp=1; tp<=nSoTPLT; tp++)
{
cout<<"\nTPLT thu "<<tp<<" gom dinh:";
for (v=0; v<V; v++)
if (ChuaXet[v] == tp)
cout<<v+1<<" ";
cout<<"\n";
}
}
1 Tìm đường đi
+ Khai báo mảng lưu vết :
int DinhTruoc[MaxV];
+ Bổ sung để hàm duyệt DFS lưu vết tìm đường đi:
//Thu tuc duyet DFS, duyet theo chieu sau su dung ky thuat de quy
void DFS(int v)
{
ChuaXet[v] = nSoTPLT;
Trang 9for ( int u=0; u<V; u++ )
if ( A[v][u]!=0 ) //The hien u la dinh ke cua v
if ( ChuaXet[u]==0 )
{
DinhTruoc[u] = v;
DFS( u ); //Dinh u chua duoc duyet qua==> Duyet u }
}
+ Hoàn thiện hàm main ( ) để tìm đường đi từ s đến t
int main(int argc, char* argv[])
{
int nSoTPLT = 0;
DocMTKe("D:\\1.TXT", A, V);
XuatMTKe(A, V);
int s, t;
cout<<"Nhap dinh bat dau, dinh ket thuc:"; cin>>s>>t;
s ; t ;
DFS(s);
int DuongDi[MaxV], k = 0;
DuongDi[k++] = t;
while ( DinhTruoc[ DuongDi[k-1] ] != s)
DuongDi[k++] = DinhTruoc[ DuongDi[k-1] ];
Trang 10DuongDi[k++] = s;
cout<<"\nDuong di tu "<<s<<" den "<<t<<" la: "; for ( int i=k-1; i>=0; i )
cout<<DuongDi[ i ] +1<<" ";
getch( );
}