Xây dựng cây khung của đồ thị bằng thuật toán DFS

Một phần của tài liệu Bài giảng Cấu trúc dữ liệu và giải thuật (2016): Phần 2 (Trang 77 - 80)

6.5. Bài toán xây dựng cây khung của đồ thị

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 uV, ta nhận được tập đỉnh vV 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 tKe(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> ; end.

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ề adj[v].push_back(w); // thêm w vào list(v)

NGUYỄN DUY PHƯƠNG 203

adj[w].push_back(v); // thêm v vào list(w) }

void Graph::Tree_DFS(int u){

//Bước 1 (Khởi tạo):

stack <int> Stack; //tạo lập stack rỗng Stack.push(u);//đưa u vào ngăn xếp chuaxet[u] = false; //xác nhận u đã xét list<int>::iterator t; //t là iterator của list while(!Stack.empty()){//lặp đến khi stack rỗng

int s = Stack.top(); //lấy s là đỉnh đầu ngăn xếp Stack.pop();//loại s ra khỏi ngăn xếp

for (t = adj[s].begin(); t != adj[s].end(); ++t){//duyệt trên list(s) if(chuaxet[*t]){//nếu đúng t chưa xét

Stack.push(s);//đưa s vào stack trước

Stack.push(*t); //đưa t vào stack sau

chuaxet[*t]=false; //ghi nhận t đã xét

T[sc].dau = s;T[sc].cuoi = *t;//thêm (s,t) vào cây

sc++; //tăng số cạnh lên 1

break;//chỉ lấy đỉnh đầu tiên

} }

}

if(sc<V-1){//nếu |T|<n-1

cout<<"\n Đồ thị không liên thông";

} else {

cout<<"\n Tập cạnh cây khung:"<<endl;

for(int i=1; i<sc; i++){

cout<<T[i].dau<<setw(3)<<T[i].cuoi<<endl;

} }

}

int main(void){

ifstream fp("Graph.in"); //mở file để đọc int n, m, dau, cuoi;

fp>>n>>m;//đọc số đỉnh và số cạnh của đồ thị Graph gh(n+1);//thiết lập đồ thị gồm n đỉnh

NGUYỄN DUY PHƯƠNG 204

for(int i=1; i<=m; i++){//chuyển đồ thị sang danh sách kề fp>>dau>>cuoi;

gh.addEdge(dau, cuoi);

}

fp.close();

gh.printGraph();

gh.Tree_BFS(1);

}

Một phần của tài liệu Bài giảng Cấu trúc dữ liệu và giải thuật (2016): Phần 2 (Trang 77 - 80)

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

(101 trang)