图邻接链表基本操作--广度优先、深度优先、拓扑排序

和树的遍历相似,若从图中某顶点出发访遍图中每个顶点,且每个顶点仅访问一次,此过程称为图的遍历(Traversing Graph)图的遍历算法是求解图的连通性问题、拓扑排序和求关键路径等算法的基础。图的遍历顺序有两种:深度优先搜索(DFS)和广度优先搜索(BFS)。对每种搜索顺序,访问各顶点的顺序也不是唯一的。

1、邻接表及逆邻接表的存储方法

1)定义

邻接表是图的一种链式存储结构。类似于树的孩子链表表示法。在邻接表中为图中每个顶点建立一个单链表,用单链表中的一个结点表示依附于该顶点的一条边(或表示以该顶点为弧尾的一条弧),称为边(或弧)结点。特征如下:

1) 为每个顶点建立一个单链表,

2) i个单链表中包含顶点Vi的所有邻接顶点。

把同一个顶点发出的边链接在同一个边链表中,链表的每一个结点代表一条边,叫做表结点(边结点),邻接点域adjvex保存与该边相关联的另一顶点的顶点下标  链域nextarc存放指向同一链表中下一个表结点的指针,数据域info存放边的权。边链表的表头指针存放在头结点中。头结点以顺序结构存储,其数据域data存放顶点信息,链域firstarc指向链表中第一个顶点。

1、广度优先遍历的递归定义

     设图G的初态是所有顶点均未访问过。在G中任选一顶点v为源点,则广度优先遍历可以定义为:首先访问出发点v,接着依次访问v的所有邻接点w1,w2,…,wt,然后再依次访问与wl,w2,…,wt邻接的所有未曾访问过的顶点。依此类推,直至图中所有和源点v有路径相通的顶点都已访问到为止。此时从v开始的搜索过程结束。
     若G是连通图,则遍历完成;否则,在图C中另选一个尚未访问的顶点作为新源点继续上述的搜索过程,直至G中所有顶点均已被访问为止。
     广度优先遍历类似于树的按层次遍历。采用的搜索方法的特点是尽可能先对横向进行搜索,故称其为广度优先搜索(Breadth-FirstSearch)。相应的遍历也就自然地称为广度优先遍历。

2、广度优先搜索过程
     在广度优先搜索过程中,设x和y是两个相继要被访问的未访问过的顶点。它们的邻接点分别记为x1,x2,…,xs和y1,y2,…,yt
     为确保先访问的顶点其邻接点亦先被访问,在搜索过程中使用FIFO队列来保存已访问过的顶点。当访问x和y时,这两个顶点相继入队。此后,当x和y相继出队时,我们分别从x和y出发搜索其邻接点x1,x2,…,xs和y1,y2,…,yt,对其中未访者进行访问并将其人队。这种方法是将每个已访问的顶点人队,故保证了每个顶点至多只有一次人队。

1.深度优先遍历的递归定义

  假设给定图G的初态是所有顶点均未曾访问过。在G中任选一顶点v为初始出发点(源点),则深度优先遍历可定义如下:首先访问出发点v,并将其标记为已访问过;然后依次从v出发搜索v的每个邻接点w。若w未曾访问过,则以w为新的出发点继续进行深度优先遍历,直至图中所有和源点v有路径相通的顶点(亦称为从源点可达的顶点)均已被访问为止。若此时图中仍有未访问的顶点,则另选一个尚未访问的顶点作为新的源点重复上述过程,直至图中所有顶点均已被访问为止。

  图的深度优先遍历类似于树的前序遍历。采用的搜索方法的特点是尽可能先对纵深方向进行搜索。这种搜索方法称为深度优先搜索(Depth-First Search)。相应地,用此方法遍历图就很自然地称之为图的深度优先遍历 

2.基本实现思想:

(1)访问顶点v;

(2)从v的未被访问的邻接点中选取一个顶点w,从w出发进行深度优先遍历;

(3)重复上述两步,直至图中所有和v有路径相通的顶点都被访问到。


 

3、拓扑排序是对有向无环图的一种排序。表示了顶点按边的方向出现的先后顺序。如果有环,则无法表示两个顶点的先后顺序。

在现实生活中,也会有不少应用例子,比如学校课程布置图,要先修完一些基础课,才可以继续修专业课。
一个简单的求拓扑排序的算法:首先要找到任意入度为0的一个顶点,删除它及所有相邻的边,再找入度为0的顶点,以此类推,直到删除所有顶点。顶点的删除顺序即为拓扑排序。
代码如下:
#include<iostream>
#include<queue>
#include<stack>
#include<malloc.h>
using namespace std;

