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
原创粉丝点击