???? 不想麻煩聲明函數(shù),所以把實(shí)現(xiàn)寫(xiě)到頭文件中了,只剩下一個(gè)cpp文件main.cpp.
??? 本程序?qū)崿F(xiàn)了深度優(yōu)先搜索非遞歸算法和單源最短路徑Bellman_Ford算法;
??? DFS用非遞歸效率高,因?yàn)檩斎胍?guī)模太大,遞歸讓我電腦吃不消,
?? Bellman_Ford算法可以處理負(fù)權(quán)值圖,這點(diǎn)比Dijkstra算法好.
1
/**//******************************************
2
?程序名稱:DFS和Bellman_Ford算法的實(shí)現(xiàn)
3
?作者:pengkuny
4
?主頁(yè):http://www.shnenglu.com/pengkuny
5
?郵箱:pengkuny@163.com
6
?參考書(shū)籍:<<Introduction?to?Agrithms>>
7
?完成日期:2006.11.30
8
******************************************/ ALGraph.h
?1
/**//*?ALGraph.h?圖的鄰接表存儲(chǔ)表示?*/
?2
#ifndef?ALGRAPH_H
?3
#define?ALGRAPH_H
?4
?5
#include<iostream>
?6
#include<cstdio>
?7
#include<cmath>
?8
#include<cstring>
?9
10
using?namespace?std;
11
12
#define?wuqiong?65535??????//初始權(quán)值無(wú)窮大
13
14
typedef?enum?
{WHITE,GRAY,BLACK};
15
16
typedef?struct?VNode?VNode;
17
18
typedef?struct?ArcNode
19

{
20
????int?????????adjvex;??/**//*?原頂點(diǎn)?*/
21
????ArcNode*????next;????/**//*?指向下一條弧的指針?*/
22
????long????????weight;??/**//*?權(quán)值?*/
23
}ArcNode;????????????????????/**//*?表結(jié)點(diǎn)?*/
24
25
26
typedef?struct?VNode
27

{????
28
????int????????adjvex;???????????/**//*?頂點(diǎn)序號(hào)????*/
29
????int???????????color;????????????/**//*?頂點(diǎn)顏色????*/
30
????long????????d;???????????????/**//*?頂點(diǎn)最初DFS發(fā)現(xiàn)時(shí)間?;?兼作Dijkstra算法中當(dāng)前最短路徑?*/
31
????long????????f;???????????????/**//*?頂點(diǎn)最終DFS結(jié)束時(shí)間?*/
32
????VNode?*?????father;
33
????ArcNode?*???next;?????????/**//*?第一個(gè)表結(jié)點(diǎn)的地址,指向第一條依附該頂點(diǎn)的弧的指針?*/
34
}VNode,*?AdjList?;?/**//*?頭結(jié)點(diǎn)?*/
35
36
37
typedef?struct
38

{
39
????AdjList?vertices;????????????????/**//*?表結(jié)點(diǎn)指針(一個(gè)頭結(jié)點(diǎn)數(shù)組)?*/
40
????int?????vexnum,arcnum;???????????/**//*?圖的當(dāng)前頂點(diǎn)數(shù)和弧數(shù)?*/
41
}ALGraph;
42
??
43
44
#endif//ALGRAPH_H Stack.h: 棧的表示,DFS使用棧非遞歸
?1
/**//*?Stack.h?圖的鄰接表存儲(chǔ)表示?*/
?2
#ifndef?STACK_H
?3
#define?STACK_H
?4
?5
#include?"ALGraph.h"
?6
?7
#include<iostream>
?8
#include<cstdio>
?9
#include<cmath>
10
#include<cstring>
11
12
using?namespace?std;
13
14
typedef?struct??LinkList
15

{
16
????VNode?*??data;????//棧中只保存圖頂點(diǎn)指針
17
????LinkList?*?next;??//下一個(gè)頂點(diǎn)
18
}LinkList;
19
20
typedef?struct??Stack
21

{
22
????LinkList?*?top;
23
}Stack;
24
25
26
void?InitStack(Stack?&S)
27

