您的位置:首页 > 其它

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

2013-04-02 18:36 507 查看
和树的遍历相似,若从图中某顶点出发访遍图中每个顶点,且每个顶点仅访问一次,此过程称为图的遍历(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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