最小生成树的Prim算法(待修正版)
// prim.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include<iostream> #include<queue> using namespace std; typedef int Vertex; #define NotAVertex 0 #define INF 65536 #define numOfVertex 4 //定义链表节点//////////////////////////////////// typedef struct TreeNode *Position; struct TreeNode { Vertex vertex; int weight; Position Next; }; //定义邻接表结构///////////////////////////////////// typedef struct adjaceency_list *adjaceency; struct adjaceency_list { int numVertex; //大小 Position* table; //表地址 }; //邻接表初始化函数//////////////////////////////////// adjaceency initAdjaceency_list(int numVertex) { //申请一个邻接表地址,给邻接表赋初值 adjaceency adja = (adjaceency)malloc(sizeof(adjaceency_list)); adja->numVertex = numVertex; if (adja == NULL) cout << "Error"; //申请一个table地址 adja->table = (Position*)malloc(sizeof(Position)*(adja->numVertex + 1)); if (adja->table == NULL) cout << "Error"; //给邻接表每一个表项添加一个链表表头 for (int i = 1; i <= adja->numVertex; i++) { adja->table[i] = (Position)malloc(sizeof(TreeNode)); if (adja->table[i] == NULL) cout << "Error"; else { adja->table[i]->vertex = i; adja->table[i]->weight = 0; //给每个邻接表项的链表头的权重设为0 adja->table[i]->Next = NULL; } } return adja; } //邻接表的插入函数,制定一个顶点per_ver,把邻接的顶点aft_ver插入其后////////////////////////////////// void Insert(adjaceency adja, Vertex per_ver, Vertex aft_ver, int weight) { //申请一个链表节点地址 Position inser = (Position)malloc(sizeof(TreeNode)); if (inser == NULL) cout << "Error"; //从头插入,修改指针 inser->vertex = aft_ver; inser->weight = weight; //从per_ver指向aft_ver的权重 inser->Next = adja->table[per_ver]->Next; adja->table[per_ver]->Next = inser; } //打印邻接表////////////////////////////////////////// void print(adjaceency adja) { cout << "Vertex" << endl; for (int i = 1; i <= adja->numVertex; i++) { Position p = adja->table[i]; while (p != NULL) { cout << p->vertex << '\t'; p = p->Next; } cout << endl; } cout << endl; } //定义顶点结构//////////////////////////////// struct Vertexs { Vertex ver_num; //顶点的标号 int minWeight; //该顶点连接到树上的最小权重 bool inQ; //是否在优先队列Q中 Vertex verFather; //该顶点的父亲 friend bool operator< (Vertexs ver1, Vertexs ver2) //重定义运算符 { return ver1.minWeight> ver2.minWeight; //因为优先队列默认是<,因此若要形成最小堆,用>来重定义< } }; //最小生成树的Prim算法///////////////////////////// void MST_PRIM(adjaceency adja, Vertex start) { //定义顶点数组以及初始化顶点 Vertexs ver[numOfVertex + 1]; for (int i = 1; i <= numOfVertex; i++) { ver[i].minWeight = INF; ver[i].ver_num = i; ver[i].inQ = true; ver[i].verFather = NULL; } ver[start].minWeight = 0; //把所有顶点入优先队列 priority_queue<Vertexs> verPriority; for (int i = 1; i <= numOfVertex; i++) { verPriority.push(ver[i]); } //出队操作 Vertexs verTemp; while (!verPriority.empty()) { //最小权重值的先出队 verTemp = verPriority.top(); verPriority.pop(); verTemp.inQ = false; Position p = adja->table[verTemp.ver_num]->Next; while (p) { if (ver[p->vertex].inQ&&p->weight < ver[p->vertex].minWeight) { ver[p->vertex].minWeight = p->weight; //这部分有问题, ver[p->vertex].verFather = verTemp.ver_num; //这里不能改变优先队列里面的元素 } p = p->Next; } } //打印最小生成树 for (int i = numOfVertex; i >= 1; i--) { cout << ver[i].ver_num << "------" << ver[i].verFather << endl;; } } int main() { //初始化邻接表//////////////////////////////////////// adjaceency adja = initAdjaceency_list(numOfVertex); Insert(adja, 1, 3, 4); Insert(adja, 1, 4, 1); Insert(adja, 1, 2, 2); Insert(adja, 2, 3, 10); Insert(adja, 2, 4, 3); Insert(adja, 2, 1, 2); Insert(adja, 3, 4, 2); Insert(adja, 3, 1, 4); Insert(adja, 3, 2, 10); Insert(adja, 4, 3, 2); Insert(adja, 4, 2, 3); Insert(adja, 4, 1, 1); print(adja); MST_PRIM(adja, 1); while (1); return 0; }