Thử nghiệm thuật toán

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 91 - 95)

Bạn đọc tự tìm hiểu phương pháp thử nghiệm thuật toán Dijkstra trong các tài liệu liên quan.

d) Cài đặt thuật toán

#include <iostream> #include <fstream> #define MAX 100 using namespace std;

//hàm tìm đỉnh có nhãn nhỏ nhất

int minDistance(int dist[], bool sptSet[], int n){ // thiết lập nhãn nhỏ nhất ban đầu

int min = INT_MAX, min_index; for (int v = 1; v <= n; v++){

if (sptSet[v] == false && dist[v] <= min){ min = dist[v]; min_index = v;

}

}

return min_index;//đỉnh có nhãn nhỏ nhất

}

// hàm in ra độ dài đường đi ngắn nhất

int printSolution(int dist[], int n){ printf("Đường đi ngắn: \n"); for (int i = 1; i <= n; i++)

printf("%d \t\t %d\n", i, dist[i]); }

// thuật toán Dijkstra sử dụng ma trận kề

void dijkstra(int graph[MAX][MAX], int src, int n) {

int dist[MAX]; // dist[i] sẽ là độ dài đường đi ngắn nhất từ src đến i bool sptSet[MAX]; //lưu trữ đường đi ngắn nhất từ src đến i

//Bước 1 (khởi tạo): thiết lập tất cả độ dài là INF. for (int i = 1; i <= n; i++){

dist[i] = INT_MAX; sptSet[i] = false; }

dist[src] = 0; //nhãn đỉnh xuất phát lấy là 0

//Bước 2(lặp): tìm đường đi ngắn nhất từ src đến tất cả các đỉnh

NGUYỄN DUY PHƯƠNG 216 int u = minDistance(dist, sptSet,n);//lấy u là đỉnh có nhãn nhỏ nhất int u = minDistance(dist, sptSet,n);//lấy u là đỉnh có nhãn nhỏ nhất

sptSet[u] = true; //đánh dấu đỉnh u đã là đường đi ngắn nhất

// cập nhật nhãn các đỉnh còn lại

for (int v = 1; v <= n; v++) {

if (!sptSet[v] && graph[u][v] && dist[u] != INT_MAX && dist[u]+graph[u][v] < dist[v])

dist[v] = dist[u] + graph[u][v]; }

}

printSolution(dist, n); // in ra đường đi ngắn nhất

}

int main() {

int n, m, dau, cuoi, trongso; //khai báo số đỉnh và số cạnh: n, m

int graph[MAX][MAX]; //ma trận kề biểu diễn đồ thị

ifstream fp("dothiw.in"); //file biểu diễn đồ thị dưới dạng danh sách cạnh

fp>>n>>m; //đọc số cạnh và số đỉnh của đồ thị

for(int i=1; i<=m; i++){ //đọc m cạnh: (dau, cuoi, trongso) fp>>dau>>cuoi>>trongso;

graph[dau][cuoi]= trongso;

graph[cuoi][dau]= trongso;//bỏ đi nếu là đồ thị có hướng

}

fp.close();

dijkstra(graph, 1, 9); }

6.6.2. Thuật toán Bellman-Ford

Thuật toán Bellman-Ford dùng để tìm đường đi ngắn nhất trên đồ thị không có chu trình âm. Do vậy, trong khi thực hiện thuật toán Bellman-Ford ta cần kiểm tra đồ thị có chu trình âm hay không. Trong trường hợp đồ thị có chu trình âm, bài toán sẽ không có lời giải. Thuật toán được thực hiện theo k = n - 2 vòng lặp trên tập đỉnh hoặc tập cạnh tùy thuộc vào dạng biểu diễn của đồ thị. Nếu đồ thị được biểu diễn dưới dạng ma trận kề, độ phức tạp thuật toán là O(V3), với V là số đỉnh của đồ thị. Trong trường hợp đồ thị được biểu diễn dưới dạng danh sách cạnh, độ phức tạp thuật toán là O(V.E), với V là số đỉnh của đồ thị, E là số cạnh của đồ thị. Thuật toán được mô tả chi tiết trong Hình 5.18 cho đồ thị biểu diễn dưới dạng ma trận kề.

NGUYỄN DUY PHƯƠNG 217

a) Biểu diễn thuật toán

Hình 5.18. Thuật toán Bellman-Ford

b) Độ phức tạp thuật toán

Độ phức tạp thuật toán là O(VE), trong đó V, E là số đỉnh và số cạnh của đồ thị. Bạn đọc tự tìm hiểu và chứng minh độ phức tạp thuật toán Bellman-Ford trong các tài liệu liên quan.

c) Thử nghiệm thuật toán

Bạn đọc tự tìm hiểu phương pháp thử nghiệm thuật toán Bellman-Ford trong các tài liệu liên quan.

d) Cài đặt thuật toán

#include <iostream.h> #include <stdlib.h> #include <stdio.h> #include <conio.h> #define MAX 100 #define MAXC 10000

Thuật toán Bellman-Ford (s): //s V là đỉnh bất kỳ của đồ thị

Begin:

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

for vV do { //Sử dụng s gán nhãn cho các đỉnh vV D[v] = A[s][v]; Truoc[v] = s; } Bước 2 (Lặp) : D[s] = 0; K=1; while (K<=N-2 ) { //N-2 vòng lặp

for vV\{s} do { //Lấy mỗi đỉnh vV\s

for uV do { //Gán nhãn cho v if (D[v] > D[u] + A[u][v] ) { D[v]= D[u] + A[u][v]; Truoc[v] = u; endif; endfor; endfor; endwlie;

Bước 3 (Trả lại kết quả):

Return( D[v], Truoc[v]: vU);

NGUYỄN DUY PHƯƠNG 218 int C[MAX][MAX]; //Ma tran trong so bieu dien do thi int C[MAX][MAX]; //Ma tran trong so bieu dien do thi

int D[MAX]; //Do dai duong di int Trace[MAX]; //Luu lai vet duong di

int n, m, S, F; // n:So dinh; S: Dinh bat dau; F: Dinh ket thuc FILE *fp;

void Read_Data(void){

int i, u, v;fp = fopen("dothi.in","r");

fscanf(fp,"%d%d%d%d",&n,&m,&S,&F); for(u=1; u<=n; u++)

for(v=1; v<=n; v++)

if (u==v) C[u][v]=0;

else C[u][v]=MAXC; for(i=1; i<=m; i++)

fscanf(fp,"%d%d%d",&u,&v,&C[u][v]); fclose(fp);

}

void Init(void){ int i;

for( i=1; i<=n; i++){ D[i] = C[S][i]; Trace[i]=S; }

}

void Result(void){

if (D[F]==MAXC) printf("\n Khong co duong di"); else {

printf("\n Do dai %d den %d: %d", S, F, D[F]); while (F!=S ){ printf("%d <--",F); F = Trace[F]; } } } void Ford_Bellman(void){ int k, u, v;D[S]=0; for( k=1; k<=n-2; k++){ for(v=1; v<=n; v++){

for( u=1; u<=n; u++){

if (D[v]>D[u]+C[u][v]){ D[v] = D[u]+C[u][v]; Trace[u]=v;

} }

NGUYỄN DUY PHƯƠNG 219 } } } } int main() { Read_Data();Init(); Ford_Bellman(); Result(); system("PAUSE"); return 0; }

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 91 - 95)

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

(101 trang)