{
28
????S.top?=?NULL;
29
}
30
31
bool?Empty(Stack?S)
32

{
33
????if?(S.top?==?NULL)
34
????
{
35
????????return?true;
36
????}
37
????return?false;
38
}
39
40
void?Push(Stack?&S,?VNode*?k)
41

{
42
43
????LinkList?*?p?=?new?LinkList;
44
????p->data?=?k;
45
????p->next?=?S.top;
46
????S.top?=?p;
47
}
48
49
VNode*?GetTop(Stack&?S)
50

{
51
????return?S.top->data;
52
}
53
54
VNode*?Pop(Stack&?S)
55

{
56
????LinkList*?p?=?S.top;//保存棧頂指針
57
????VNode*?q;
58
????if(Empty(S))
59
????
{
60
????????cout<<"Stack?underflow.";??//下溢
61
????????exit(1);
62
????}
63
64
????S.top?=?p->next;??//將棧頂結(jié)點(diǎn)從鏈上摘下
65
66
????q?=?p->data;//回收??臻g,不可以寫(xiě)成q=p;delete?p;return?q->data;
67
????delete?p;???//因?yàn)閐elete?p之后,p所指的空間已不可用
68
69
????return?q;
70
}
71
72
73
#endif//STACK_H CTimer.h:CTimer類,計(jì)時(shí)功能,單位毫秒
?1
#ifndef?CTIMER_H
?2
#define?CTIMER_H
?3
?4
#include?"Windows.h"
?5
?6
class???CTimer???
?7

{???
?8
public:???
?9
????CTimer()?
10
????
{
11
????????QueryPerformanceFrequency(&m_Frequency);//取CPU頻率
12
????}???
13
????void?Start()
14
????
{
15
????????QueryPerformanceCounter(&m_StartCount);//開(kāi)始計(jì)數(shù)
16
????}???
17
????double?End()?
18
????
{
19
????????LARGE_INTEGER???CurrentCount;
20
????????QueryPerformanceCounter(&CurrentCount);//終止計(jì)數(shù)
21
????????return?
22
????????????double(CurrentCount.QuadPart-m_StartCount.QuadPart)*1000/(double)m_Frequency.QuadPart;
23
????????
24
????}???
25
private:???
26
????LARGE_INTEGER???m_Frequency;???
27
????LARGE_INTEGER???m_StartCount;???
28
};
29
30
#endif//CTIMER_H??? CreateALGraph.h: 創(chuàng)建鄰接圖G
??1
#include?"ALGraph.h"
??2
??3
void?CreateALGraph(ALGraph&?G,long?vexnum,?long?arcnum)
??4

