【数据结构】实验十一:图

实验十一 图

一、实验目的与要求

1)掌握图的存储表示与操作实现。

2)掌握图的连通性及其应用。

二、 实验内容

1.用邻接表存储一个图形结构,并计算每个顶点的度。

2. 采用深度和广度优先搜索算法,遍历上述这张图,并输出遍历结果。

三、实验结果

1)请将调试通过的运行结果截图粘贴在下面,并说明测试用例、运行过程和算法步骤。

2请分析算法的时间复杂度。

3)请将源代码(必要的注释)cpp文件压缩上传(上传附件)。


题目1:

1

测试用例:

测试用例为总结点数为4、总边数为5的无向图,如下图所示。

运行结果:

运行过程:

通过邻接表创建无向连通图->通过for循环遍历并输出邻接表结果->通过for循环计算并输出各顶点的度数。

2

算法步骤和时间复杂度分析:

图的邻接表存储类似于树的孩子链表表示法。对于图中每个顶点vi建立一个链表,第i个链表中的结点表示依附于vi的边。每个链表上附设一个头结点和一个尾结点。

假设需要存储的图的顶点数为V,边数为E。如果存储的是无向图,那么遍历时先访问顶点数组的各个元素,再访问其对应的边链表,由于有V个节点,而且无向图的E条边在边链表中会出现两次,即边共出现2E次,所以一共的访问次数为V+2E。因此,算法的时间复杂度为O(|V|+2|E|)。

对于n个顶点无向图的邻接表,顶点vi的度恰为第i个链表中的结点个数。因此可以计算无向图中每个顶点的度。

3

实验源代码:

#include <iostream>
using namespace std;
#define MVNum 100//最大顶点数 

typedef char VerTexType;//顶点信息
typedef int OtherInfo;//和边相关的信息 

//边结点 
typedef struct ArcNode{
    int adjvex;//该边所指向的顶点的位置 
    struct ArcNode *nextarc;//指向下一条边的指针 
    OtherInfo info;//和边相关的信息
}ArcNode; 

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

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

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

//采用邻接表表示法,创建无向图G
void CreateUDG(ALGraph &G){
	int i , k;
	cout <<"请输入总顶点数:";
	cin >> G.vexnum;
	cout <<"请输入总边数:";
	cin >> G.arcnum;
    cout << endl;
	cout << "输入点的名称:" <<endl;
	for(i = 0; i < G.vexnum; ++i){       	
		cout << "请输入第" << (i+1) << "个点的名称:";
		cin >> G.vertices[i].data;//输入顶点值 
		G.vertices[i].firstarc=NULL;//初始化表头结点的指针域为NULL 
    }
	cout << endl;
	cout << "请输入一条边依附的顶点:"<<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);//确定第二个点的位置
		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的边表头部 
    } 
}

//输出邻接表 
void Show(ALGraph &G){
	cout<<endl;
	int i;
	cout<<endl<<"邻接表为:"<<endl; 
	for(i = 0 ; i < G.vexnum ; ++i){
		VNode temp = G.vertices[i];
		ArcNode *p = temp.firstarc;
		if(p == NULL){
			cout << G.vertices[i].data;
			cout << endl;
		}
		else{
			cout << temp.data;
			while(p){
				cout << "->";
				cout << p->adjvex;
				p = p->nextarc;
			}
		}
		cout << endl;
	}
}

//计算度数 
void CountDegree(ALGraph *G){
	cout<<endl;
	int i,j,k,degree;
	int count1=0;
	ArcNode *p;
	for(i=0;i<G->vexnum;i++){
		degree=0;
		p=G->vertices[i].firstarc;
		while(p!=NULL){
			degree++;
			p=p->nextarc ;
		} 
		if(i!=G->vexnum -1){
			cout<<degree<<" ";
		}
		else{
			cout<<degree;
		}
	}
}

int main(){
	ALGraph G;
	CreateUDG(G);
	Show(G);
	cout<<endl<<"各顶点度数依次为:"<<endl;
	CountDegree(&G);
	return 0;
}







题目2:

1

测试用例:

下图所示的总顶点数的9,总边数为10的无向连通图。人为设置从A点开始遍历。

运行结果:

深度优先:

 

 广度优先:

运行过程:

深度优先:

通过邻接表创建无向连通图->输入遍历起点的名称->判断起点是否在无向图内->调用DFS函数进行深度遍历。

广度优先:

通过邻接矩阵和队列创建无向连通图->输入遍历起点的名称->判断起点是否在无向图内->调用BFS函数进行深度遍历。

2

算法步骤和时间复杂度分析:

深度优先:

假设图的顶点个数为n,边的个数为e。本算法的执行时间主要耗费在递归调用DFS函数上。当访问某顶点时,DFS的执行时间主要耗费在从该顶点出发搜索其所有邻接点上。采用邻接表作为图的存储结构时,对n个顶点访问就需要对所有链表中的e个表结点检查一遍。因此,算法的时间复杂度为O(n+e)。

广度优先:

假设图的顶点个数为n,边的个数为e。本算法对图中的每一个顶点均入队一次。当访问某个顶点时,执行时间主要耗费在从该顶点出发搜索其所有邻接点上。采用邻接矩阵作为图的存储结构时,查找每一个顶点的邻接点所需要的时间为O(n2)。因此,算法的时间复杂度为O(n2)。

3

实验源代码:

深度优先

//深度优先 
#include <iostream>
#include <cstring>
#include <cstdio>
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" 

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

//采用邻接表表示法,创建无向图G
void CreateUDG(ALGraph &G){ 
	int i , k;
	cout <<"请输入总顶点数,总边数:";
	cin >> G.vexnum >> G.arcnum;
    cout << endl;
	
	cout << "输入点的名称:" << endl;
    //输入各点,构造表头结点表
	for(i = 0; i < G.vexnum; ++i){          	
		cout << "请输入第" << (i+1) << "个点的名称:";
		cin >> G.vertices[i].data;//输入顶点值 
		G.vertices[i].firstarc=NULL;		
    }
	cout << endl;
    
	cout << "输入边依附的顶点:" << 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的边表头部 
    }
}

//深度优先 
void DFS(ALGraph G, int v){        				
	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指向下一个边结点 
	} 
}

int main(){
	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);
	return 0;
}

广度优先

//广度优先
#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;

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

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

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

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

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

//采用邻接矩阵表示法,创建无向G
void CreateUDN(Graph &G){
	int i , j , k;
	cout <<"请输入总顶点数,总边数:";
    cin >> G.vexnum >> G.arcnum;						
	cout << endl;
	cout << "输入点的名称:" << endl;
    for(i = 0; i < G.vexnum; ++i){   
		cout << "请输入第" << (i+1) << "个点的名称:";
		cin >> G.vexs[i];
	}
	cout << endl;
	//初始化邻接矩阵,边的权值均置为极大值MaxInt
    for(i = 0; i < G.vexnum; ++i)               			 
		for(j = 0; j < G.vexnum; ++j)   
			G.arcs[i][j] = 0; 
	cout << "输入边依附的顶点:" << 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 
	}
}

//返回v的第一个邻接点
int FirstAdjVex(Graph G , int v){
	int i;
	for(i = 0 ; i < G.vexnum ; ++i){
		if(G.arcs[v][i] == 1 && visited[i] == false){
			return i;
		}
	}
	return -1;
}

//返回v相对于w的下一个邻接点
int NextAdjVex(Graph G , int u , int w){
	int i;
	for(i = w ; i < G.vexnum ; ++i){
		if(G.arcs[u][i] == 1 && visited[i] == false){
			return i;
		}
	}
	return -1;
}

//按广度优先非递归遍历连通图G
void BFS (Graph G, int v){ 
	sqQueue Q;
	ArcType u;
	ArcType w;
    cout << G.vexs[v] << "->";    
	visited[v] = true;  
    InitQueue(Q);//辅助队列Q  
    EnQueue(Q, v);//v进队 
    while(!QueueEmpty(Q)){
		DeQueue(Q, u);
		for(w = FirstAdjVex(G, u); w >= 0; w = NextAdjVex(G, u, w)){
			//依次检查u的所有邻接点w ,FirstAdjVex(G, u)表示u的第一个邻接点 
			//NextAdjVex(G, u, w)表示u相对于w的下一个邻接点,w≥0表示存在邻接点 
			if(!visited[w]){//w为u的尚未访问的邻接顶点
				cout << G.vexs[w]<<"->";   
				visited[w] = true;
				EnQueue(Q, w);//w进队 
			}
		}
    }
}

int main(){
	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);
	return 0;
}

实验十一 图(2)

一、实验目的与要求

3)掌握最小生成树的概念和算法;

4)掌握最短路径的算法的实现;

5)掌握拓扑排序的应用。

二、实验内容

1.输出所有可能的路径

有n个结点的有向无环图,选取合适的存储方式并找到所有从0到n-1的路径并输出(不要求按顺序)。二维数组的第i个数组中的单元都表示有向图中i号结点所能到达的结点(注:有向图是有方向的,即规定了a→b你就不能从b→a)空就是没有下一个结点了。

示例1:

输入:graph = [[1,2],[3],[3],[]]

输出:[[0,1,3],[0,2,3]]

解释:有两条路径 0 -> 1 -> 3 和 0 -> 2 -> 3

示例2:

输入:graph = [[4,3,1],[3,2,4],[3],[4],[]]

输出:[[0,4],[0,3,4],[0,1,3,4],[0,1,2,3,4],[0,1,4]]

2.建造物流配送中心问题

给定4个城市之间的交通图如下图所示(图中弧上数字表示城市之间的道路长度)。要在4个城市之间选择一个城市建造一个物流配送中心,并使得到物流配送中心最远的城市到物流配送中心的路程最短。

要求:

(1)设计存储结构表示城市及城市之间的关系;

(2)求出物流配送中心最远城市到物流配送中心的最短路程;

(3)分析算法的时间复杂度。

三、实验结果

1)请将调试通过的主要源代码、运行结果截图粘贴在下面,并说明测试用例、运行过程。(必要的注释、Times New Roman 5号,行间距1.5倍)

2)简述算法步骤(选画技术路线图),格式如下:

S1:

S2:

3)请分析算法的时间复杂度。

4)请将源代码(必要的注释)cpp文件一起压缩上传(上传附件)。


题目1:

(1.1)源代码

#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;

//DFS回溯算法——遍历graph[p],寻找下一个元素,并进行回溯。
void DFS(vector<vector<int> > & graph,vector<int> path,vector<vector<int> >& res,int p){
	int i;
	//在graph[p]中找下一个元素
    for(i=0;i<graph[p].size();i++){
    	//找到最后一个元素,将path加入res
        if(graph[p][i]==graph.size()-1){
            path.push_back(graph.size()-1);
            res.push_back(path);
            path.pop_back();
            continue;
        }
        path.push_back(graph[p][i]);  //不是最后一个元素,继续回溯
        DFS(graph,path,res,graph[p][i]);  //递归调用 
        path.pop_back();
    }
}

//寻找所有到达路径 
vector<vector<int> > allPathsSourceTarget(vector<vector<int> >& graph) {
    vector<vector<int> > res;  //res存储一条路径的所有结点 
    vector<int> path={0};
    DFS(graph,path,res,0);  //调用DFS函数 
    return res;
}

//主函数 
int main() {
	int n;
	cout<<"请输入结点个数:";
	cin>>n;
	vector<vector<int> > store(n);
	cout<<endl<<"请依次输入每个结点的出度以及可达结点的编号:"<<endl<<endl;
	for(int i=0;i<n;i++){
		int m;
		cout<<"编号为"<<i<<"的结点的出度:";
		cin>>m;
		cout<<endl<<"该结点可达结点的编号:";
		vector<int> each(m);
		for(int j=0;j<m;j++){
			cin>>each[j];
		}
		cout<<endl;
		store[i]=each;
	}
	vector<vector<int> > res=allPathsSourceTarget(store);
	cout<<endl<<"所有的可能路径如下:"<<endl;
	cout<<endl;
	for(int k=0;k<res.size();k++){
		for(int l=0;l<res[k].size();l++){
			if(l==0){
				cout<<res[k][l];
			}
			else{
				cout<<"->"<<res[k][l];
			}
		}
		cout<<endl;
	}
	return 0;
}

(1.2)测试用例

测试用例1:

    如图1所示的4点4边的有向图。寻找0点到3点的所有可能路径。

测试用例2:

    如图2所示的5点8边的有向图。寻找0点到4点的所有可能路径。

(图1)

(图2)

(1.3)运行结果

测试用例1:

测试用例2:

(1.4)运行过程

输入总结点数 -> 输入各结点的出度 -> 输入当前结点可达的结点 -> 调用寻找所有到达路径的函数 -> DFS回溯遍历 -> 输出所有可能的路径。

(2)算法步骤

S1:DFS回溯函数。该函数不仅包含了递归的过程,而且包含了回退的过程。对于一个无向连通图,访问图中某个顶点v0后,然后访问它的某一个邻接顶点v1,然后再从v1出发,访问v1的未访问过的邻接顶点。如此下去,直至到达所有的领接顶点都被访问过。然后回退一步,回到前一次被访问的顶点,看是否还有没有访问的顶点。如果有没有访问的顶点,那么从这个顶点出发,进行向上述的过程一样进行访问;如果无没有访问的顶点,那么再回退一步,进行类似的访问,直至所有的顶点都被访问为止。后续该函数将在寻找所有到达路径函数中被调用。

S2:寻找所有到达路径函数。利用vector<int>向量容器,同时调用DFS回溯函数,将得到的路径结点顺序存储到res数组中,最后返回res数组的结果。后续该函数将在主函数中被调用。

S3:主函数。依次输入结点数、每个结点的出度和当前结点指向的结点,并用数组储存起来。建立起有向图的结构,并明确各个结点之间的连通性。

 

 

(3)算法时间复杂度分析

在遍历有向图时,对于图中每个结点,DFS函数至多调用一次。一旦某个结点被标志为已访问,就不再从当前结点开始进行搜索。对图的遍历实质上是对每个结点查找其邻接点的过程。DFS回溯函数中,使用的是二维数组和向量容器进行存储。因此,查找每个顶点的邻接点所需时间为O(n2)。

因此,本算法的时间复杂度为O(n2)。


题目2:

(1.1)源代码

#include <iostream>
#include <vector>
#define inf 99999
using namespace std;

//邻接矩阵 
int graph[4][4]{
    {0,8,inf,inf},
    {10,0,5,inf},
    {4,inf,0,4},
    {inf,7,3,0},
}; 

int path[4][4]{ 
    {0,1,2,3},
    {0,1,2,3},
    {0,1,2,3},
    {0,1,2,3},
}; 

//最短路径算法 
void solve(int graph[4][4],int path[4][4]){
	int i,j,k;
	for(k=0;k<4;k++) {
        for(i=0;i<4;i++) {
            for(j=0;j<4;j++) {
                if(graph[i][k]+graph[k][j] < graph[i][j]) {
                    graph[i][j] = graph[i][k]+graph[k][j];  //更新最短路径 
                    path[i][j] = path[i][k];
                }
            }
        }
    }
}

//输出邻接矩阵
void Output(int graph[4][4]){
	int i,j;
	for(i=0;i<4;i++){
    	cout<<"[";
    	for(j=0;j<4;j++){
    		if(graph[i][j]==99999){
    			cout<<"inf";
			}
			else{
				cout.width(4);
    			cout<<graph[i][j];
			}
    		if(j!=3){
    			cout<<",";
			}
		}
		cout<<"]\n";
	}
}

//排序最远距离
void Sort(int graph[4][4]){
	int i,j,maxlen[4];//i行j列 
	for(j=0;j<4;j++){
		int maxno=0;
		for(i=0;i<4;i++){
			if(graph[maxno][j]<graph[i][j]){
				maxno=i;
			}
		}
		maxlen[j]=maxno; 
	}
	cout<<"到当前结点最远的距离依次为:";
	for(int k=0;k<4;k++){
		cout<<graph[maxlen[k]][k]<<" ";//第k列的最大数 
	}
	cout<<endl;
	cout<<"其中最小的距离为:";
	int min=graph[maxlen[0]][0],minno=0;
	for(i=1;i<4;i++){
		if(min>graph[maxlen[i]][i]){
			min=graph[maxlen[i]][i];
			minno=i;
		}
	}
	cout<<min<<endl;
	cout<<"所以物流配送中心应该建设的地方为:";
	switch(minno){
		case 0:cout<<"a"<<endl;break;
		case 1:cout<<"b"<<endl;break;
		case 2:cout<<"c"<<endl;break;
		case 3:cout<<"d"<<endl;break;
	}
}

//主函数 
int main() {
	cout<<"初始邻接矩阵:"<<endl; 
	Output(graph);
    solve(graph,path);
    cout<<endl<<"最终邻接矩阵:"<<endl; 
    Output(graph);
    cout<<endl;
    Sort(graph);
    return 0;
}

(1.2)测试用例

测试用例为如下图所示的4点7边的有向图。

预设置的邻接矩阵为:

{0,8,inf,inf}

{10,0,5,inf}

{4,inf,0,4}

{inf,7,3,0}

(1.3)运行结果

(1.4)运行过程

预先设置初始邻接矩阵 -> 输出初始邻接矩阵 -> 将每一个结点进行最小路径函数调用 -> 输出最小路径条件下的邻接矩阵 -> 排序离当前结点的最远距离 -> 寻找最远距离中的最小值和最小值对应的结点并输出。

(2)算法步骤

S0:初始化。预先设置邻接矩阵graph和存储路径的二维数组path。

S1:最短路径算法函数。利用三层for循环,遍历图的所有路径,同时根据判断条件得到当前的最短路径,并更新最短路径,从而使graph中的数据得以更新。

S2:输出邻接矩阵函数。按照矩阵的形式,输出结果最短路径算法更新后的邻接矩阵。

S3:排序最远距离函数。首先通过两层for循环寻找所有结点到当前结点的最远距离,并通过maxlen数组存储。之后通过一层for循环寻找maxlen数组中的最小值,并记录最小值对应的结点序号。最后统一输出每一个结点的最远物流距离,最小的最远物流距离及其对应结点。

S4:主函数。在主函数中依次调用输出邻接矩阵函数(最初的状态)、最短路径算法函数、输出邻接矩阵函数(给每个结点均进行了戴克斯特拉算法的状态)、排序最远距离函数,即可得到物流中心的建设结果和计算分析过程。

(3)算法时间复杂度分析

在最短路径算法函数中,使用了三层for循环来更新最短路径,对于邻接矩阵的每一行而言,耗费的时间为O(n3)。

在排序最远距离函数中,使用了两层for循环来寻找每个结点的最远物流距离,耗费的时间为O(n2);并使用了一层for循环来寻找最远物流距离中的最小值,耗费的时间为O(n)。

因此,本算法的时间复杂度为O(n3)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/54662.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

网络基础-认识每层的设备和每层的特点用途

目录 网络层次常见设备各层介绍数据链路层网络层传输层应用层 网络层次 常见设备 各层介绍 数据链路层 有了MAC地址。数据链路层工作在局域网中的&#xff0c;以帧为单位进行传输和处理数据。 网络层 网络层有了IP。不同的网络通过路由器连接成为互联网 路由器的功能:   …

数据挖掘实战:基于KMeans算法对超市客户进行聚类分群(文末送书)

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

1.2 eureka注册中心,完成服务注册

目录 环境搭建 搭建eureka服务 导入eureka服务端依赖 编写启动类&#xff0c;添加EnableEurekaServer注解 编写eureka配置文件 启动服务,访问eureka Euraka服务注册 创建了两个子模块 在模块里导入rureka客户端依赖 编写eureka配置文件 添加Services 环境搭建 创建父…

【算法提高:动态规划】1.3 背包模型 TODO

文章目录 例题列表423. 采药&#xff08;01背包&#xff09;1024. 装箱问题&#xff08;大小和价值相等的01背包&#xff09;1022. 宠物小精灵之收服&#xff08;二维费用的背包问题&#xff09;补充&#xff1a;相关题目——8. 二维费用的背包问题 278. 数字组合&#xff08;0…

【雕爷学编程】MicroPython动手做(02)——尝试搭建K210开发板的IDE环境

知识点&#xff1a;简单了解K210芯片 2018年9月6日,嘉楠科技推出自主设计研发的全球首款基于RISC-V的量产商用边缘智能计算芯片勘智K210。该芯片依托于完全自主研发的AI神经网络加速器KPU,具备自主IP、视听兼具与可编程能力三大特点,能够充分适配多个业务场景的需求。作为嘉楠科…

快速搭建Vue项目

1.安装node环境 下载地址为&#xff1a;https://nodejs.org/en/ 注意node版本问题&#xff0c;有很多情况下是node版本问题导致的错误。 2.安装淘宝镜像cnpm 为了提高我们的效率&#xff0c;可以使用淘宝的镜像&#xff1a;http://npm.taobao.org/ npm install cnpm -g --r…

PostgreSQL Patroni_exporter 监控 patroni高可用工具

Patroni是Cybertec公司基于python语言开发的&#xff0c;可用于使用流复制来创建&#xff0c;管理&#xff0c;维护和监视高可用性PostgreSQL集群设置的工具。 目前&#xff0c;PatroniEtcd 是最为推荐的PostgreSQL数据库高可用方案之一。 PostgreSQL有postgres_exporter监控采…

华为OD机试真题 JavaScript 实现【小朋友排队】【2023 B卷 100分】,附详细解题思路

目录 一、题目描述二、输入描述三、输出描述四、解题思路五、JavaScript算法源码六、效果展示1、输入2、输出 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 刷的越多&#xff0c;抽中的概率越大&#xff0c;每一题都有详细的答题思路、详细的代码注释、样例测试&am…