#define MAXSIZE 10

struct Vertex
{
	char key;
	Vertex *next;
};

struct Graphic
{
	Vertex *vArray;
	int *indegree;
	int vertexNum;
	int size;
};

class MyGraph
{
public:
	MyGraph();
	void GraphInit(char edge[][2],int edgelen,char *vertexs,int verlen);
	void GraphEdgeInsert(char startkey,int endkey);
	Vertex* GraphVertexSearch(char key,int &location);
	int GraphOutDegree(char key);
	int GraphInDegree(char key);
	void GraphBFS();
	void GraphDFS();
	void GraphDFSRecur();
	void DFSRecur(int vnum,bool* verflag);
	void GraphTopSort();
private:
	Graphic *graph;
};

MyGraph::MyGraph()
{
	graph = (Graphic*)malloc(sizeof(Graphic));
	graph->vArray = (Vertex*)malloc(sizeof(Vertex)*MAXSIZE);
	graph->indegree = (int*)malloc(sizeof(int)*MAXSIZE);
	for(int i = 0; i < MAXSIZE;i++)
	{
		graph->vArray[i].key = NULL;
		graph->vArray[i].next = NULL;
		graph->indegree[i] = 0;
	}
	graph->vertexNum = 0;
	graph->size = MAXSIZE;
}

void MyGraph::GraphInit(char edge[][2],int edgelen,char *vertexs,int verlen)
{
	int i;
	if(verlen > graph->size)
	{
		graph->vArray = (Vertex*)realloc(graph->vArray,sizeof(Vertex)*(graph->size + verlen));
		graph->indegree = (int*)realloc(graph->indegree,sizeof(int)*(graph->size + verlen));
		graph->size += verlen;
	}

	for(i = 0; i < verlen; i++)
	{
		graph->vArray[i].key = vertexs[i];
	}
	graph->vertexNum = verlen;

	for(i = 0; i < edgelen; i++)
	{
		GraphEdgeInsert(edge[i][0],edge[i][1]);
	}

}

void MyGraph::GraphEdgeInsert(char startkey,int endkey)
{
	int location;
	Vertex *result = GraphVertexSearch(startkey,location);
	Vertex *newnode = (Vertex*)malloc(sizeof(Vertex));
	newnode->key = endkey;
	if(result == NULL)
	{
		if(graph->size == graph->vertexNum)
		{
			graph->vArray = (Vertex*)realloc(graph->vArray,sizeof(Vertex)*(graph->size + MAXSIZE));
			graph->size += MAXSIZE;
		}
		result = &(graph->vArray[graph->vertexNum]);
		result->key = startkey;
	}
	GraphVertexSearch(endkey,location);
	newnode->next = result->next;
	result->next = newnode;
	graph->indegree[location]++;
}

Vertex* MyGraph::GraphVertexSearch(char key,int &location)
{
	for(location = 0;location < graph->vertexNum; location++)
	{
		if(graph->vArray[location].key == key)
			return &(graph->vArray[location]);
	}
	return NULL;
}

int MyGraph::GraphOutDegree(char key)
{
	int outdegree = 0;
	int i;
	for(i = 0; i < graph->vertexNum; i++)
	{
		if(graph->vArray[i].key == key)
			break;
	}
	if(i != graph->vertexNum)
	{
		Vertex *temp = &(graph->vArray[i]);

		while(temp->next != NULL)
		{
			temp = temp->next;
			outdegree++;
		}
	}
	return outdegree; 
}

int MyGraph::GraphInDegree(char key)
{
	int indegree = 0;
	Vertex *temp;
	for(int i = 0;i < graph->vertexNum; i++)
	{
		if(graph->vArray[i].key != key)
		{
			temp = graph->vArray[i].next;
			while(temp != NULL)
			{
				if(temp->key == key)
				{
					indegree++;
					break;						//默认一个节点到另一个节点没有直接的两条或两条以上的边
				}
				temp = temp->next;
			}
		}
	}
	return indegree;
}

