邻接表实现Dijkstra算法以及DFS与BFS算法
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了邻接表实现Dijkstra算法以及DFS与BFS算法相关的知识,希望对你有一定的参考价值。
//============================================================================ // Name : ListDijkstra.cpp // Author : fffff // Version : // Copyright : Your copyright notice // Description : Hello World in C++, Ansi-style //============================================================================ #include<iostream> #include<cstdlib> #include<queue> using namespace std; #define MAXSIZE 100 #define INF (~(0x1<<31)) //最大值 0x7FFFFFFF class ListUDG{ /* * 内部类 */ private: /* * 邻接表中的边节点 * ivex:下一个节点的编号 * nextEdge:指向下一个边节点的指针 */ class Enode{ public: int ivex; int weight; Enode *nextEdge; }; /* * 邻接表中的顶点节点 * data:顶点节点的数据 * firstEdge:顶点节点的第一条边 */ class Vnode{ public: char data; Enode *firstEdge; }; private: int mVexNum;//顶点个数 int mEdgNum;//边的条数 Vnode mVexs[MAXSIZE]; bool visited[MAXSIZE]; public: ListUDG(); ListUDG(char vexs[],int vlen,char edge[][2],int elen,int weigh[]); ~ListUDG(); char rChar(); int getPost(char ch); int getmVexNum(); int getmEdgNum(); Vnode getVexs(int i){ return mVexs[i]; }; int getWeight(int v,int u); void print(); void BFS(); void DFS(); void DFSK(int k); void Dijkstra(ListUDG *listudg,int v,int pre[],int dist[]); void trace(ListUDG *listudg,int v,int u,int pre[]); private: char readChar(); int getPosition(char ch); void LinkLast(Enode *list,Enode *node); }; ListUDG::ListUDG(char vexs[],int vlen,char edge[][2],int elen,int weigh[]){ /* * 初始化顶点数与边的条数 */ mVexNum = vlen; mEdgNum = elen; /* * 初始化邻接表中的顶点节点 */ for(int i=0;i<mVexNum;i++){ mVexs[i].data = vexs[i]; mVexs[i].firstEdge = NULL; } /* * 初始化邻接表中的边节点 */ for(int i=0;i<mEdgNum;i++){ char first = edge[i][0]; char second = edge[i][1]; int start = getPosition(first); int end = getPosition(second); Enode *enode1 = new Enode; enode1->ivex = end; enode1->weight = weigh[i]; enode1->nextEdge = NULL; if(mVexs[start].firstEdge==NULL) mVexs[start].firstEdge = enode1; else LinkLast(mVexs[start].firstEdge,enode1); Enode *enode2 = new Enode; enode2->ivex = start; enode2->weight = weigh[i]; enode2->nextEdge = NULL; if(mVexs[end].firstEdge==NULL) mVexs[end].firstEdge=enode2; else LinkLast(mVexs[end].firstEdge,enode2); } }; ListUDG::ListUDG(){ /* * 初始化顶点数与边的条数 */ cout<<"input num of Vexs and Edges : "; cin>>mVexNum>>mEdgNum; /* * 初始化邻接表中的顶点节点 */ for(int i=0;i<mVexNum;i++){ cout<<"input data of "<<i<<" Vex:"; mVexs[i].data = readChar(); mVexs[i].firstEdge = NULL; } /* * 初始化邻接表中的边节点 */ for(int i=0;i<mEdgNum;i++){ cout<<"input edge("<<i<<"):"; char first = readChar(); char second = readChar(); int start = getPosition(first); int end = getPosition(second); cout<<"input weight of the edge:"; int weight; cin>>weight; Enode *enode1 = new Enode; enode1->ivex = end; enode1->weight = weight; /********************-----ERROR-----******************** * 两个构造方法都忘掉此句,导致出错, * 出错地方在调用方法LinkLast的时候无法判断nextEdge是否为空 * 因为nextEdge没有被赋值 *******************************************************/ enode1->nextEdge = NULL; if(mVexs[start].firstEdge==NULL) mVexs[start].firstEdge = enode1; else LinkLast(mVexs[start].firstEdge,enode1); Enode *enode2 = new Enode; enode2->ivex = start; enode2->weight = weight; enode2->nextEdge = NULL; if(mVexs[end].firstEdge==NULL) mVexs[end].firstEdge = enode2; else LinkLast(mVexs[end].firstEdge,enode2); } }; ListUDG::~ListUDG(){ }; char ListUDG::rChar(){ return readChar(); }; int ListUDG::getPost(char ch){ return getPosition(ch); }; int ListUDG::getmVexNum(){ return mVexNum; }; int ListUDG::getmEdgNum(){ return mEdgNum; }; int ListUDG::getWeight(int v,int u){ Enode *enode; if(v==u) return 0; else{ enode = mVexs[v].firstEdge; while(enode){ if(enode->ivex==u) return enode->weight; else enode = enode->nextEdge; } return INF; } }; void ListUDG::print(){ cout<<"ListUDG"<<endl; for(int i=0;i<mVexNum;i++){ cout<<i<<" ("<<mVexs[i].data<<"): "; Enode *p = mVexs[i].firstEdge; while(p){ cout<<p->ivex<<"("<<mVexs[p->ivex].data<<")["<<p->weight<<"] "; p = p->nextEdge; } cout<<endl; } return ; }; char ListUDG::readChar(){ char cha; cin>>cha; while(!((cha>=‘a‘&&cha<=‘z‘)||(cha>=‘A‘&&cha<=‘Z‘))){ cin>>cha; } return cha; }; int ListUDG::getPosition(char ch){ for(int i = 0;i<mVexNum;i++){ if(mVexs[i].data==ch) return i; } return -1; } void ListUDG::LinkLast(Enode*list,Enode *node){ Enode *p = list; while(p->nextEdge) p = p->nextEdge; p->nextEdge = node; return; }; /* * Dijkstra 算法----最短路径 */ void ListUDG::Dijkstra(ListUDG *listudg,int v,int pre[],int dist[]){ bool s[MAXSIZE]; /* * 第一步:初始化S集合以及距离dist */ for(int i=0;i<listudg->getmVexNum();i++){ s[i] = false; dist[i] = listudg->getWeight(v,i); if(dist[i]==INF) pre[i] = -1; else pre[i] = v; } s[v] = true; dist[v] = 0; /* * 第二步:寻找dist中的最小值加入到S集合中 */ for(int i=1;i<listudg->getmVexNum();i++){ int min = INF; int u = v; for(int j=0;j<listudg->getmVexNum();j++){ if(s[j]==false&&dist[j]<min){ min = dist[j]; u = j; } } s[u] = true;//将顶点u加入到集合S中 /* * 第三步:更新dist */ for(int j=0;j<listudg->mVexNum;j++){ if(s[j]==false&&listudg->getWeight(u,j)<INF){ int newdist = dist[u] + listudg->getWeight(u,j); if(newdist<dist[j]){ dist[j] = newdist; pre[j] = u; } } } } }; void ListUDG::trace(ListUDG *listudg,int v,int u,int pre[]){ int start = v; int end = u; while(start!=end){ cout<<listudg->mVexs[end].data<<"<---"; end = pre[end]; } cout<<listudg->mVexs[start].data<<endl; }; /* * 广度优先搜索邻接表 */ void ListUDG::BFS(){ for(int i=0;i<MAXSIZE;i++) visited[i] = false; queue<int>que; que.push(0); visited[0] = true; int out; Enode *outNext; while(!que.empty()){ out = que.front(); outNext = mVexs[out].firstEdge; que.pop(); cout<<mVexs[out].data<<" "; /****************-----ERROR-----***************** * 此处刚开始将判断条件visited[outNext->ivex]==false * 写入while循环的判断语句中,导致某一个顶点的边链表没有 * 访问完就结束了循环(可能某边之前已经访问过),丢掉了后面 * 的节点 ************************************************/ while(outNext!=NULL){ if(visited[outNext->ivex]==false){ que.push(outNext->ivex); visited[outNext->ivex] = true; outNext = outNext->nextEdge; }else outNext = outNext->nextEdge; } } cout<<endl; }; void ListUDG::DFS(){ for(int i=0;i<MAXSIZE;i++) visited[i] = false; for(int i=0;i<mVexNum;i++) if(visited[i]==false) DFSK(i); cout<<endl; }; void ListUDG::DFSK(int k){ visited[k]=true; cout<<mVexs[k].data<<" "; Enode *enode = mVexs[k].firstEdge; while(enode){ if(visited[enode->ivex]==false){ DFSK(enode->ivex); enode = enode->nextEdge; } else /************-----ERROR-----************* *开始时候忘掉了写此句,导致顶点的边链表没有访问完 *而到时enode没有向后移动,从而导致循环无法结束,因此 *程序死循环 ****************************************/ enode = enode->nextEdge; } return ; } int main(){ char vexs[]={‘a‘,‘b‘,‘c‘,‘d‘,‘e‘,‘f‘,‘g‘}; char edges[][2]={ {‘a‘,‘b‘}, {‘a‘,‘d‘}, {‘a‘,‘g‘}, {‘b‘,‘f‘}, {‘c‘,‘d‘}, {‘c‘,‘g‘}, {‘d‘,‘f‘}, {‘e‘,‘g‘}, {‘f‘,‘g‘} }; int pre[MAXSIZE]; int dist[MAXSIZE]; int weight[]={1,3,2,2,6,4,3,7,1}; int vlen = sizeof(vexs)/sizeof(vexs[0]); int elen = sizeof(edges)/sizeof(edges[0]); ListUDG *listudg1 = new ListUDG(vexs,vlen,edges,elen,weight); listudg1->print(); listudg1->BFS(); listudg1->DFS(); listudg1->Dijkstra(listudg1,0,pre,dist); listudg1->trace(listudg1,0,2,pre); return 0; } 运行结果如下 ListUDG 0 (a): 1(b)[1] 3(d)[3] 6(g)[2] 1 (b): 0(a)[1] 5(f)[2] 2 (c): 3(d)[6] 6(g)[4] 3 (d): 0(a)[3] 2(c)[6] 5(f)[3] 4 (e): 6(g)[7] 5 (f): 1(b)[2] 3(d)[3] 6(g)[1] 6 (g): 0(a)[2] 2(c)[4] 4(e)[7] 5(f)[1] a b d g f c e a b f d c g e c<---g<---a
以上是关于邻接表实现Dijkstra算法以及DFS与BFS算法的主要内容,如果未能解决你的问题,请参考以下文章
数据结构C语言版 图的遍历 DFS和BFS算法,用邻接矩阵储存 急阿在线等 求大神指点
[数据结构]邻接矩阵和邻接表存储的图DFS,BFS算法时间复杂度分析