编程语言
首页 > 编程语言> > 邻接矩阵广度优先遍历算法 连通图采用邻接表深度优先遍历的非递归过程 图G中距离顶点v的最短路径长度最大迪杰斯特拉

邻接矩阵广度优先遍历算法 连通图采用邻接表深度优先遍历的非递归过程 图G中距离顶点v的最短路径长度最大迪杰斯特拉

作者:互联网

1.采用邻接矩阵存储图的广度优先遍历算法的实现(参考教材算法6.5选作)。

2.一个连通图采用邻接表作为存储结构,设计一个算法,实现从顶点v出发的深度优先遍历的非递归过程。

3.设计一个算法,求图G中距离顶点v的最短路径长度最大的一个顶点,设v可达其余各个顶点。

1

//算法6.7 广度优先搜索遍历连通图

#include <iostream>
using namespace std;

#define MVNum 100                       	//最大顶点数
#define MAXQSIZE 100						//最大队列长度
						
typedef char VerTexType;              		//假设顶点的数据类型为字符型
typedef int ArcType;                  		//假设边的权值类型为整型
bool visited[MVNum];           				//访问标志数组,其初值为"false" 

//-----图的邻接矩阵存储表示----- 
typedef struct{ 
	VerTexType vexs[MVNum];            		//顶点表
	ArcType arcs[MVNum][MVNum];      		//邻接矩阵
	int vexnum,arcnum;                		//图的当前点数和边数
}Graph;

//----队列的定义及操作--------
typedef struct{
	ArcType *base;							//初始化的动态分配存储空间
	int front;								//头指针,若队列不空,指向队头元素
	int rear;								//尾指针,若队列不空,指向队尾元素的下一个位置
}sqQueue;

void InitQueue(sqQueue &Q){
	//构造一个空队列Q
	Q.base = new ArcType[MAXQSIZE];
	if(!Q.base)     exit(1);				//存储分配失败
	Q.front = Q.rear = 0;
}//InitQueue

void EnQueue(sqQueue &Q, ArcType e){
	//插入元素e为Q的新的队尾元素
	if((Q.rear + 1) % MAXQSIZE == Q.front)
		return;
	Q.base[Q.rear] = e;
	Q.rear = (Q.rear + 1) % MAXQSIZE;
}//EnQueue

bool QueueEmpty(sqQueue Q){
	//判断是否为空队
	if(Q.rear == Q.front)
		return true;
	return false;
}//QueueEmpty

void DeQueue(sqQueue &Q, ArcType &u){
	//队头元素出队并置为u 
	u = Q.base[Q.front];
	Q.front = (Q.front + 1) % MAXQSIZE;
}//DeQueue   								
//--------------------------------------------------

int LocateVex(Graph G , VerTexType v){
	//确定点v在G中的位置
	for(int i = 0; i < G.vexnum; ++i)
		if(G.vexs[i] == v)
			return i;
		return -1;
}//LocateVex

void CreateUDN(Graph &G){ 
    //采用邻接矩阵表示法,创建无向网G 
	int i , j , k;
	cout <<"请输入总顶点数,总边数,以空格隔开:";
    cin >> G.vexnum >> G.arcnum;							//输入总顶点数,总边数
	cout << endl;
	cout << "输入点的名称,如a" << endl;
    for(i = 0; i < G.vexnum; ++i){   
		cout << "请输入第" << (i+1) << "个点的名称:";
		cin >> G.vexs[i];                        			//依次输入点的信息 
	}
	cout << endl;
    for(i = 0; i < G.vexnum; ++i)                			//初始化邻接矩阵,边的权值均置为极大值MaxInt 
		for(j = 0; j < G.vexnum; ++j)   
			G.arcs[i][j] = 0; 
	cout << "输入边依附的顶点,如a b" << endl;
	for(k = 0; k < G.arcnum;++k){							//构造邻接矩阵 
		VerTexType v1 , v2;
		cout << "请输入第" << (k + 1) << "条边依附的顶点:";
		cin >> v1 >> v2;									//输入一条边依附的顶点
		i = LocateVex(G, v1);  j = LocateVex(G, v2);		//确定v1和v2在G中的位置,即顶点数组的下标 
		G.arcs[i][j] = 1;									//边<v1, v2>的权值置为w 
		G.arcs[j][i] = G.arcs[i][j];						//置<v1, v2>的对称边<v2, v1>的权值为w 
	}//for 
}//CreateUDN

