d) Cài đặt thuật toán
6.5.1. Xây dựng cây khung của đồ thị bằng thuật toán DFS
Khi ta thực hiện thủ tục tìm kiếm theo chiều sâu bắt đầu tại đỉnh uV, ta nhận được tập đỉnh vV có cùng thành phần liên thông với u. Nếu DFS(u) = V thì ta kết luận đồ thị liên thông và phép duyệt DFS(u) đi qua đúng n-1 cạnh. Nếu Nếu DFS(u) V thì ta kết luận đồ thị không liên thông. Chính vì vậy, ta có thể sử dụng phép duyệt DFS(u) để xây dựng cây khung của đồ thị. Trong mỗi bước của thuật toán DFS, xuất phát tại đỉnh u ta sẽ thăm được đỉnh v và ta kết nạp cạnh (u,v) vào tập cạnh của cây khung. Các bước tiếp theo được tiến hành tại đỉnh v cho đến khi kết thúc thuật toán DFS. Thuật toán được xây dựng dựa vào ngăn xếp được mô tả chi tiết trong Hình 5.14.
a) Biểu diễn thuật toán
Hình 5.14. Xây dựng cây khung của đồ thị bằng thuật toán DFS.
Thuật toán Tree-DFS(u):
Begin
Bước 1 (Khởi tạo):
T = ; //tập cạnh cây khung ban đầu.
stack = ; //thiết lập stack rỗng; Push(stack, u); //đưa u vào stack;
chuaxet[u] = False;//bật trạng thái đã xét của đỉnh u
Bước 2 (Lặp):
while (stack ) do { //lặp cho đến khi stack rỗng
s = Pop(stack); //lấy s ra khỏi stack
for each tKe(s) do { //lặp trên danh sách Ke(s)
if (chuaxet[t] ) then { //nếu đỉnh t chuaxet
Push(stack, s);// đưa s vào stack trước
Push(stack, s);// đưa t vào stack sau
T = T(s,t); //kết nạp (s,t) vào cây khung
chuaxet[t] = False; //ghi nhận t đã xét
break ;//chỉ lấy đỉnh đầu tiên
endif ; endfor ; endwwhile ;
Bước 3 (Trả lại kết quả) :
if (| T | < n-1 ) <Đồ thị không liên thông> ; else <Ghi nhận tập cạnh T của cây khung> ;
NGUYỄN DUY PHƯƠNG 202
b) Độ phức tạp thuật toán
Độ phức tạp thuật toán Tree-DFS(u) đúng bằng độ phức tạp thuật toán DFS(u).
c) Kiểm nghiệm thuật toán
Bạn đọc tự tìm hiểu và kiểm nghiệm thuật toán trong các tài liệu tham khảo liên quan.
d) Cài đặt thuật toán
#include<iostream> #include <list> #include <fstream> #include <iomanip> #include <stack> using namespace std;
struct canh{ //biểu diễn một cạnh của đồ thị
int dau; //đỉnh đầu của cạnh
int cuoi; //đỉnh cuối của cạnh
};
class Graph{ //xây dựng lớp đồ thị
private:
int V; // số đỉnh của đồ thị
list<int> *adj; // con trỏ đến mảng các danh sách kề
bool *chuaxet; //mảng chưa xét
canh *T;//tập cạnh của cây khung
int sc; //số cạnh của cây khung
public:
Graph(int V); // constructor của lớp
void addEdge(int v, int w); // thêm một cạnh vào đồ thị void Tree_BFS(int u);//thuật toán Tree-BFS
void Tree_DFS(int u);//thuật toán Tree-DFS
};
Graph::Graph(int V){ //constructor của lớp
this->V = V;//thiết lập tập đỉnh
adj = new list<int>[V];//thiết lập V danh sách kề
T = new canh[V]; sc =1; //thiết lập số cạnh cây khung
chuaxet = new bool[V];//thiết lập giá trị mảng chưa xét
for(int u=0; u<V; u++) chuaxet[u]=true; }
void Graph::addEdge(int v, int w){ //thêm một cạnh vào danh sách kề