【数据结构】图的应用

包含:最小生成树(Prim算法,Kruskal算法),最短路径(Dijkstra算法,Floyd算法)

最小生成树

Prim算法

无符号整型的int最大的数值是65535 , 而普通的int占32位的时候,最大可以赋值为:21 4748 3647,约为20亿,2*10^9。

void Prim(MGraph G){
	int adjvex[Maxvex];	 // adjvex代表此时访问这个点是从那个点来的。0代表访问结点已经访问过了 // 
	int lowcost[Maxvex];//	lowcost是访问当前结点的数值和距离。0代表已经加入生成树,无穷代表无关,有数据代表与当前 i 的距离  
	
	lowcost[0] = 0;//最初的时候 
	adjvex[0] = 0; 
	
	//初始化操作
	for(int i = 1 ; i < G.vexnum ; i ++){	/ 
		lowcost[i] = G.arc[0][i];	//这个代表的是从初始结点开始到各个结点的路径长 
		adjvex[i] = 0; // 保存邻接顶点下标 
	}
	
	//Core
	for(int i = 0 ; i < G.vexnum ; i ++){
		int min = 65535; // 无符号整型的最大值为65535
		int k = 0;
		
		//找顶点 
		for(int j = 0 ; j < G.vexnum ; j ++){
			if(lowcost[j] != 0 && lowcost[j] < min){	//尚未加入生成树,并且是当前最短的 
				min = lowcost[j];	//	距离当前 i 的最短的路径 
				k = j;	//	最短路径到达的位置 
			}
		}
		printf("%d --> %d\n" , adjvex[k] , k);
		lowcost[k] = 0; //标记为访问过 
		
		//更新表数据 
		for(int j = 0 ; j < G.vexnum ; j ++){
			if(lowcost[j] != 0 && G.arc[k][j] < lowcost[j]){	//尚未加入生成树 , 并且可以更新为更短的 
				lowcost[j] = G.arc[k][j];	 
				adjvex[j] = k;	// 那些修改的点的下一坐标都改成从当前 k 开始 
			}
		} 
	} 
}

Kruskal算法

利用边

typedef struct{
	int a , b;
	int weight;
}Edge;	//边结构体

//并查集:并 
int Find(int *parent , int x){	//指针 
	while(parent[x] >= 0){
		x = parent[x];
	} 
	return x;
} 

Edge edges[MaxVex];
int parent[MaxVex];

void Kruskal(MGraph G){
	
	sort(edges);//	堆排序:权值递增排序 
	
	//并查集:初始化 
	for(int i = 0 ; i < G.vexnum ; i ++){
		parent[i] = -1;  
	}
	
	//搜索所有的边// 
	for(int i = 0 ; i < G.arcnum ; i ++){
		n = Find(parent , edges[i].a);
		m = Find(parent , edges[i].b);
		if(n != m){	//当边的结点不在一个圈子内,合并起来 
			parent[n] = m;	//并查集:并 
			printf("%d --> %d" , edges[i].a , edges[i].b);
		} 
	}
}

 

最短路径

Dijkstra算法

#define INF 65535

/*
 * v代表当前访问开始的结点
 * path[]当前结点的来源
 */ 

void Dijkstra(MGraph G , int v , int path[] , int dist[]){
	bool vis[Maxsize];	//那些被访问最短路径,访问过的设置为true , 未访问的false
	int u;
	
	//初始化记录表 
	for(int i = 0 ; i < G.vexnum ; i ++){
		dist[i] = G.edge[v][i];	//	到初始的结点的距离 
		vis[i] = false;	//	所有的结点都是尚未访问的 
		if(G.edge[v][i] < INF)
			path[i] = v;	//	与初始结点联通的数据写入path 
		else
			path[i] = -1
	} 
	vis[v] = true;	//	根结点已经访问过 
	path[v] = -1;
	
	//核心
	for(int i = 0 ; i < G.vexnum ; i ++){
		int min = INF;
		
		//核心:找最小值 
		for(int j = 0 ; j < G.vexnum ; j ++){
			if(vis[j] == false && dist[j] < min){	//找未访问过的结点中的最小值 
				min = dist[j];
				u = j;
			}
		}
		
		//核心:更新数组 
		vis[u] = true;	//	该结点访问过 
		for(int j = 0 ; j < G.vexnum ; j ++){
			if(vis[j] == false && dist[u] + G.edges[u][j] < dist[j]){	//	找那些能与当前结点 
				dist[j] = dist[j] + G.edges[u][j];
				path[j] = u;	//	更新,代表这条路径的来源 
			}
		}
	} 	
}

Floyd算法

void Floyd(MGraph G , int Path[][]){
	int A[Maxsize][Maxsize];
	
	//初始化 
	for(int i = 0 ; i < G.vexnums ; i ++){
		for(int j = 0 ; j < G.vexnums ; j ++){
			A[i][j] = G.Edges[i][j];
			Path[i][j] = -1; 
		}
	}
	
	//更新数值 
	for(int k = 0 ; k < G.vexnums; k ++){
		for(int i = 0 ; i < G.vexnums ; i ++){
			for(int j = 0 ; j < G.vexnums ; j ++){
				if(A[i][j] > A[i][k] + A[k][j]){	//	从 i 到 k 到 j 的距离 < i 到 j 的距离 
					A[i][j] = A[i][k] + A[k][j];	
					Path[i][j] = k;	//	中间穿插的路径 
				}
			}
		}
	}
}

 

拓扑排序

若是三角矩阵,有拓扑序列。形不成环。

bool TopologicalSort(Graph G){
	stack<int> s;	
	
	//找到一个入度为 0 的结点 
	for(int i = 0 ; i < G.vexnum ; i ++){
		if(indrgee[i] == 0){
			s.push(i);	
		} 
	}
	
	int count = 0;	//	记录当前已经输出的顶点数 
	while(!s.empty()){
		int k = s.top();
		s.pop();
		count ++; 
		printf("%d " , G.adlist[k]);
		for(ArcNode *p = G.vertices[i].firstarc ; p ; p = p->nextarc){	//遍历这个结点的孩子链表 
			v = p->adjvex;
			if(!( --indegree[v]))	//	如果它的结点的数值减到 0 了 入栈 
				s.push(v);
		}
	}
	if(count < G.vexnum)	//	输出的结点数比原来的少,则存在回路	
		return false;	//	有环的话,入度结点不肯能有1 -> 栈空了 -> count的个数不如原有的多 
	else
		return true;
} 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值