{
??5
????int?i,j,m,n;
??6
????bool?flag?=?false;//檢查邊是否已存在
??7
????int?*?weight?=?new?int[arcnum];
??8
????for(i?=?0;?i?<?G.arcnum;?i++)
??9
????
{
?10
????????weight[i]?=?0;??//初始權(quán)值為零????
?11
????}
?12
?13
????AdjList?vertices?=?new?VNode[vexnum]?;?//動(dòng)態(tài)分配頭結(jié)點(diǎn)數(shù)組
?14
????ArcNode*?p?=?NULL;?
?15
????ArcNode*?q?=?NULL;?
?16
????srand(NULL);
?17
????
?18
????G.vexnum?=?vexnum;
?19
????G.arcnum?=?arcnum;
?20
????for(i=0;?i<G.vexnum;?i++)
?21
????
{
?22
????????vertices[i].adjvex?=?i;?????//?頂點(diǎn)序號(hào)
?23
????????vertices[i].color?=?WHITE;??//?頂點(diǎn)顏色???
?24
????????vertices[i].d?=?0;???//?頂點(diǎn)最初DFS發(fā)現(xiàn)時(shí)間?;?兼作Bellman_Ford算法中當(dāng)前最短路徑?
?25
????????vertices[i].f?=?0;??????????//?頂點(diǎn)最終DFS結(jié)束時(shí)間?
?26
????????vertices[i].father?=?NULL;??//訪問(wèn)路徑上的父結(jié)點(diǎn)
?27
????????vertices[i].next?=?NULL;????//表結(jié)點(diǎn)指針,叫做firstarc似乎更合適,也更好控制,懶得改了
?28
????}
?29
????G.vertices?=?vertices;
?30
????
?31
????
?32
????for(i?=?0;?i?<?G.arcnum;?i++)//隨機(jī)產(chǎn)生arcnum條邊
?33
????
{
?34
????????weight[i]?=?rand()%1000?;//-?200;?//適當(dāng)加一些負(fù)權(quán)值邊
?35
????????if?(weight[i]?==?0)
?36
????????
{
?37
????????????weight[i]++;//不能讓權(quán)值為零,否則等于沒(méi)有添加邊
?38
????????}
?39
????}
?40
????
?41
????for(i?=?0;?i?<?G.arcnum;?i++)//打亂數(shù)組
?42
????
{?
?43
????????j?=?rand()%G.arcnum?;//隨機(jī)選取數(shù)組下標(biāo),注意整除的是數(shù)組大小
?44
????????if?(j>=0?&&?j<G.arcnum)?
?45
????????
{
?46
????????????int?exchange=weight[i];
?47
????????????weight[i]=weight[j];
?48
????????????weight[j]=exchange;????
?49
????????}
?50
????}
?51
????
?52
????
?53
????i?=?0;
?54
????j?=?0;
?55
????while?(2*i+1?<?G.vexnum)//先將V-1條邊分配,為保證圖是連通的,按完全二叉樹(shù)結(jié)構(gòu)產(chǎn)生邊
?56
????????//當(dāng)然這樣產(chǎn)生的邊不夠隨機(jī)性
?57
????
{???????????
?58
????????p?=?new?ArcNode;????
?59
????????p->adjvex?=?2*i+1;
?60
????????p->weight?=?weight[j++];
?61
????????p->next?=?NULL;???????????
?62
????????G.vertices[i].next?=?p;//k尚無(wú)鄰接點(diǎn),p作為第一個(gè)鄰接點(diǎn)
?63
????????
?64
????????if?(2*i+2?<?G.vexnum)
?65
????????
{
?66
????????????q?=?p;
?67
????????????p->next?=?new?ArcNode;//動(dòng)態(tài)分配表結(jié)點(diǎn)
?68
????????????p?=?p->next;
?69
????????????p->adjvex?=?2*i+2;
?70
????????????p->weight?=?weight[j++];
?71
????????????p->next?=?NULL;
?72
????????????G.vertices[i].next->next?=?p;
?73
????????}
?74
????????else
?75
????????????break;//V-1條邊分配完畢
?76
????????
?77
????????i++;
?78
????}
?79
????
?80
????
?81
????for(i?=?G.vexnum-1;?i?<?G.arcnum;?)//將剩下的邊分配出去
?82
????
{
?83
????????flag?=?false;
?84
????????
?85
????????m?=?rand()%G.vexnum;?//隨機(jī)弧尾序號(hào)
?86
????????n?=?rand()%G.vexnum;?//隨機(jī)弧頭序號(hào)
?87
????????while?(m?==?n)???????//不考慮指向自身的結(jié)點(diǎn)
?88
????????
{
?89
????????????n?=?rand()%G.vexnum;
?90
????????}
?91
????????
?92
????????if?(G.vertices[m].next?!=?NULL)????????????
?93
????????
{
?94
????????????p?=?G.vertices[m].next;
?95
????????}
?96
????????else??//k尚無(wú)鄰接點(diǎn)
?97
????????
{
?98
????????????p?=?NULL;
?99
????????????q?=?NULL;
100
????????}
101
????????
102
????????while?(p?!=?NULL)
103
????????
{
104
????????????if?(p->adjvex?==?n)
105
????????????
{
106
????????????????flag?=?true;//邊已經(jīng)存在
107
????????????????break;
108
????????????}
109
????????????else//繼續(xù)往下找
110
????????????
{
111
????????????????q?=?p;
112
????????????????p?=?p->next;
113
????????????}
114
????????}
115
????????
116
????????if?(!flag)//Vm→Vn的邊本不存在
117
????????
{
118
????????????p?=?new?ArcNode;
119
????????????
120
????????????p->adjvex?=?n;
121
????????????p->weight?=?weight[i];
122
????????????p->next?=?NULL;
123
????????????if?(q!=NULL)?
124
????????????
{
125
????????????????q->next?=?p;
126
????????????}
127
????????????else
128
????????????????G.vertices[m].next?=?p;
129
????????????
130
????????????i++;//僅當(dāng)成功分配一條邊才i++;?本循環(huán)存在死循環(huán)的可能,即永遠(yuǎn)碰巧都分配不出去
131
????????????//考慮復(fù)雜度和出錯(cuò)的概率,姑且不管它.
132
????????}
133
????}
134
135
????delete?[]?weight;
136
}
137
138
139
140
void?ShowGraph(ALGraph?G)???//打印創(chuàng)建后的圖
141

