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

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

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

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

 

    原文作者:数据结构之图
    原文地址: https://blog.csdn.net/jkay_wong/article/details/6664151
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