Kruskal最小生成树
来源:互联网 发布:拓普网络怎么样 编辑:程序博客网 时间:2024/06/05 11:32
本代码实现的是Kruskal发实现最小生成树,定义见《算法导论》。使用的文件MapInfo.txt的内容如下:
h 1 g
g 2 f
i 2 c
a 4 b
c 4 f
i 6 g
i 7 h
c 7 d
b 8 c
a 8 h
d 9 e
f 10 e
b 11 h
d 14 f
左边和右边的字符分别代表两个节点,中间的数字表示两个节点所在边的权重。
代码实现如下:
/* * Kruskal方法做最小生成树 * 使用最小堆排序的方法来获取权重最小的边 * 使用单向链表来保存森林中所有树 * Author: StoryMonster *Last Change Date: 2016/7/1 */#include <iostream>#include <stdio.h>#include <stdlib.h>typedef struct MapEdge{ char NodeName1; char NodeName2; int weight;} MapEdge;typedef struct PealNode{ MapEdge *edge; int index; struct PealNode *father; struct PealNode *left; struct PealNode *right;} PealNode;typedef struct MinTree{ MapEdge *edge; //以边为节点包含的内容 struct MinTree *father; struct MinTree *left; struct MinTree *right;} MinTree;typedef struct TreeChain{ MinTree *tree; TreeChain *next;} TreeChain;static void ReadConfigFile(void); //读取文件信息并将信息存入最小堆static bool PutIntoMinPeal(PealNode *, PealNode *); //将堆节点存入最小堆中static void FixMinPeal(PealNode *root); //恢复最小堆的性质static void GetTheMinNode(PealNode *, PealNode *);//获取以第一个参数为根结点的堆中的最小节点,保存在第二个参数中static PealNode *GetMaxIndexNode(PealNode *); //返回下标最大的节点static void BuildTheMinTree(void); //生成最小生成树static void InsertTreeToChain(TreeChain *); //将树插入到链表中static MinTree *GetTheTree(char NodeName); //返回链表中包含名为NodeName的节点的树static bool InThisTree(MinTree *, char NodeName); //判断树中是否有包含名为NodeName的节点的边static void UnionTwoTree(MinTree *tree1, MinTree *tree2, MinTree * NewTree, MapEdge *RootEdge);//合并两棵树static void DeleteNodeFromTreeChain(MinTree *); //删除森林从的一棵树static void CreatTree(MapEdge *); //创建一棵树并将之保存到链表中static void InsertToTree(MinTree *, MapEdge *); //向指定树中插入一个节点static void ShowThisMinTree(MinTree *); //打印最小生成树的信息PealNode *PealRoot = (PealNode *)malloc(sizeof(PealNode));TreeChain *ChainHead = (TreeChain *)malloc(sizeof(TreeChain));int PealNodeCount = 0;int TreeCount = 0;void ShowThisMinTree(MinTree *root){ if(root == NULL) return ; std::cout << (root->edge)->NodeName1<< " "<< (root->edge)->NodeName2 << " "<< (root->edge)->weight << std::endl; ShowThisMinTree(root->left); ShowThisMinTree(root->right);}void BuildTheMinTree(void){ while(PealNodeCount > 0) { PealNode *node = (PealNode *)malloc(sizeof(PealNode)); GetTheMinNode(PealRoot,node); MapEdge *edge = node->edge; MinTree *tree1 = GetTheTree(edge->NodeName1); MinTree *tree2 = GetTheTree(edge->NodeName2); if((tree1 == tree2)&&(tree1 != NULL)) continue; if(tree1 == NULL && tree2 == NULL) CreatTree(edge); if(tree1 != NULL && tree2 == NULL) InsertToTree(tree1,edge); if(tree1 == NULL && tree2 != NULL) InsertToTree(tree2,edge); if(tree1 != NULL && tree2 != NULL) { MinTree *NewTree = (MinTree *)malloc(sizeof(MinTree)); UnionTwoTree(tree1,tree2,NewTree,edge); } }}/* 此处往最小树中插入节点,节点排列与堆类似是最好的,但是若是做成与堆类似的话,用广度搜索的方式是最好的,但是考虑到广度搜索会增加代码量,故而在此处使用这种生成树的方式。当前方式生成的树会是极左的树 */void InsertToTree(MinTree *tree, MapEdge *edge){ MinTree *p = tree; MinTree *p1 = (MinTree *)malloc(sizeof(MinTree)); p1->edge = edge; p1->left = NULL; p1->right = NULL; p1->father = NULL; while(p != NULL) { if(p->left == NULL) { p->left = p1; p1->father = p; break; } else { if(p->right == NULL) { p->right = p1; p1->father = p; break; } } p = p->left; }}void CreatTree(MapEdge *edge){ MinTree *tree = (MinTree *)malloc(sizeof(MinTree)); tree->father = NULL; tree->left = NULL; tree->right = NULL; tree->edge = edge; TreeChain *chain = (TreeChain *)malloc(sizeof(TreeChain)); chain->tree = tree; chain->next = NULL; InsertTreeToChain(chain);}void DeleteNodeFromTreeChain(MinTree *tree){ TreeCount--; TreeChain *p = ChainHead; if(ChainHead->tree == tree) { ChainHead = ChainHead->next; return ; } while((p->next)->tree != tree) p = p->next; TreeChain *p1 = p->next; p->next = p1->next;}void UnionTwoTree(MinTree *tree1, MinTree *tree2, MinTree *NewTree, MapEdge *RootEdge){ NewTree->left = tree1; NewTree->right = tree2; NewTree->father = NULL; tree1->father = NULL; tree2->father = NULL; NewTree->edge = RootEdge; DeleteNodeFromTreeChain(tree1); DeleteNodeFromTreeChain(tree2); TreeChain *chain = (TreeChain *)malloc(sizeof(TreeChain)); chain->tree = NewTree; chain->next = NULL; InsertTreeToChain(chain);}bool InThisTree(MinTree *root,char NodeName){ if(root == NULL) return false; if((root->edge)->NodeName1 == NodeName || (root->edge)->NodeName2 == NodeName) { return true; } else { bool result = InThisTree(root->left, NodeName); if(result == false) result = InThisTree(root->right, NodeName); return result; }}MinTree *GetTheTree(char NodeName){ TreeChain *p = ChainHead; while(p!=NULL) { if(InThisTree(p->tree, NodeName)) { return p->tree; } p = p->next; } return NULL;}void InsertTreeToChain(TreeChain * chain){ TreeCount++; if(ChainHead == NULL) { ChainHead = chain; return ; } TreeChain *p = ChainHead; while(p->next != NULL) p = p->next; p->next = chain;} PealNode *GetMaxIndexNode(PealNode *root){ if(root == NULL) { return NULL; } else { if(root->index == PealNodeCount) { return root; } PealNode *result = GetMaxIndexNode(root->left); if(result == NULL) { return GetMaxIndexNode(root->right); } else return result; }}void GetTheMinNode(PealNode *root, PealNode *MinNode){ MinNode->edge = root->edge; PealNode *p = GetMaxIndexNode(root); PealNodeCount--; if(p == root); else { root->edge = p->edge; if(p == (p->father)->left) { (p->father)->left = NULL; } else (p->father)->right = NULL; p->father = NULL; FixMinPeal(root); } free(p); p = NULL;}void FixMinPeal(PealNode *root){ if(root->left == NULL) return ; else { PealNode *r_left = root->left; if((r_left->edge)->weight < (root->edge)->weight) { MapEdge *edgeTemp = r_left->edge; r_left->edge = root->edge; root->edge = edgeTemp; if(root->father != NULL) FixMinPeal(root->father); } FixMinPeal(r_left); } if(root->right == NULL) return ; else { PealNode *r_right = root->right; if((r_right->edge)->weight < (root->edge)->weight) { MapEdge *edgeTemp = r_right->edge; r_right->edge = root->edge; root->edge = edgeTemp; if(root->father != NULL) FixMinPeal(root->father); } FixMinPeal(r_right); }}bool PutIntoMinPeal(PealNode * root, PealNode *node){ if(PealRoot == NULL) { PealRoot = node; return true; } if(root == NULL) { return false; } if((root->index)*2 == (node->index)) { root->left = node; node->father = root; return true; } if((root->index)*2+1 == node->index) { root->right = node; node->father = root; return true; } if(PutIntoMinPeal(root->left,node)== false) { return PutIntoMinPeal(root->right,node); } else return true;}void ReadConfigFile(void){ FILE *fp = fopen("MapInfo.txt","rb"); if(!fp) { std::cout << "Open MapInfo.txt failed!" << std::endl; fp = NULL; return ; } int index = 1; while(1) { MapEdge *edge = (MapEdge *)malloc(sizeof(MapEdge)); int n = fscanf(fp,"%c %d %c\n",&edge->NodeName1,&edge->weight,&edge->NodeName2); if(n < 1) { free(edge); edge = NULL; break; } // std::cout << edge->NodeName1<<edge->weight<<edge->NodeName2<<"**"<<std::endl; PealNode *node = (PealNode *)malloc(sizeof(PealNode)); node->edge = edge; node->index = index++; node->father= NULL; node->left = NULL; node->right = NULL; PutIntoMinPeal(PealRoot, node); PealNodeCount++; } fclose(fp); fp = NULL;}int main(){ PealRoot = NULL; ChainHead = NULL; ReadConfigFile(); FixMinPeal(PealRoot); BuildTheMinTree(); ShowThisMinTree(ChainHead->tree); return 0;}
0 0
- 最小生成树Kruskal
- kruskal 最小生成树
- 最小生成树 kruskal
- kruskal 最小生成树
- 最小生成树-Kruskal
- 最小生成树kruskal
- 最小生成树---Kruskal
- Kruskal 最小生成树
- 最小生成树 Kruskal
- 最小生成树--Kruskal
- Kruskal 最小生成树
- 最小生成树-Kruskal
- 最小生成树Kruskal
- Kruskal 最小生成树
- kruskal最小生成树
- 最小生成树-Kruskal
- 最小生成树 kruskal()
- 最小生成树 - Kruskal()
- XML
- 指针_引用_内存管理new_delete
- kafka基本简介
- Git:Git重置(git reset)
- 一个简单的数据质量检查和汇总工具——Profiler
- Kruskal最小生成树
- iOS开发UI篇—程序启动原理和UIApplication
- 07.10C
- 英里 英尺 英寸的换算
- cmd命令
- Android多媒体之MediaPlayerService
- 实现一个可以在队列满时,将溢出的部分缓存入文件,待空闲时取出的队列
- 使用HBuilder开发移动APP:开发环境准备 (转)
- 1 1 2 3 5 8 13 21 34