{
142
????for(int?i=0;?i<G.vexnum;?i++)
143
????
{
144
????????ArcNode?*?p?=?G.vertices[i].next;
145
????????cout<<"source?V"<<G.vertices[i].adjvex<<":";
146
????????while(p!=NULL)
147
????????
{
148
????????????cout<<"??V"<<p->adjvex;
149
????????????cout<<"(w:?"<<p->weight<<")";
150
????????????p=p->next;
151
????????}
152
????????cout<<endl;
153
154
????}
155
} ClearUp.h: 銷毀圖G,回收工作
?1
#include?"ALGraph.h"
?2
?3
void?ClearUp(ALGraph?&G)//銷毀圖G
?4

{
?5
????ArcNode*?p?=?NULL;????
?6
????ArcNode*?q?=?NULL;
?7
????int?i;
?8
????for(i=0;?i<G.vexnum;?i++)??//回收表結(jié)點(diǎn)
?9
????
{????
10
????????p?=?G.vertices[i].next;
11
????????while?(p?!=?NULL)?
12
????????
{
13
????????????q?=?p->next;
14
????????????delete?p;
15
????????????p?=?q;????????????
16
????????}
17
????}
18
19
????delete?[]?G.vertices;?????//回收頭結(jié)點(diǎn)
20
????G.vertices?=?NULL;
21
????G.arcnum?=?0;
22
????G.vexnum?=?0;
23
} DFS.h: 深度優(yōu)先遍歷
?1
#include?"ALGraph.h"
?2
#include?"Stack.h"
?3
?4
void?DFSVisit(ALGraph&?G,?VNode&?s,?int&?time);
?5
?6
void?DFS(ALGraph&?G)
?7

{
?8
????int?time?=?0;????
?9
????for(int?i=0;?i<G.vexnum;?i++)??//初始化
10
????
{
11
????????G.vertices[i].color?=?WHITE;
12
????????G.vertices[i].father?=?NULL;
13
????}
14
????
15
????for(i=0;?i<G.vexnum;?i++)?????//深度優(yōu)先遍歷
16
????
{
17
????????if?(G.vertices[i].color?==?WHITE)?
18
????????????DFSVisit(G,?G.vertices[i],?time);
19
????}
20
}
21
22
void?DFSVisit(ALGraph&?G,?VNode&?s,?int&?time)??/**//*從s出發(fā)深度優(yōu)先搜索圖G*/
23

