用邻接表存储的有向图,因为在建立邻接表的时候,建的链表都是头插入的,所以遍历出来的顺序和原先设想的是相反的,就是从下往上的。为了减少一些无谓的操作,所以在程序中加入了一个全局变量 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
按照上面的输入所生成的有向图如下所示: