文章目录
回顾
我们用这张图来进行算法讲解
初始化
/*
* vex - 存储顶点
* weight - 存储权值
*/
typedef struct Edge {
char vex;
int weight;
}Edge;
/*
* 开辟数组大小得空间,大小具体为 vexNum 的个数
* 同时将 vex 初始化赋值同G->vexs 一样,这里的vex全都是一样的值,等后续进行更新
* weight的值为index行的那一列二维数组的值
* 按总代码来讲,如果传入值为 index= 0, 则 T[i].weight初始化成0, 6, 1, 5, MAX, MAX这一关于顶点“1”的所有边的权值
如果传入值为 index= 1, 则 T[i].weight初始化成6, 0, 5, MAX, 3, MAX,这一关于顶点“2”的所有边的权值,以此类推
*
* 总的来说初始化同时将传入进来的顶点也初始化了
*/
Edge* initEdeg(Graph* G, int index)
{
int i=0;
Edge *T = (Edge*)malloc(sizeof(Edge) * G->vexNum);
for(i=0;i<G->vexNum;i++)
{
T[i].vex = G->vexs[index];
T[i].weight = G->arcs[index][i];
}
return T;
}
寻找最小权值
/*
* 我们规定,如果他的weight为0时,说明他已经访问过了这个节点/或者是他本身了
* 同时不断找到最小值并且逐步开始更新min的值,知道找到这一顶点这一条边的最小权值
*/
int getMinEdge(Edge* edge, Graph* G)
{
int min = MAX;
int i=0;
int index=0;
for(i=0;i<G->vexNum;i++)
{
if(edge[i].weight && edge[i].weight < min)
{
min = edge[i].weight;
index = i;
}
}
return index;
}
算法主体
/*
* 初始化顶点的值,所以我们在循环的时候就要G->vexNum-1。这里减去的就是顶点的值
* 循环获取最小值,同时获取完最小值以后,将该点的权值赋值为0,代表已经寻找过了这个节点了
* 寻找完最小值(最小权值以后)我们就要重新将的内容进行一个更新,同时将他的边/权值替换为寻找到最小值的那个顶点后的那些边,同时小于他的权值都要更新他的vex值,所以这就是为什么他可以有类似于“回归节点再去寻找”的类似方法,他并不会把所有遍历的节点都给存储进去
*/
void prim(Graph* G, int index)
{
int i=0,j=0;
Edge *edge = initEdeg(G,index);
int min = 0;
for(i=0;i<G->vexNum-1;i++)
{
min = getMinEdge(edge,G);
printf("v%c --> v%c, weight = %d\n", edge[min].vex, G -> vexs[min], edge[min].weight);
edge[min].weight = 0;
for(j=0;j<G->vexNum;j++)
{
if(edge[j].weight > G->arcs[min][j] && edge[j].weight)
{
edge[j].weight = G->arcs[min][j];
edge[j].vex = G->vexs[min];
}
}
}
}
总代码
#include <stdio.h>
#include <stdlib.h>
/**
* 图顶点之前不通,那么邻接矩阵的值为MAX
* 如果顶点是自己本身,那么值为0
*/
#define MAX 32767
typedef struct Graph {
char* vexs;
int** arcs;
int vexNum;
int arcNum;
}Graph;
typedef struct Edge {
char vex;
int weight;
}Edge;
/**
* 当edge.weight = 0时,代表顶点加入到U集合中
*/
Edge* initEdeg(Graph* G, int index)
{
int i=0;
Edge *T = (Edge*)malloc(sizeof(Edge) * G->vexNum);
for(i=0;i<G->vexNum;i++)
{
T[i].vex = G->vexs[index];
T[i].weight = G->arcs[index][i];
//printf("T[i].vex->%c, T[i].weight->%d\r\n", T[i].vex,T[i].weight);
}
return T;
}
int getMinEdge(Edge* edge, Graph* G)
{
int min = MAX;
int i=0;
int index=0;
for(i=0;i<G->vexNum;i++)
{
if(edge[i].weight && edge[i].weight < min)
{
min = edge[i].weight;
index = i;
}
}
return index;
}
void prim(Graph* G, int index)
{
int i=0,j=0;
Edge *edge = initEdeg(G,index);
int min = 0;
for(i=0;i<G->vexNum-1;i++)
{
min = getMinEdge(edge,G);
printf("v%c --> v%c, weight = %d\n", edge[min].vex, G -> vexs[min], edge[min].weight);
edge[min].weight = 0;
for(j=0;j<G->vexNum;j++)
{
if(edge[j].weight > G->arcs[min][j] && edge[j].weight)
{
edge[j].weight = G->arcs[min][j];
edge[j].vex = G->vexs[min];
}
}
}
}
Graph* initGraph(int vexNum)
{
int i = 0;
Graph* G = (Graph*)malloc(sizeof(Graph));
G -> vexs = (char*)malloc(sizeof(char) * vexNum);
G -> arcs = (int**)malloc(sizeof(int*) * vexNum);
for (i = 0 ; i < vexNum; i++) {
G -> arcs[i] = (int*)malloc(sizeof(int) * vexNum);
}
G -> vexNum = vexNum;
G -> arcNum = 0;
return G;
}
void createGraph(Graph* G, char* vexs, int* arcs)
{
int i=0,j=0;
for (i = 0 ; i < G -> vexNum; i++)
{
G -> vexs[i] = vexs[i];
for (j = 0; j < G -> vexNum; j++)
{
G -> arcs[i][j] = *(arcs + i * G -> vexNum + j);
if (G -> arcs[i][j] != 0 && G -> arcs[i][j] != MAX)
G -> arcNum ++;
}
}
G -> arcNum /= 2;
}
void DFS(Graph* G, int* visited, int index)
{
int i=0;
printf("%c\t", G -> vexs[index]);
visited[index] = 1;
for (i = 0; i < G ->vexNum; i++)
{
if (G -> arcs[index][i] > 0 && G -> arcs[index][i] != MAX && !visited[i])
{
DFS(G, visited, i);
}
}
}
int main()
{
int i=0;
int arcs[6][6] = {
0, 6, 1, 5, MAX, MAX,
6, 0, 5, MAX, 3, MAX,
1, 5, 0, 5, 6, 4,
5, MAX, 5, 0, MAX, 2,
MAX, 3, 6, MAX, 0, 6,
MAX, MAX, 4, 2, 6, 0
};
Graph* G = initGraph(6);
int* visited = (int*)malloc(sizeof(int) * G -> vexNum);
for (i = 0; i < G -> vexNum; i++)
visited[i] = 0;
createGraph(G, "123456", (int*)arcs);
DFS(G, visited, 0);
printf("\n");
prim(G, 0);
return 0;
}
最后树得出来的样式图
往期回顾
1.【第一章】《线性表与顺序表》
2.【第一章】《单链表》
3.【第一章】《单链表的介绍》
4.【第一章】《单链表的基本操作》
5.【第一章】《单链表循环》
6.【第一章】《双链表》
7.【第一章】《双链表循环》
8.【第二章】《栈》
9.【第二章】《队》
10.【第二章】《字符串暴力匹配》
11.【第二章】《字符串kmp匹配》
12.【第三章】《树的基础概念》
13.【第三章】《二叉树的存储结构》
14.【第三章】《二叉树链式结构及实现1》
15.【第三章】《二叉树链式结构及实现2》
16.【第三章】《二叉树链式结构及实现3》
17.【第三章】《二叉树链式结构及实现4》
18.【第三章】《二叉树链式结构及实现5》
19.【第三章】《中序线索二叉树理论部分》
20.【第三章】《中序线索二叉树代码初始化及创树》
21.【第三章】《中序线索二叉树线索化及总代码》
22【第三章】《先序线索二叉树理论及线索化》
23【第三章】《先序线索二叉树查找及总代码》
24【第三章】《后续线索二叉树线索化理论》
25【第三章】《后续线索二叉树总代码部分》
26【第三章】《二叉排序树基础了解》
27【第三章】《二叉排序树代码部分》
28【第三章】《二叉排序树代码部分》
29【第三章】《平衡二叉树基础概念》
30【第三章】《平衡二叉树的平衡因子》
31【第三章】《平衡二叉树的旋转基础详解》
32【第三章】《平衡二叉树的旋转类型图文详解》
33【第三章】《平衡二叉树的旋转类型总结及总代码》
34【第三章】《哈夫曼树简单了解》
35【第三章】《哈夫曼树的构造方法》
36【第三章】《哈夫曼编码构造及代码》
37【第四章】《图的定义》
38【第四章】《图的基本概念和术语》
39【第四章】《图的存储结构》
40【第四章】《图的遍历之深度优先遍历》
41【第四章】《广度优先遍历BFS》
42【第四章】《图的遍历总代码》
43【第四章】《最小生成树概念》
44【第四章】《最小生成树的应用举例》
45【第四章】《prim算法(普里姆算法)详解》
46【第四章】《prim算法(普里姆算法)详解2》
47【第四章】《prim算法(普里姆算法)详解3》
48【第四章】《prim算法(普里姆算法)讲解汇总》
49【第四章】《prim算法(普里姆算法)代码讲解》