{
24
????Stack?S;
25
????ArcNode?*?p;?
26
????VNode*?k;//出棧頂點(diǎn)序號(hào)
27
????VNode*?t;
28
????
29
????InitStack(S);??/**//*初始化空棧*/
30
????
31
????s.color?=?GRAY;
32
????time?=?time?+1;
33
????s.d?=?time;
34
????Push(S,?&s);?
35
????while(!Empty(S))
36
????
{?
37
????????t?=?GetTop(S);??//彈出棧頂,返回棧頂元素地址
38
39
????????for(p=t->next;?p?&&?G.vertices[p->adjvex].color!=WHITE;?p=p->next);
40
????????//找到第一個(gè)白色鄰接點(diǎn)
41
????????if(p?==?NULL)//t的所有鄰接點(diǎn)都已訪問(wèn)
42
????????
{
43
????????????k?=?Pop(S);
44
????????????k->color?=?BLACK;
45
????????????time?=?time+1;
46
????????????k->f?=?time;//結(jié)束時(shí)間
47
????????}
48
????????else//繼續(xù)深度訪問(wèn)
49
????????
{
50
????????????Push(S,&G.vertices[p->adjvex]);
51
????????????G.vertices[p->adjvex].father?=?t;
52
????????????G.vertices[p->adjvex].color?=?GRAY;
53
????????????time?=?time+1;
54
????????????G.vertices[p->adjvex].d?=?time;//入棧之時(shí)即發(fā)現(xiàn)之時(shí)d
55
????????}
56
????}
57
} Bellman_Ford算法
?1
#include?"ALGraph.h"
?2
?3
void?Initialize_Single_Source(ALGraph&?G,VNode&?s)//初始化
?4

{
?5
????for(int?i=0;?i<G.vexnum;?i++)
?6
????
{
?7
????????G.vertices[i].father?=?NULL;
?8
????????G.vertices[i].d?=?wuqiong;????
?9
????}
10
????s.d?=?0;
11
}
12
13
void?Relax(VNode&?v,?VNode&?w,?ArcNode?*?p)//Relax操作,更新最短路徑
14

{
15
????if?(w.d?>?v.d+?p->weight)
16
????
{
17
????????w.d?=?v.d+?p->weight;
18
????????w.father?=?&v;
19
????}
20
}
21
22
bool?Bellman_Ford(ALGraph&?G,?VNode&?s)
23

{
24
????ArcNode?*?p;
25
????int?i;
26
????
27
????Initialize_Single_Source(G,?s);
28
29
????for?(int?j=0;?j<G.vexnum-1;?j++)//V-1趟Relax
30
????
{
31
????????for(i=0;?i<G.vexnum;?i++)//沿著頭結(jié)點(diǎn)
32
????????
{
33
????????????for?(p=G.vertices[i].next;?p!=NULL;?p=p->next)//沿著表結(jié)點(diǎn)
34
????????????
{????????????
35
????????????????Relax(G.vertices[i],?G.vertices[p->adjvex],?p);
36
????????????}
37
????????}
38
????}
39
40
????//判斷是否有負(fù)回路
41
????for(i=0;?i<G.vexnum;?i++)//沿著頭結(jié)點(diǎn)
42
????
{
43
????????for?(p=G.vertices[i].next;?p!=NULL;?p=p->next)//沿著表結(jié)點(diǎn)
44
????????
{
45
????????????if?(G.vertices[p->adjvex].d?>?G.vertices[i].d+?p->weight)?
46
????????????
{
47
????????????????cout<<"圖中有負(fù)權(quán)值回路."<<endl;
48
????????????????return?false;
49
????????????}
50
????????}
51
????}
52
53
????return?true;????????????????
54
}
55
56
void?PrintPath(ALGraph?G,?VNode?s,?VNode?v)//遞歸打印最短路徑
57

{????
58
????if?(v.father?!=?NULL)
59
????
{
60
????????PrintPath(G,?s,?*v.father);
61
????????cout<<"v"<<v.adjvex<<"→";
62
????}
63
????else
64
????????cout<<"v"<<s.adjvex<<"→";????
65
}
66
67
void?ShortestPath(ALGraph?G,?VNode?s)
68

{
69
????int?i=0;
70
????cout<<"頂點(diǎn)為v0,v1,v2,……,v"<<G.vexnum-1<<endl;
71
????cout<<"從源點(diǎn)v"<<s.adjvex<<"到其它所有頂點(diǎn)的最短距離:"<<endl;
72
????for(i=0;?i<G.vexnum;?i++)//沿著頭結(jié)點(diǎn)
73
????
{
74
????????cout<<"到頂點(diǎn)v"<<i<<":??";
75
????????PrintPath(G,?s,?G.vertices[i]);
76
????????cout<<endl;
77
????}
78
}
79
80
void?DFSPath(ALGraph?G,?VNode?s)//打印DFS各頂點(diǎn)的發(fā)現(xiàn)時(shí)間和結(jié)束時(shí)間d/f;
81