void MyGraph::GraphBFS()
{
	if(graph->vertexNum > 0)
	{
		bool *vertexflag = (bool*)malloc(sizeof(bool)*graph->vertexNum);
		int i;
		for(i = 0; i < graph->vertexNum; i++)
			vertexflag[i] = false;

		int vertexnum = 0;
		Vertex* temp,*element;
		queue<Vertex*> queue;
		cout<<"The result of BFS : ";
		while(vertexnum < graph->vertexNum)
		{
			if(vertexflag[vertexnum] == false)
				queue.push(&(graph->vArray[vertexnum]));
			while(!queue.empty())
			{
				temp = queue.front();
				queue.pop();
				cout<<temp->key<<" ";
				temp = temp->next;
				while(temp != NULL)
				{
					GraphVertexSearch(temp->key,i);
					if(vertexflag[i] == false)
					{
						vertexflag[i] = true;
						element = &(graph->vArray[i]);
						queue.push(element);
					}
					temp = temp->next;
				}
			}
			vertexnum++;
		}
		cout<<endl;
		return;
	}
	cout<<"Contain Nothing!"<<endl;
}

void MyGraph::GraphDFS()
{
	if(graph->vertexNum > 0)
	{
		bool *vertexflag = (bool*)malloc(sizeof(bool)*graph->vertexNum);
		int i;
		for(i = 0; i < graph->vertexNum; i++)
			vertexflag[i] = false;
		Vertex* temp;
		stack<Vertex*> vstack;
		int vertexnum = 0;
		cout<<"The result of DFS : ";
		while(vertexnum < graph->vertexNum)
		{
			if(vertexflag[vertexnum] == false)
				vstack.push(&(graph->vArray[vertexnum]));
			while(!vstack.empty())
			{
				temp = vstack.top();
				vstack.pop();
				if(temp->next != NULL)
					vstack.push(temp->next);
				GraphVertexSearch(temp->key,i);
				if(vertexflag[i] == false)
				{
					cout<<temp->key<<" ";
					if(graph->vArray[i].next != NULL)
						vstack.push(graph->vArray[i].next);
					vertexflag[i] = true;
				}

			}
			vertexnum++;
		}
		cout<<endl;
		return;
	}
	cout<<"Contain Nothing!"<<endl;
}

void MyGraph::GraphDFSRecur()
{
	bool *verflag = (bool*)malloc(sizeof(bool)*graph->vertexNum);
	int i;
	for(i = 0; i < graph->vertexNum; i++)
		verflag[i] = false;
	cout<<"The result of DFSRecur : ";
	i = 0;
	while(i < graph->vertexNum)
	{
		if(verflag[i] == false)
			DFSRecur(i,verflag);
		i++;
	}
	cout<<endl;
}

void MyGraph::DFSRecur(int vnum,bool* verflag)
{
	int i;
	cout<<graph->vArray[vnum].key<<" ";
	verflag[vnum] = true;
	Vertex* temp = graph->vArray[vnum].next;
	while(temp != NULL)
	{
		GraphVertexSearch(temp->key,i);
		if(verflag[i] == false)
		{
			DFSRecur(i,verflag);
		}
		temp = temp->next;
	}
}

void MyGraph::GraphTopSort()
{
	int i,location;
	int vexnum = graph->vertexNum;
	int count = 0;
	Vertex* temp;
	char *topSort = (char*)malloc(sizeof(char)*vexnum);
	int *tempindegree = (int*)malloc(sizeof(int)*vexnum);
	for(i = 0; i < vexnum; i++)
		tempindegree[i] = graph->indegree[i];

	
	while(count < vexnum)
	{
		for(i = 0; i < vexnum; i++)
		{
			if(tempindegree[i] == 0)
				break;
		}
		if(i != vexnum)
		{
			tempindegree[i] = -1;			//遍历后,把它排除在外
			temp = &(graph->vArray[i]);
			topSort[count] = temp->key;
			while(temp->next != NULL)
			{
				temp = temp->next;
				GraphVertexSearch(temp->key,location);
				tempindegree[location]--;
			}
		}
		else
		{
			cout<<"The Graphic contains circle!!"<<endl;
			return;
		}
		count++;
	}
	cout<<"The TOPSORT result : ";
	for(i = 0;i < vexnum;i++)
		cout<<topSort[i]<<" ";
	cout<<endl;
}

int main()
{
	MyGraph *mygraph = new MyGraph();
	char edge[][2] = {{'U','V'},{'U','X'},{'V','Y'},{'Y','X'},{'X','V'},{'W','Y'},{'W','Z'}};
	char vertexs[] = {'U','V','W','X','Y','Z'};

	mygraph->GraphInit(edge,7,vertexs,6);
	cout<<"The Out-Degree of U is "<<mygraph->GraphOutDegree('U')<<endl;
	cout<<"The In-Degree of U is "<<mygraph->GraphInDegree('U')<<endl;
	mygraph->GraphBFS();
	mygraph->GraphDFS();
	mygraph->GraphDFSRecur();
	mygraph->GraphTopSort();
	return 0;
}


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值