邻接表存储有向图的两种遍历方式

用邻接表存储的有向图,因为在建立邻接表的时候,建的链表都是头插入的,所以遍历出来的顺序和原先设想的是相反的,就是从下往上的。为了减少一些无谓的操作,所以在程序中加入了一个全局变量 Vex_Num 来记录输出顶点的数目,一旦全部顶点都已经输出,就跳出函数,不再继续进行下去,节省一点时间。

下面是代码

#include<iostream> #include<string> #include<time.h> using namespace std; //下面是循环队列模版 template<class T> class My_queue; template<class T> class Node { private: T data; Node<T> *next; public: Node() { next=0; } Node(T d) { data=d; next=0; } friend My_queue<T>; }; template<class T> class My_queue { private: Node<T> *tail; public: My_queue() { tail=new Node<T>(); tail->next=tail; } ~My_queue() { clean(); delete tail; } bool empty() { return (tail->next==tail); } void push(T d) { Node<T> *p=new Node<T>(d); p->next=tail->next; tail->next=p; tail=p; } T front() { if(empty()) { cout<<"queue is empty!"<<endl; exit(0); } Node<T> *p=tail->next; T data=p->next->data; return data; } T back() { if(empty()) { cout<<"queue is empty!"<<endl; exit(0); } T data=tail->data; return data; } void pop() { Node<T> *p=tail->next; Node<T> *q=p->next; p->next=q->next; if(q==tail) tail=p; delete q; } void clean() { Node<T> *p=tail->next; Node<T> *q=p->next; while(q!=p) { p->next=q->next; delete q; p->next=q; } } }; #define MAX_VERTEX_NUM 20 bool visited[20];//用于遍历时辅组使用 int Vex_Num;//统计输出顶点数目 //表结点 struct ArcNode { int adjvex; //弧所指向顶点的位置 ArcNode *nextarc;// 指向下一条弧 }; //头结点 typedef struct VNode { string data;//顶点名 ArcNode *firstarc;//指向第一条关联顶点的弧 }AdjList[MAX_VERTEX_NUM]; struct ALGraph { AdjList vertices;//头结点数组 int vexnum;//顶点数 int arcnum;//边数 }; int Locate_Vex(ALGraph G,string x) //定位顶点位置 { for(int v=0;G.vertices[v].data!=x;v++); return v; } void CreateDG_ALG(ALGraph &G) { //采用邻接表存储表示,构造有向图G string v1,v2; int i,j,k; cout<<"输入顶点数和边数:"; cin>>G.vexnum>>G.arcnum; //构造头结点数组 cout<<"输入顶点民称:"; for(i=0;i<G.vexnum;i++) { cin>>G.vertices[i].data; G.vertices[i].firstarc=NULL; } //输入各弧并构造邻接表 for(k=0;k<G.arcnum;k++) { cout<<"按尾->头的顺序输入边所对应的两个顶点:"; cin>>v1>>v2; i=Locate_Vex(G,v1); j=Locate_Vex(G,v2); while(i<0|| i>G.vexnum-1 || j<0 || j>G.vexnum-1) { cout<<"结点位置输入错误,重新输入: "; cin>>v1>>v2; i=Locate_Vex(G,v1); j=Locate_Vex(G,v2); } ArcNode *p=new ArcNode; p->adjvex=j; p->nextarc=G.vertices[i].firstarc; G.vertices[i].firstarc=p; } } //深度优先遍历 void DFS(ALGraph G,int v) { visited[v]=true; cout<<G.vertices[v].data<<" "; Vex_Num+=1; if(Vex_Num==G.vexnum) return; ArcNode *p; int w; for(p=G.vertices[v].firstarc;p;p=p->nextarc) { w=p->adjvex; if(!visited[w]) DFS(G,w); } } void DFS_Traverse(ALGraph G) { Vex_Num=0; int i,k; for(i=0;i<G.vexnum;i++) visited[i]=false; for(k=0;k<G.vexnum;k++) if(!visited[k]) DFS(G,k); } //广度优先遍历 void BFS_Traverse(ALGraph G) { Vex_Num=0; int i,k,w; My_queue<int> q; ArcNode *p; for(i=0;i<G.vexnum;i++) visited[i]=false; for(i=0;i<G.vexnum;i++) { if(!visited[i]) { visited[i]=true; cout<<G.vertices[i].data<<" "; Vex_Num+=1; if(G.vertices[i].firstarc) q.push(i); while(!q.empty()) { k=q.front(); q.pop(); for(p=G.vertices[k].firstarc;p;p=p->nextarc) { w=p->adjvex; if(!visited[w]) { visited[w]=true; cout<<G.vertices[w].data<<" "; Vex_Num+=1; if(Vex_Num==G.vexnum) break; if(G.vertices[w].firstarc) q.push(w); } } } } } } int main() { clock_t begin=clock(),end(0); ALGraph G; CreateDG_ALG(G); cout<<"深度优先遍历图为:"; DFS_Traverse(G); cout<<endl; cout<<"广度优先遍历图为:"; BFS_Traverse(G); cout<<endl; end=clock(); cout<<"这段代码运行时间为:"<<double(end-begin)<<"ms"<<endl; return 0; }

测试结果如下:

输入顶点数和边数:8 13 输入顶点民称:v1 v2 v3 v4 v5 v6 v7 v8 按尾->头的顺序输入边所对应的两个顶点:v1 v2 按尾->头的顺序输入边所对应的两个顶点:v1 v4 按尾->头的顺序输入边所对应的两个顶点:v1 v6 按尾->头的顺序输入边所对应的两个顶点:v2 v3 按尾->头的顺序输入边所对应的两个顶点:v2 v5 按尾->头的顺序输入边所对应的两个顶点:v2 v4 按尾->头的顺序输入边所对应的两个顶点:v4 v5 按尾->头的顺序输入边所对应的两个顶点:v6 v5 按尾->头的顺序输入边所对应的两个顶点:v6 v7 按尾->头的顺序输入边所对应的两个顶点:v3 v8 按尾->头的顺序输入边所对应的两个顶点:v5 v3 按尾->头的顺序输入边所对应的两个顶点:v5 v7 按尾->头的顺序输入边所对应的两个顶点:v7 v8 深度优先遍历图为:v1 v6 v7 v8 v5 v3 v4 v2 广度优先遍历图为:v1 v6 v4 v2 v7 v5 v3 v8 这段代码运行时间为:40988ms Press any key to continue

按照上面的输入所生成的有向图如下所示:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值