void BFS (Graph G, int v){ 
    //按广度优先非递归遍历连通图G 
	sqQueue Q;
    int u,w;
	 cout << G.vexs[v] << "  ";    visited[v] = true;     						//访问第v个顶点,并置访问标志数组相应分量值为true 
    InitQueue(Q);              													//辅助队列Q初始化,置空         
    EnQueue(Q, v);            													//v进队 
    while(!QueueEmpty(Q))
	{   													//队列非空 
		DeQueue(Q, u);       												//队头元素出队并置为u
	//	for(w = FirstAdjVex(G, u); w >= 0; w = NextAdjVex(G, u, w)){
			//依次检查u的所有邻接点w  ,修改该语句使得能够得到正确
		for(w=0;w<G.vexnum;w++)
		{
			if((G.arcs[v][w]!=0)&&(!visited[w]))
			{
				visited[w]=true;
				cout<<G.vexs[w]<<"  ";
				EnQueue(Q,w);
			}
			 
			/*if(!visited[w]){	           										//w为u的尚未访问的邻接顶点 
				cout << G.vexs[w] << "  ";   visited[w] = true;					//访问w,并置访问标志数组相应分量值为true 
				EnQueue(Q, w);													//w进队 
			}//if*/ 
		}//for
    }//while 
}//BFS

int main(){
	cout << "************算法6.7 广度优先搜索遍历连通图**************" << endl << endl;
	Graph G;
	CreateUDN(G);
	cout << endl;
	cout << "无向连通图G创建完成!" << endl << endl;
	
	cout << "请输入遍历连通图的起始点:";
	VerTexType c;
	cin >> c;
	
	int i;
	for(i = 0 ; i < G.vexnum ; ++i){
		if(c == G.vexs[i])
			break;
	}
	cout << endl;
	while(i >= G.vexnum){
		cout << "该点不存在,请重新输入!" << endl;
		cout << "请输入遍历连通图的起始点:";
		cin >> c;
		for(i = 0 ; i < G.vexnum ; ++i){
			if(c == G.vexs[i])
				break;
		}
	}
	cout << "广度优先搜索遍历连通图结果:" << endl;
	BFS(G , i);
	
	cout <<endl;
	return 0;
}//main

2

//算法6.6 采用邻接表表示图的深度优先搜索遍历

#include <iostream>
#include <stack>
using namespace std;

#define MVNum 100							//最大顶点数
typedef char VerTexType;					//假设顶点的数据类型为字符型 

//-------------图的邻接表---------------------
typedef struct ArcNode{                		//边结点 
    int adjvex;                          	//该边所指向的顶点的位置 
    struct ArcNode *nextarc;          		//指向下一条边的指针 
}ArcNode; 

typedef struct VNode{ 
    VerTexType data;                    	//顶点信息
    ArcNode *firstarc;                		//指向第一条依附该顶点的边的指针 
}VNode, AdjList[MVNum];               		//AdjList表示邻接表类型 

typedef struct{
    AdjList vertices;                 		//邻接表 
    int vexnum, arcnum;              		//图的当前顶点数和边数 
}ALGraph;

bool visited[MVNum];           				//访问标志数组,其初值为"false" 

int LocateVex(ALGraph G , VerTexType v){
	//确定点v在G中的位置
	for(int i = 0; i < G.vexnum; ++i)
		if(G.vertices[i].data == v)
			return i;
		return -1;
}//LocateVex

void CreateUDG(ALGraph &G){ 
	//采用邻接表表示法,创建无向图G
	int i , k;
	
	cout <<"请输入总顶点数,总边数,以空格隔开:";
	cin >> G.vexnum >> G.arcnum;				//输入总顶点数,总边数 
    cout << endl;
	
	cout << "输入点的名称,如a" << endl;

	for(i = 0; i < G.vexnum; ++i){          	//输入各点,构造表头结点表
		cout << "请输入第" << (i+1) << "个点的名称:";
		cin >> G.vertices[i].data;           	//输入顶点值 
		G.vertices[i].firstarc=NULL;			//初始化表头结点的指针域为NULL 
    }//for
	cout << endl;
    
	cout << "输入边依附的顶点,如a b" << endl;

	for(k = 0; k < G.arcnum;++k){        		//输入各边,构造邻接表
		VerTexType v1 , v2;
		int i , j;
		cout << "请输入第" << (k + 1) << "条边依附的顶点:";
		cin >> v1 >> v2;                 		//输入一条边依附的两个顶点
		i = LocateVex(G, v1);  j = LocateVex(G, v2);
		//确定v1和v2在G中位置,即顶点在G.vertices中的序号 
		
		ArcNode *p1=new ArcNode;               	//生成一个新的边结点*p1 
		p1->adjvex=j;                   		//邻接点序号为j 
		p1->nextarc= G.vertices[i].firstarc;  G.vertices[i].firstarc=p1;  
		//将新结点*p1插入顶点vi的边表头部
		
		ArcNode *p2=new ArcNode;                //生成另一个对称的新的边结点*p2 
		p2->adjvex=i;                   		//邻接点序号为i 
		p2->nextarc= G.vertices[j].firstarc;  G.vertices[j].firstarc=p2;  
		//将新结点*p2插入顶点vj的边表头部 
    }//for 
}//CreateUDG

/*void DFS(ALGraph G, int v){        				//图G为邻接表类型 
	cout << G.vertices[v].data << "   ";  
	visited[v] = true;    						//访问第v个顶点,并置访问标志数组相应分量值为true 
	ArcNode *p = G.vertices[v].firstarc;		//p指向v的边链表的第一个边结点 
	while(p != NULL){              				//边结点非空 
		int w = p->adjvex;               		//表示w是v的邻接点 
		if(!visited[w])  DFS(G, w);   			//如果w未访问,则递归调用DFS 
		p = p->nextarc;                			//p指向下一个边结点 
	} 
}//DFS*/

  
void DFS(ALGraph G, int v)
{  //从第v个顶点出发非递归实现深度优先遍历图G
	stack s;
	SetEmpty(s);
	Push(s,v);
	while(!StackEmpty(s))
{ 	//栈空时第v个顶点所在的连通分量已遍历完
Pop(s,k);
	If(!visited[k])
{	visited[k]=TRUE;
	VisitFunc(k);          //访问第k个顶点
	//将第k个顶点的所有邻接点进栈
for(w=FirstAdjVex(G,k);w;w=NextAdjVex(G,k,w))
{	
if(!visited[w]&&w!=GetTop(s)) Push(s,w);    //图中有环时w==GetTop(s)
}
		}
	}

			

int main(){
	cout << "************算法6.6 采用邻接表表示图的深度优先搜索遍历**************" << endl << endl;
	ALGraph G;
	CreateUDG(G);
	cout << endl;
	cout << "无向连通图G创建完成!" << endl << endl;

	cout << "请输入遍历连通图的起始点:";
	VerTexType c;
	cin >> c;
	
	int i;
	for(i = 0 ; i < G.vexnum ; ++i){
		if(c == G.vertices[i].data)
			break;
	}
	cout << endl;
	while(i >= G.vexnum){
		cout << "该点不存在,请重新输入!" << endl;
		cout << "请输入遍历连通图的起始点:";
		cin >> c;
		for(i = 0 ; i < G.vexnum ; ++i){
			if(c == G.vertices[i].data)
				break;
		}
	}

	cout << "深度优先搜索遍历图结果:" << endl;
	DFS(G , i);
	
	cout <<endl;
	return 0;
}//main

3

//算法6.10 迪杰斯特拉算法

#include <iostream>
using namespace std;

#define MaxInt 32767                    					//表示极大值,即∞
#define MVNum 100                       					//最大顶点数
typedef char VerTexType;              						//假设顶点的数据类型为字符型 
typedef int ArcType;                  						//假设边的权值类型为整型

int *D=new int[MVNum];	                    				//用于记录最短路的长度
bool *S=new bool[MVNum];          							//标记顶点是否进入S集合
int *Path=new int[MVNum];									//用于记录最短路顶点的前驱

//------------图的邻接矩阵-----------------
typedef struct{ 
	VerTexType vexs[MVNum];            						//顶点表 
	ArcType arcs[MVNum][MVNum];      						//邻接矩阵 
	int vexnum,arcnum;                						//图的当前点数和边数 
}AMGraph;

int LocateVex(AMGraph G , VerTexType v){
	//确定点v在G中的位置
	for(int i = 0; i < G.vexnum; ++i)
		if(G.vexs[i] == v)
			return i;
   return -1;
}//LocateVex

void CreateUDN(AMGraph &G){ 
    //采用邻接矩阵表示法,创建无向网G 
	int i , j , k;
	cout <<"请输入总顶点数,总边数,以空格隔开:";
    cin >> G.vexnum >> G.arcnum;							//输入总顶点数,总边数
	cout << endl;

	cout << "输入点的名称:,如a" << endl;

    for(i = 0; i < G.vexnum; ++i){   
		cout << "请输入第" << (i+1) << "个点的名称:";
		cin >> G.vexs[i];                        			//依次输入点的信息 
	}
	cout << endl;
    for(i = 0; i < G.vexnum; ++i)                			//初始化邻接矩阵,边的权值均置为极大值MaxInt 
		for(j = 0; j < G.vexnum; ++j)   
			G.arcs[i][j] = MaxInt; 
	cout << "输入边依附的顶点及权值,如a b 7" << endl;
	for(k = 0; k < G.arcnum;++k){							//构造邻接矩阵 
		VerTexType v1 , v2;
		ArcType w;
		cout << "请输入第" << (k + 1) << "条边依附的顶点及权值:";
		cin >> v1 >> v2 >> w;								//输入一条边依附的顶点及权值
		i = LocateVex(G, v1);  j = LocateVex(G, v2);		//确定v1和v2在G中的位置,即顶点数组的下标 
		G.arcs[i][j] = w;									//边<v1, v2>的权值置为w 
		G.arcs[j][i] = G.arcs[i][j];						//置<v1, v2>的对称边<v2, v1>的权值为w 
	}//for
}//CreateUDN

void ShortestPath_DIJ(AMGraph G, int v0){ 
    //用Dijkstra算法求有向网G的v0顶点到其余顶点的最短路径 
    int v , i , w , min;
	int n = G.vexnum;                    					//n为G中顶点的个数 

	for(v = 0; v < n; ++v){             					//n个顶点依次初始化 
		S[v] = false;                  						//S初始为空集 
		D[v] = G.arcs[v0][v];           					//将v0到各个终点的最短路径长度初始化为弧上的权值 
		if(D[v] < MaxInt)  Path [v] = v0;  					//如果v0和v之间有弧,则将v的前驱置为v0 
		else Path [v] = -1;               					//如果v0和v之间无弧,则将v的前驱置为-1 
	}//for 

	S[v0]=true;                    							//将v0加入S 
	D[v0]=0;                      							//源点到源点的距离为0 

	/*―初始化结束,开始主循环,每次求得v0到某个顶点v的最短路径,将v加到S集―*/ 
	for(i = 1;i < n; ++i){									//对其余n-1个顶点,依次进行计算 
        min= MaxInt; 
        for(w = 0; w < n; ++w) 
			if(!S[w] && D[w] < min){						//选择一条当前的最短路径,终点为v 
				v = w; 
				min = D[w];
			}//if         	
		S[v]=true;                   						//将v加入S 
		for(w = 0;w < n; ++w)           					//更新从v0出发到集合V?S上所有顶点的最短路径长度 
			if(!S[w] && (D[v] + G.arcs[v][w] < D[w])){ 
				D[w] = D[v] + G.arcs[v][w];   				//更新D[w] 
				Path [w] = v;              					//更改w的前驱为v 
			}//if 
    }//for  
}//ShortestPath_DIJ

void DisplayPath(AMGraph G , int begin ,int temp ){
	//显示最短路
	if(Path[temp] != -1){
		DisplayPath(G , begin ,Path[temp]);
		cout << G.vexs[Path[temp]] << "-->";
	}
}//DisplayPath

void main()
{
	cout << "************算法6.10 迪杰斯特拉算法**************" << endl << endl;
	AMGraph G; 
	int i , j ,num_start , num_destination;
	VerTexType start , destination;
	CreateUDN(G);
	cout <<endl;
	cout << "*****无向网G创建完成!*****" << endl;
	
	for(i = 0 ; i < G.vexnum ; ++i){
		for(j = 0; j < G.vexnum; ++j){
			if(j != G.vexnum - 1){
				if(G.arcs[i][j] != MaxInt)
					cout << G.arcs[i][j] << "\t";
				else
					cout << "∞" << "\t";
			}
			else{
				if(G.arcs[i][j] != MaxInt)
					cout << G.arcs[i][j] <<endl;
				else
					cout << "∞" <<endl;
			}
		}
	}//for
	cout << endl;
	cout << "请依次输入起始点、终点名称:";
	cin >> start >> destination;
	num_start = LocateVex(G , start);
	num_destination = LocateVex(G , destination);
	ShortestPath_DIJ(G , num_start);
	cout << endl <<"最短路径为:";
	DisplayPath(G , num_start , num_destination);
	cout << G.vexs[num_destination]<<endl;
}//main

标签:vexnum,优先,遍历,cout,int,LocateVex,迪杰,MVNum,顶点
来源: https://blog.csdn.net/qq_54008392/article/details/122135354