uC-OS2 V2.93 STM32L476 移植:环境搭建篇

前言 uC-OS2 是比较经典的 RTOS&#xff0c;如今软件授权已经改为 Apache License Version 2.0&#xff0c;意味着可以免费商用了 当前 uC-OS2 的最新版本是&#xff1a; V2.93&#xff0c;打算研究一下 RTOS 的设计思想&#xff0c;所以想在已有的开发板&#xff1a;NUCLEO-L…

WAVE SUMMIT 定档8月16日,或将曝百度飞桨、文心大模型最新进展

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

【LeetCode 75】第十七题(1493)删掉一个元素以后全为1的最长子数组

目录 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 代码运行结果&#xff1a; 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 给一个数组&#xff0c;求删除一个元素以后能得到的连续的最长的全是1的子数组。 我们可以先单独统计出连续为1的子数组分别长度…

Vue3--->组合式API与Pinia

目录 使用create-vue搭建 1、使用create-vue创建项目 2、项目目录和关键文件 组合式API 1、组合式API - setup选项 2、组合式API - reactive和ref函数 3、组合式API - computed 4、组合式API - watch 1、基础使用 - 侦听单个数据 2、基础使用 - 侦听多个数据 3、immediate&…

【单片机】温控系统参数辨识及单片机PID控制

温控系统参数辨识及单片机PID控制 1. 温控系统组成2. matlab辨识系统参数2.1 采集阶跃响应信号导入matlab系统辨识模块 PID控制 1. 温控系统组成 半导体制冷片正向通电制冷&#xff0c;反向通电制热。系统采用半导体制冷片&#xff08;帕尔贴&#xff09;作为执行单元&#xf…

WilliamNing - 电脑办公环境 - 以及个人工作/开发习惯 - Windows/Mac

主要是记录个人的办公环境习惯&#xff0c;方便到新的环境&#xff0c;快速搭建自己熟悉的环境&#xff0c;从而提高工作效率 1. Windows 深圳客友 腾讯外包 家里电脑 TBD 2. Mac SeekAsia[深圳就业网络] Kumu[成都脑海科技] 2.1 桌面软件列表 后调整 -- 加了一些软件 同时…

组件化、跨平台…未来前端框架将如何演进?

前端框架在过去几年间取得了显著的进步和演进。前端框架也将继续不断地演化&#xff0c;以满足日益复杂的业务需求和用户体验要求。从全球web发展角度看&#xff0c;框架竞争已经从第一阶段的前端框架之争&#xff08;比如Vue、React、Angular等&#xff09;&#xff0c;过渡到…

BUG分析以及BUG定位

一般来说bug大多数存在于3个模块&#xff1a; 1、前台界面&#xff0c;包括界面的显示&#xff0c;兼容性&#xff0c;数据提交的判断&#xff0c;页面的跳转等等&#xff0c;这些bug基本都是一眼可见的&#xff0c;不太需要定位&#xff0c;当然也不排除一些特殊情况&#xf…

随笔03 考研笔记整理

图源&#xff1a;文心一言 上半年的考研类博文整理&#xff0c;因为真的花费了很多时间才写好&#xff0c;所以设置为仅关注我的伙伴可以查看~&#x1f95d;&#x1f95d; 第1版&#xff1a;整理博文~&#x1f9e9;&#x1f9e9; 第2版&#xff1a;博文链接提前&#xff0c;方…

Vector - CAPL - 诊断模块函数(设置和获取)

目录 CanTpGetRxIdentifier CanTpGetTxIdentifier CanTpSetRxIdentifier CanTpSetTxIdentifier 代码示例 CanTpGetPadding & CanTpSetPadding 代码示例 CanTpGetAcceptOtherMode & CanTpSetAcceptOtherMode 代码示例 对于使用OSEK.dll文件调用发送诊断数据和接…

【element-plus】 table表格每行圆角解决方案 element也通用

系列文章目录 【Vue3ViteTselement-plus】使用tsx实现左侧栏菜单无限层级封装 前言 我们在使用element-plus或element 的table时是否有时UI给到的UI效果是如下面这样的&#xff0c;但是我们翻遍了组件库的文档 调整了很多次样式 发现在 左右侧栏固定的时候 普通的方法是完全…

基于小程序+spring boot流浪动物救助系统-计算机毕设 附源码12783

小程序spring boot流浪动物救助系统 摘 要 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;流浪动物救助系统被用…