以十字链表作为有向图的存储结构,将邻接表和逆邻接表结合起来,对统计结点的出入度很方便,
这是之前的一篇日志,也是说图的存储的,有兴趣的也可以看看图的几种存储结构
下面是代码:
//graph.h #include <iostream> #include <string> #include <queue> #include <stack> using namespace std; bool visited[100]; //顶点是否已被访问的标志数组 //十字链表存储图 //弧结点 struct ArcBox { //弧结点头尾结点位置 int tailvex; int headvex; //弧头和弧尾相同的弧的链域 ArcBox *hlink; ArcBox *tlink; }; //顶点节点 struct VexNode { string data; //顶点名称 ArcBox *firstin; //指向第一条入弧 ArcBox *firstout; //指向第一条出弧 }; class OLGraph { private: VexNode *xlist; //指向顶点数组的指针 int vexnum; //顶点数 int arcnum; //弧数 int maxnum; //顶点数的最大值 public: OLGraph(int num=20) { xlist=new VexNode[num]; maxnum=num; } int Locate_Vex(string v) { for(int i=0;i<vexnum;i++) { if(xlist[i].data==v) return i; } return -1; } void CreateDG_OLG() { //构造有向图 string v1,v2; int i,j,k; cout<<"输入顶点数和边的数目:"; cin>>vexnum>>arcnum; while(vexnum>maxnum) { cout<<"顶点数目大于最大限制,请重新输入:"; cin>>vexnum; } cout<<"输入各个顶点的名称:"; for(i=0;i<vexnum;i++) { cin>>xlist[i].data; xlist[i].firstin=NULL; xlist[i].firstout=NULL; } for(k=0;k<arcnum;k++) { cout<<"输入第"<<k+1<<"条边的两个顶点(尾—>头的顺序):"; cin>>v1>>v2; i=Locate_Vex(v1); j=Locate_Vex(v2); while(i == -1 || j == -1) { cout<<"结点位置输入错误,重新输入: "; cin>>v1>>v2; i=Locate_Vex(v1); j=Locate_Vex(v2); } ArcBox *p=new ArcBox; p->tailvex=i; p->headvex=j; p->hlink=xlist[j].firstin; p->tlink=xlist[i].firstout; xlist[i].firstout=xlist[j].firstin=p; } cout<<"有向图构造完成"<<endl; } //统计顶点入度 int In_degree(string v) { int pos=Locate_Vex(v); if(pos == -1) { cout<<"结点不在图中"<<endl; return -1; } ArcBox *p=xlist[pos].firstin; int ins=0; while(p) { ins++; p=p->hlink; } return ins; } //统计顶点出度 int Out_degree(string v) { int pos=Locate_Vex(v); if(pos == -1) { cout<<"结点不在图中"<<endl; return -1; } ArcBox *p=xlist[pos].firstout; int out=0; while(p) { out++; p=p->tlink; } return out; } //深度优先遍历 void DFS(int v) { visited[v]=true; cout<<xlist[v].data<<" "; ArcBox *p=xlist[v].firstout; while(p) { if(!visited[p->headvex]) DFS(p->headvex); p=p->tlink; } } void DFS_Traverse() { for(int i=0;i<vexnum;i++) visited[i]=false; for(i=0;i<vexnum;i++) if(!visited[i]) DFS(i); } //广度优先遍历 void BFS(int v) { visited[v]=true; cout<<xlist[v].data<<" "; queue<int> qu; int vex; ArcBox *p; qu.push(v); while(!qu.empty()) { vex=qu.front(); qu.pop(); p=xlist[vex].firstout; while(p) { if(!visited[p->headvex]) { visited[p->headvex]=true; cout<<xlist[p->headvex].data<<" "; qu.push(p->headvex); } p=p->tlink; } } } void BFS_Traverse() { for(int i=0;i<vexnum;i++) visited[i]=false; for(i=0;i<vexnum;i++) if(!visited[i]) BFS(i); } void DFS_2(int v) { visited[v]=true; cout<<xlist[v].data<<" "; stack<int> s; ArcBox *p; int pos; s.push(v); while(!s.empty()) { pos=s.top(); p=xlist[pos].firstout; while(p && visited[p->headvex]) p=p->tlink; if(!p) s.pop(); else { visited[p->headvex]=true; cout<<xlist[p->headvex].data<<" "; s.push(p->headvex); } } } void DFS_Traverse_2() { for(int i=0;i<vexnum;i++) visited[i]=false; for(i=0;i<vexnum;i++) if(!visited[i]) DFS_2(i); } //求连通分支数 int Connect_Cpnt() { for(int i=0;i<vexnum;i++) visited[i]=false; cout<<"下面的每一行显示一个连通分支:"<<endl; int num=1; DFS(0); cout<<endl; for(i=0;i<vexnum;i++) { if(!visited[i]) { num++; DFS(i); cout<<endl; } } return num; } };#include "graph.h" #include <iostream> #include <string> using namespace std; int main() { OLGraph G; string v; int ins,out,a; G.CreateDG_OLG(); cout<<"输入要统计哪个结点的入度:"; cin>>v; ins=G.In_degree(v); if(ins != -1) cout<<"顶点"<<v<<"的入度为:"<<ins<<endl; cout<<"输入要统计哪个结点的出度:"; cin>>v; out=G.Out_degree(v); if(out != -1) cout<<"顶点"<<v<<"的出度为:"<<out<<endl; cout<<"深度优先遍历:"; G.DFS_Traverse(); cout<<endl; cout<<"广度优先遍历:"; G.BFS_Traverse(); cout<<endl; cout<<"计算图的连通分支"<<endl; int num=G.Connect_Cpnt(); cout<<"图的连通分支数目为:"<<num<<endl; cout<<"深度优先遍历非递归:"; G.DFS_Traverse_2(); cout<<endl; return 0; }
测试结果: 输入顶点数和边的数目:12 12 输入各个顶点的名称:v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 输入第1条边的两个顶点(尾—>头的顺序):v1 v3 输入第2条边的两个顶点(尾—>头的顺序):v1 v5 输入第3条边的两个顶点(尾—>头的顺序):v2 v1 输入第4条边的两个顶点(尾—>头的顺序):v2 v5 输入第5条边的两个顶点(尾—>头的顺序):v5 v4 输入第6条边的两个顶点(尾—>头的顺序):v4 v2 输入第7条边的两个顶点(尾—>头的顺序):v3 v6 输入第8条边的两个顶点(尾—>头的顺序):v3 v4 输入第9条边的两个顶点(尾—>头的顺序):v7 v8 输入第10条边的两个顶点(尾—>头的顺序):v7 v9 输入第11条边的两个顶点(尾—>头的顺序):v8 v10 输入第12条边的两个顶点(尾—>头的顺序):v11 v12 有向图构造完成 输入要统计哪个结点的入度:v4 顶点v4的入度为:2 输入要统计哪个结点的出度:v12 顶点v12的出度为:0 深度优先遍历:v1 v5 v4 v2 v3 v6 v7 v9 v8 v10 v11 v12 广度优先遍历:v1 v5 v3 v4 v6 v2 v7 v9 v8 v10 v11 v12 计算图的连通分支 下面的每一行显示一个连通分支: v1 v5 v4 v2 v3 v6 v7 v9 v8 v10 v11 v12 图的连通分支数目为:3 深度优先遍历非递归:v1 v5 v4 v2 v3 v6 v7 v9 v8 v10 v11 v12 Press any key to continue
所生成的有向图的示意图,晚点再放 今晚得上实验课了,差点忘了。。。闪
下面是图的示意图: