有向图的邻接表存储,递归和非递归的深度、广度遍历(codeblocks+gcc。
程序功能:
1. 图的邻接表存储
2. 递归深度遍历
3. 非递归深度遍历(借助stack)
4. 递归广度遍历
5. 非递归广度遍历(借助queue)
程序中通过条件编译实现,递归与非递归的选择
- //#define _RECURSION_TRAVERSE //递归遍历(将下一行注释,此行不注释)
- #define _NON_RECURSION_TRAVERSE //非递归遍历(节点本身有isVisited域)(将上一行注释,此行不注释)
注释第一行,保留第二行:实现非递归遍历
注释第二行,保留第一行:实现递归遍历
两行都注释或都不注释:出错(无此函数/函数重名)
程序所用图的结构
程序源代码
- /*****************************************************************
- *功 能:利用邻接表存储图,实现其递归与非递归的深度遍历和广度遍历
- *作 者:JarvisChu
- *时 间:2011-04-30
- *****************************************************************/
- #include <iostream>
- #include <string>
- #include <stack>
- #include <queue>
- using namespace std;
- //#define _RECURSION_TRAVERSE //递归遍历(将下一行注释,此行不注释)
- #define _NON_RECURSION_TRAVERSE //非递归遍历(节点本身有isVisited域)(将上一行注释,此行不注释)
- #define MAX_VERTEX_NUM 20 //最大顶点数
- /*弧节点的结构,即每个顶点后面的单链表中的节点结构*/
- typedef struct ArcNode{
- int adjvex; //该弧所指向的顶点的位置
- struct ArcNode* nextArc; //下一条弧
- string info; //该弧所携带的信息
- }ArcNode;
- #ifdef _NON_RECURSION_TRAVERSE
- /*每个顶点的节点结构,非递归时使用*/
- typedef struct VNode{
- bool isVisited;
- string data; //顶点的数据
- ArcNode* fristArc; //指向该顶点所接的单链表的第一个弧节点
- }VNode,AdjList[MAX_VERTEX_NUM];
- #endif
- #ifdef _RECURSION_TRAVERSE
- /*每个顶点的节点结构,递归时使用*/
- typedef struct VNode{
- string data; //顶点的数据
- ArcNode* fristArc; //指向该顶点所接的单链表的第一个弧节点
- }VNode,AdjList[MAX_VERTEX_NUM];
- #endif
- /*图的结构*/
- typedef struct{
- AdjList vertices; //顶点数组
- int vexNum; //顶点数
- int arcNum; //弧数
- int kind; //种类
- }Graph;
- /*初始化有向图*/
- bool InitDiGraph(Graph* pGraph){
- pGraph->kind = 0; //有向图
- pGraph->vexNum = 5;
- pGraph->arcNum = 5;
- pGraph->vertices[0].data = “V0″; //顶点V0的邻接表
- #ifdef _NON_RECURSION_TRAVERSE
- pGraph->vertices[0].isVisited = false;
- #endif
- ArcNode* node = new ArcNode();
- node->adjvex = 1;
- node->info = “V0–>V1″;
- node->nextArc = NULL;
- ArcNode* node1 = new ArcNode();
- node1->adjvex = 2;
- node1->info = “V0–>V2″;
- node1->nextArc = NULL;
- node->nextArc = node1;
- pGraph->vertices[0].fristArc = node;
- pGraph->vertices[1].data = “V1″; //顶点V1的邻接表
- #ifdef _NON_RECURSION_TRAVERSE
- pGraph->vertices[1].isVisited = false;
- #endif
- pGraph->vertices[1].fristArc = NULL;
- pGraph->vertices[2].data = “V2″; //顶点V2的邻接表
- #ifdef _NON_RECURSION_TRAVERSE
- pGraph->vertices[2].isVisited = false;
- #endif
- node = new ArcNode();
- node->adjvex = 3;
- node->info = “V2–>V3″;
- node->nextArc = NULL;
- pGraph->vertices[2].fristArc = node;
- pGraph->vertices[3].data = “V3″; //顶点V3的邻接表
- #ifdef _NON_RECURSION_TRAVERSE
- pGraph->vertices[3].isVisited = false;
- #endif
- node = new ArcNode();
- node->adjvex = 0;
- node->info = “V3–>V0″;
- node->nextArc = NULL;
- node1 = new ArcNode();
- node1->adjvex = 4;
- node1->info = “V3–>V4″;
- node1->nextArc = NULL;
- node->nextArc = node1;
- pGraph->vertices[3].fristArc = node;
- pGraph->vertices[4].data = “V4″; //顶点V4的邻接表
- #ifdef _NON_RECURSION_TRAVERSE
- pGraph->vertices[4].isVisited = false;
- #endif
- pGraph->vertices[4].fristArc = NULL;
- return true;
- }
- /*显示有向图*/
- bool DisplayDiGraph(Graph diGraph){
- cout<<”*******************图信息********************”<<endl;
- cout<<”图种类为:”<<diGraph.kind<<endl;
- cout<<”顶点数为:”<<diGraph.vexNum<<endl;
- cout<<”弧数为:”<<diGraph.arcNum<<endl<<endl;
- cout<<”邻接表结构如下”<<endl;
- ArcNode* node = NULL;
- for(int i=0;i<diGraph.vexNum;i++){
- cout<<diGraph.vertices[i].data<<”:”;
- node = diGraph.vertices[i].fristArc;
- while(node != NULL){
- cout<<”(“<<node->adjvex<<”,”<<node->info<<”) ; “;
- node = node->nextArc;
- }
- cout<<endl;
- }
- return true;
- }
- #ifdef _NON_RECURSION_TRAVERSE
- /*深度优先非递归遍历有向图,利用栈*/
- bool Depth_First_Traverse(Graph* pDiGraph){
- for(int i=0;i<pDiGraph->vexNum;i++){ //初始化,全为false
- pDiGraph->vertices[i].isVisited = false;
- }
- VNode* vnode;
- stack<VNode*> TraverseStack; //用stack实现非递归遍历算法
- TraverseStack.push(&(pDiGraph->vertices[0])); //第一个节点入栈
- while(!TraverseStack.empty()){
- vnode = (VNode*)TraverseStack.top(); //获得栈顶节点
- vnode->isVisited = true;
- cout<<”遍历:”<<vnode->data<<endl;
- TraverseStack.pop();
- ArcNode* node = vnode->fristArc;
- while(node != NULL){
- if(!(pDiGraph->vertices[node->adjvex]).isVisited){
- TraverseStack.push(&(pDiGraph->vertices[node->adjvex])); //入栈
- }
- node = node->nextArc;
- }
- }
- return true;
- }
- #endif
- #ifdef _RECURSION_TRAVERSE
- /*深度优先递归遍历时,用来遍历每一个顶点*/
- bool DFT(Graph* pDiGraph,bool* visited,int i){
- if(!visited[i]){
- visited[i] = true; //标志该顶点已被访问了
- cout<<”遍历:”<<pDiGraph->vertices[i].data<<endl;
- ArcNode* node = pDiGraph->vertices[i].fristArc;//遍历其临街单链表
- while(node != NULL){
- DFT(pDiGraph,visited,node->adjvex);
- node = node->nextArc;
- }
- }
- return true;
- }
- /*深度优先递归遍历有向图*/
- bool Depth_First_Traverse(Graph* pDiGraph){
- int size = pDiGraph->vexNum; //顶点数目
- bool* visited = new bool[size]; //访问标志数组
- for(int i = 0;i < size;i++){ //初始化,全为false
- visited[i] = false;
- }
- for(int i = 0;i<size;i++){ //
- DFT(pDiGraph,visited,i);
- }
- delete[] visited;
- return true;
- }
- #endif
- #ifdef _NON_RECURSION_TRAVERSE
- /*广度优先非递归遍历有向图,利用队列*/
- bool Breadth_First_Traverse(Graph* pDiGraph){
- for(int i=0;i<pDiGraph->vexNum;i++){ //初始化,全为false
- pDiGraph->vertices[i].isVisited = false;
- }
- VNode* vnode;
- queue<VNode*> TraverseQueue; //用queue实现非递归遍历算法
- TraverseQueue.push(&(pDiGraph->vertices[0])); //第一个节点入队
- while(!TraverseQueue.empty()){
- vnode = (VNode*)TraverseQueue.front(); //获得队首节点
- vnode->isVisited = true;
- cout<<”遍历:”<<vnode->data<<endl;
- TraverseQueue.pop();
- ArcNode* node = vnode->fristArc;
- while(node != NULL){
- if(!(pDiGraph->vertices[node->adjvex]).isVisited){
- TraverseQueue.push(&(pDiGraph->vertices[node->adjvex])); //入队
- }
- node = node->nextArc;
- }
- }
- return true;
- }
- #endif
- #ifdef _RECURSION_TRAVERSE
- /*广度优先递归遍历时,用来遍历每一个顶点*/
- bool BFT(Graph* pDiGraph,bool* visited,int i){
- if(!visited[i]){
- visited[i] = true; //标志该顶点已被访问了
- cout<<”遍历:”<<pDiGraph->vertices[i].data<<endl;
- ArcNode* node = pDiGraph->vertices[i].fristArc;//遍历其临街单链表
- while(node != NULL){
- if(!pDiGraph->vertices[node->adjvex].isVisited){
- pDiGraph->vertices[node->adjvex].isVisited = true;
- cout<<”遍历:”<<pDiGraph->vertices[node->adjvex].data<<endl;
- }
- node = node->nextArc;
- // BFT(pDiGraph,visited,node->adjvex);
- }
- BFT(pDiGraph,visited,node->adjvex);
- }
- return true;
- }
- /*广度优先递归遍历有向图*/
- bool Breadth_First_Traverse(Graph* pDiGraph){
- int size = pDiGraph->vexNum; //顶点数目
- bool* visited = new bool[size]; //访问标志数组
- for(int i = 0;i < size;i++){ //初始化,全为false
- visited[i] = false;
- }
- for(int i = 0;i<size;i++){ //
- BFT(pDiGraph,visited,i);
- }
- delete[] visited;
- }
- #endif
- int main()
- {
- Graph diGraph; //有向图
- Graph udiGraph; //无向图
- InitDiGraph(&diGraph); //初始化有向图,构建
- DisplayDiGraph(diGraph); //显示该有向图
- cout<<endl<<”***************深度优先遍历结果***********”<<endl;
- Depth_First_Traverse(&diGraph); //深度优先遍历
- cout<<endl<<”***************广度优先遍历结果***********”<<endl;
- Breadth_First_Traverse(&diGraph); //广度优先遍历
- return 0;
- }
using namespace std;
//#define _RECURSION_TRAVERSE //递归遍历(将下一行注释,此行不注释)
#define _NON_RECURSION_TRAVERSE //非递归遍历(节点本身有isVisited域)(将上一行注释,此行不注释)
#define MAX_VERTEX_NUM 20 //最大顶点数
/*弧节点的结构,即每个顶点后面的单链表中的节点结构*/
typedef struct ArcNode{
int adjvex; //该弧所指向的顶点的位置
struct ArcNode* nextArc; //下一条弧
string info; //该弧所携带的信息
}ArcNode;
#ifdef _NON_RECURSION_TRAVERSE
/*每个顶点的节点结构,非递归时使用*/
typedef struct VNode{
bool isVisited;
string data; //顶点的数据
ArcNode* fristArc; //指向该顶点所接的单链表的第一个弧节点
}VNode,AdjList[MAX_VERTEX_NUM];
#endif
#ifdef _RECURSION_TRAVERSE
/*每个顶点的节点结构,递归时使用*/
typedef struct VNode{
string data; //顶点的数据
ArcNode* fristArc; //指向该顶点所接的单链表的第一个弧节点
}VNode,AdjList[MAX_VERTEX_NUM];
#endif
/*图的结构*/
typedef struct{
AdjList vertices; //顶点数组
int vexNum; //顶点数
int arcNum; //弧数
int kind; //种类
}Graph;
/*初始化有向图*/
bool InitDiGraph(Graph* pGraph){
pGraph->kind = 0; //有向图
pGraph->vexNum = 5;
pGraph->arcNum = 5;
pGraph->vertices[0].data = “V0″; //顶点V0的邻接表
#ifdef _NON_RECURSION_TRAVERSE
pGraph->vertices[0].isVisited = false;
#endif
ArcNode* node = new ArcNode();
node->adjvex = 1;
node->info = “V0–>V1″;
node->nextArc = NULL;
ArcNode* node1 = new ArcNode();
node1->adjvex = 2;
node1->info = “V0–>V2″;
node1->nextArc = NULL;
node->nextArc = node1;
pGraph->vertices[0].fristArc = node;
pGraph->vertices[1].data = “V1″; //顶点V1的邻接表
#ifdef _NON_RECURSION_TRAVERSE
pGraph->vertices[1].isVisited = false;
#endif
pGraph->vertices[1].fristArc = NULL;
pGraph->vertices[2].data = “V2″; //顶点V2的邻接表
#ifdef _NON_RECURSION_TRAVERSE
pGraph->vertices[2].isVisited = false;
#endif
node = new ArcNode();
node->adjvex = 3;
node->info = “V2–>V3″;
node->nextArc = NULL;
pGraph->vertices[2].fristArc = node;
pGraph->vertices[3].data = “V3″; //顶点V3的邻接表
#ifdef _NON_RECURSION_TRAVERSE
pGraph->vertices[3].isVisited = false;
#endif
node = new ArcNode();
node->adjvex = 0;
node->info = “V3–>V0″;
node->nextArc = NULL;
node1 = new ArcNode();
node1->adjvex = 4;
node1->info = “V3–>V4″;
node1->nextArc = NULL;
node->nextArc = node1;
pGraph->vertices[3].fristArc = node;
pGraph->vertices[4].data = “V4″; //顶点V4的邻接表
#ifdef _NON_RECURSION_TRAVERSE
pGraph->vertices[4].isVisited = false;
#endif
pGraph->vertices[4].fristArc = NULL;
return true;
}
/*显示有向图*/
bool DisplayDiGraph(Graph diGraph){
cout<<”*******************图信息********************”<<endl;
cout<<”图种类为:”<<diGraph.kind<<endl;
cout<<”顶点数为:”<<diGraph.vexNum<<endl;
cout<<”弧数为:”<<diGraph.arcNum<<endl<<endl;
cout<<”邻接表结构如下”<<endl;
ArcNode* node = NULL;
for(int i=0;i<diGraph.vexNum;i++){
cout<<diGraph.vertices[i].data<<”:”;
node = diGraph.vertices[i].fristArc;
while(node != NULL){
cout<<”(“<<node->adjvex<<”,”<<node->info<<”) ; “;
node = node->nextArc;
}
cout<<endl;
}
return true;
}
#ifdef _NON_RECURSION_TRAVERSE
/*深度优先非递归遍历有向图,利用栈*/
bool Depth_First_Traverse(Graph* pDiGraph){
for(int i=0;i<pDiGraph->vexNum;i++){ //初始化,全为false
pDiGraph->vertices[i].isVisited = false;
}
VNode* vnode;
stack<VNode*> TraverseStack; //用stack实现非递归遍历算法
TraverseStack.push(&(pDiGraph->vertices[0])); //第一个节点入栈
while(!TraverseStack.empty()){
vnode = (VNode*)TraverseStack.top(); //获得栈顶节点
vnode->isVisited = true;
cout<<”遍历:”<<vnode->data<<endl;
TraverseStack.pop();
ArcNode* node = vnode->fristArc;
while(node != NULL){
if(!(pDiGraph->vertices[node->adjvex]).isVisited){
TraverseStack.push(&(pDiGraph->vertices[node->adjvex])); //入栈
}
node = node->nextArc;
}
}
return true;
}
#endif
#ifdef _RECURSION_TRAVERSE
/*深度优先递归遍历时,用来遍历每一个顶点*/
bool DFT(Graph* pDiGraph,bool* visited,int i){
if(!visited[i]){
visited[i] = true; //标志该顶点已被访问了
cout<<”遍历:”<<pDiGraph->vertices[i].data<<endl;
ArcNode* node = pDiGraph->vertices[i].fristArc;//遍历其临街单链表
while(node != NULL){
DFT(pDiGraph,visited,node->adjvex);
node = node->nextArc;
}
}
return true;
}
/*深度优先递归遍历有向图*/
bool Depth_First_Traverse(Graph* pDiGraph){
int size = pDiGraph->vexNum; //顶点数目
bool* visited = new bool[size]; //访问标志数组
for(int i = 0;i < size;i++){ //初始化,全为false
visited[i] = false;
}
for(int i = 0;i<size;i++){ //
DFT(pDiGraph,visited,i);
}
delete[] visited;
return true;
}
#endif
#ifdef _NON_RECURSION_TRAVERSE
/*广度优先非递归遍历有向图,利用队列*/
bool Breadth_First_Traverse(Graph* pDiGraph){
for(int i=0;i<pDiGraph->vexNum;i++){ //初始化,全为false
pDiGraph->vertices[i].isVisited = false;
}
VNode* vnode;
queue<VNode*> TraverseQueue; //用queue实现非递归遍历算法
TraverseQueue.push(&(pDiGraph->vertices[0])); //第一个节点入队
while(!TraverseQueue.empty()){
vnode = (VNode*)TraverseQueue.front(); //获得队首节点
vnode->isVisited = true;
cout<<”遍历:”<<vnode->data<<endl;
TraverseQueue.pop();
ArcNode* node = vnode->fristArc;
while(node != NULL){
if(!(pDiGraph->vertices[node->adjvex]).isVisited){
TraverseQueue.push(&(pDiGraph->vertices[node->adjvex])); //入队
}
node = node->nextArc;
}
}
return true;
}
#endif
#ifdef _RECURSION_TRAVERSE
/*广度优先递归遍历时,用来遍历每一个顶点*/
bool BFT(Graph* pDiGraph,bool* visited,int i){
if(!visited[i]){
visited[i] = true; //标志该顶点已被访问了
cout<<”遍历:”<<pDiGraph->vertices[i].data<<endl;
ArcNode* node = pDiGraph->vertices[i].fristArc;//遍历其临街单链表
while(node != NULL){
if(!pDiGraph->vertices[node->adjvex].isVisited){
pDiGraph->vertices[node->adjvex].isVisited = true;
cout<<”遍历:”<<pDiGraph->vertices[node->adjvex].data<<endl;
}
node = node->nextArc;
// BFT(pDiGraph,visited,node->adjvex);
}
BFT(pDiGraph,visited,node->adjvex);
}
return true;
}
/*广度优先递归遍历有向图*/
bool Breadth_First_Traverse(Graph* pDiGraph){
int size = pDiGraph->vexNum; //顶点数目
bool* visited = new bool[size]; //访问标志数组
for(int i = 0;i < size;i++){ //初始化,全为false
visited[i] = false;
}
for(int i = 0;i<size;i++){ //
BFT(pDiGraph,visited,i);
}
delete[] visited;
}
#endif
int main()
{
Graph diGraph; //有向图
Graph udiGraph; //无向图
InitDiGraph(&diGraph); //初始化有向图,构建
DisplayDiGraph(diGraph); //显示该有向图
cout<<endl<<”***************深度优先遍历结果***********”<<endl;
Depth_First_Traverse(&diGraph); //深度优先遍历
cout<<endl<<”***************广度优先遍历结果***********”<<endl;
Breadth_First_Traverse(&diGraph); //广度优先遍历
return 0;
}
程序运行结果
0 表示有向图