{
82
????int?i=0;
83
????for(i=0;?i<G.vexnum;?i++)//沿著頭結(jié)點(diǎn)
84
????
{
85
????????//PrintPath(G,?s,?*k);
86
????????cout<<"v"<<G.vertices[i].adjvex<<":"<<G.vertices[i].d<<"?/?"
87
????????????<<G.vertices[i].f<<"??顏色:"<<G.vertices[i].color;
88
????????cout<<endl;
89
????}
90
} main函數(shù):對(duì)不同輸入規(guī)模計(jì)時(shí)分析算法性能
?1
#include?"ALGraph.h"
?2
#include?"DFS.h"
?3
#include?"CreateALGraph.h"
?4
#include?"Bellman_Ford.h"
?5
#include?"ClearUp.h"
?6
#include?"CTimer.h"
?7
?8
#include<iostream>
?9
#include<cstdio>
10
#include<cmath>
11
#include<cstring>
12
13
14
int?main()
15
16

{
17
????//輸入規(guī)模
18
????const?int?NUM1[6]?=?
{1000,2500,5000,7500,10000,15000};
19
????const?int?RATE1[4]?=?
{pow(2,2),pow(2,4),pow(2,6),pow(2,8)};
20
????const?int?NUM2[6]?=?
{200,400,800,1200,1600,2000};
21
????const?int?RATE2[5]?=?
{pow(2,2),pow(2,3),pow(2,4),pow(2,5),pow(2,6)};
22
????
23
????ALGraph?G;??????????//圖G
24
????CTimer?timer;???????//計(jì)數(shù)器
25
????int?i,j;?????????
26
????double?runningtime;?//運(yùn)行時(shí)間(毫秒/ms)
27
????long?vexnum;????????//圖頂點(diǎn)數(shù)
28
????long?arcnum;????????//圖邊數(shù)
29
????
30
????for(i=0;?i<6;?i++)//DFS運(yùn)行時(shí)間分析
31
????
{????
32
????????cout<<"/********************************/"<<endl;
33
????????for(j=0;j<4;?j++)
34
????????
{
35
????????????vexnum?=?NUM1[i];
36
????????????arcnum?=?NUM1[i]*RATE1[j];
37
????????????CreateALGraph(G,?vexnum,?arcnum);//創(chuàng)建圖
38
????????????timer.Start();?????????????//計(jì)時(shí)開(kāi)始
39
????????????DFS(G);????????????
40
????????????runningtime?=?timer.End();//計(jì)時(shí)結(jié)束
41
????????????cout<<"????"<<runningtime<<"ms"<<endl;???????????????
42
//????????????DFSPath(G,?*G.vertices);
43
????????????ClearUp(G);
44
????????}????
45
????}
46
????
47
????for(i=0;?i<6;?i++)//Bellman_Ford最短路徑算法運(yùn)行時(shí)間分析
48
????
{????
49
????????cout<<"/********************************/"<<endl;????????
50
????????for(j=0;j<5;?j++)????????
{
51
????????????vexnum?=?NUM2[i];
52
????????????arcnum?=?NUM2[i]*RATE2[j];
53
????????????CreateALGraph(G,?vexnum,?arcnum);
54
//????????????ShowGraph(G);??????????????//打印原始圖
55
????????????timer.Start();?????????????//計(jì)時(shí)開(kāi)始
56
????????????Bellman_Ford(G,?*G.vertices);
57
????????????runningtime?=?timer.End();//計(jì)時(shí)結(jié)束
58
????????????cout<<"????"<<runningtime<<"ms"<<endl;
59
//????????????ShortestPath(G,?*G.vertices);//打印源點(diǎn)v0到各頂點(diǎn)的最短路徑
60
????????????ClearUp(G);
61
????????}
62
????}
63
????
64
????
65
????return?0;
66
}
posted on 2006-12-02 10:34
哈哈 閱讀(1579)
評(píng)論(2) 編輯 收藏 引用