当前位置: 首页 >> 程序设计 >> 数据结构和算法 >> 并查集的最小生成树算法
 

并查集的最小生成树算法

作者:      来源:zz     发表时间:2007-04-04     浏览次数:      字号:    

摘要
   树结构实现得并查集数据结构,用来求无向图的最小生成树。
   基本操作:
   0. 根据弧的权值对图的所有弧进行排序,设弧的数目为e, 使用归并排序,排序复杂度 log(eloge)
   1. 设无向图共有N个结点,初始化N棵树,树的根代表图的一个结点。
   2. 从小到大考察每一条弧,如果弧的两个结点在不同一棵树上,则合并这两树。否则跳过这条弧,考察下一条弧。
      合并的原则是将“小树“(树的深度小)合并到“大树“ , 复杂度 O(1)
      判断两个结点是否在同一颗树上需要从某个结点向上遍历至树根,因为只有树根存储集合号。把这个操作称为 Union_Find (int nodeIndex);
      在便利的同时,将每一个便利过的结点直接指向树根,这样可以减少下一次 Union_Find () 的时间。这样Union_Find的复杂度可以从O(logn)降低到O(G(n)); 做此操作带来的附加难度是需要在Union_Find后更新树的高度。

关键字
   并查集,树结构,最小生成树

联系作者:
   如果发现任何的bug,请发信到yaming.kuang@gmail.com;

文件结构
graph.h          实现图的头文件, 定义图的数据结构 - 邻接表;
graph.cpp        定义图构造函数,对弧的排序函数(归并排序)。
MiniSpanTree_Kruskal_TreeImpl.cpp  实现Union_Find等操作,文件内对每个函数的注释已经很清楚了。
MiniSpanTree_Kruskal_TreeImpl.h    实现树结构时显得并查集的树集结构,文件内注释已经很清楚了。
main.cpp         测试函数

/******************************************************************************/
/********************************* file: graph.h ******************************/
/******************************************************************************/

#ifndef __GRAPHH__
#define __GRAPHH__

const int  MAX_VERTEX_NUM = 30;
typedef enum { DG, AG } GraphKind;  // { Digraph, Undigraph}
/*
 * Adjacency List.
 * */
typedef int ArcInfoType ;            // The weight of arc
typedef struct ArcNode{             // Arc Node
    int             adjvex;         // The Node pointed by this arc.
    struct ArcNode *nextarc;        // Point to next arc.
    ArcInfoType     weight;           // Info about this arc. e.g. weight of this arc.
}ArcNode;

typedef int VertexType;            // The index of Vertex Node.
typedef struct VNode{               // Vertex Node
    VertexType      data;           // Info of node
    ArcNode        *firstarc;       // Point to the first arc originates from this Vertex.
}VNode, AdjList[MAX_VERTEX_NUM];

typedef struct{
    AdjList     vertices;           //
    int         vexnum, arcnum;     // Number of vertex and arc.
    GraphKind   kind;               // The kind of this graph.
}ALGraph;

typedef struct ArcGraph{
    int             VStart;
    int             VEnd;     
    ArcInfoType     weight;           // Info about this arc.
}ArcGraph;

ALGraph* CreateALGraph ();
ArcGraph* GetArcsToArray (ALGraph *graph);
void SortArcs (ArcGraph *arcGraph, int numArcs );
void MergeSort_ArcGraph (ArcGraph *E, int first, int last);
void Merge_ArcGraph (ArcGraph *E, int first, int mid, int last);
void PrintArcGraph (ArcGraph *arcGraph, int numArcs);

#endif

/*************************  end of file: graph.h ******************************/


/******************************************************************************/
/********************************* file: graph.cpp ******************************/
/******************************************************************************/

#include <iostream>
#include "graph.h"
using namespace std;

/*
 * Func Name    :  CreateALGraph   
 * Desc         :  Create an Adjacency List Graph.
 * Input        :   
 *      - graph    
 * Output       :   
 *      -
 * Return Value :  None
 * Remarks      :  None
 * */
ALGraph* CreateALGraph (){
     cout << "CreateALGraph" << endl;
     ALGraph *graph = new ALGraph;
     graph->vexnum = 8;   
     graph->arcnum = 17;
     graph->kind   = AG;

     // Create Adjacency List for node 1
     ArcNode **pArc = &(graph->vertices[0].firstarc);
     *pArc = new ArcNode;
     (*pArc)->adjvex = 1;  // 1->2
     (*pArc)->weight = 6;

     pArc = &((*pArc)->nextarc);
     *pArc = new ArcNode;
     (*pArc)->adjvex = 2;  // 1->3
     (*pArc)->weight = 1;

     pArc = &((*pArc)->nextarc);
     *pArc = new ArcNode;
     (*pArc)->adjvex = 3;  // 1->4
     (*pArc)->weight = 5;

     pArc = &((*pArc)->nextarc);
     *pArc = new ArcNode;
     (*pArc)->adjvex = 7;  // 1->8
     (*pArc)->weight = 9;

     (*pArc)->nextarc = NULL;

     // Create Adjacency List for node 2
     pArc = &(graph->vertices[1].firstarc);
     *pArc = new ArcNode;
     (*pArc)->adjvex = 0;  // 2->1
     (*pArc)->weight = 6;
    
     pArc = &((*pArc)->nextarc);
     *pArc = new ArcNode;
     (*pArc)->adjvex = 2;  // 2->3
     (*pArc)->weight = 5;

     pArc = &((*pArc)->nextarc);
     *pArc = new ArcNode;
     (*pArc)->adjvex = 4;  // 2->5
     (*pArc)->weight = 3;

     pArc = &((*pArc)->nextarc);
     *pArc = new ArcNode;
     (*pArc)->adjvex = 7;  // 2->8
     (*pArc)->weight = 6;

     (*pArc)->nextarc = NULL;

     // Create Adjacency List for node 3
     pArc = &(graph->vertices[2].firstarc);
     *pArc = new ArcNode;
     (*pArc)->adjvex = 0;  // 3->1
     (*pArc)->weight = 1;

     pArc = &((*pArc)->nextarc);
     *pArc = new ArcNode;
     (*pArc)->adjvex = 1;  // 3->2
     (*pArc)->weight = 5;

     pArc = &((*pArc)->nextarc);
     *pArc = new ArcNode;
     (*pArc)->adjvex = 3;  // 3->4
     (*pArc)->weight = 5;
    
     pArc = &((*pArc)->nextarc);
     *pArc = new ArcNode;
     (*pArc)->adjvex = 4;  // 3->5
     (*pArc)->weight = 6;
    
     pArc = &((*pArc)->nextarc);
     *pArc = new ArcNode;
     (*pArc)->adjvex = 5;  // 3->6
     (*pArc)->weight = 4;

     (*pArc)->nextarc = NULL;
    
     // Create Adjacency List for node 4
     pArc = &(graph->vertices[3].firstarc);
     *pArc = new ArcNode;
     (*pArc)->adjvex = 0;  // 4->1
     (*pArc)->weight = 5;

     pArc = &((*pArc)->nextarc);
     *pArc = new ArcNode;
     (*pArc)->adjvex = 2;  // 4->3
     (*pArc)->weight = 5;

     pArc = &((*pArc)->nextarc);
     *pArc = new ArcNode;
     (*pArc)->adjvex = 5;  // 4->6
     (*pArc)->weight = 2;

     pArc = &((*pArc)->nextarc);
     *pArc = new ArcNode;
     (*pArc)->adjvex = 6;  // 4->7
     (*pArc)->weight = 8;

     pArc = &((*pArc)->nextarc);
     *pArc = new ArcNode;
     (*pArc)->adjvex = 7;  // 4->8
     (*pArc)->weight = 5;

     (*pArc)->nextarc = NULL;

     // Create Adjacency List for node 5
     pArc = &(graph->vertices[4].firstarc);
     *pArc = new ArcNode;
     (*pArc)->adjvex = 1;  // 5->2
     (*pArc)->weight = 3;

     pArc = &((*pArc)->nextarc);
     *pArc = new ArcNode;
     (*pArc)->adjvex = 2;  // 5->3
     (*pArc)->weight = 6;

     pArc = &((*pArc)->nextarc);
     *pArc = new ArcNode;
     (*pArc)->adjvex = 5;  // 5->6
     (*pArc)->weight = 6;
    
     pArc = &((*pArc)->nextarc);
     *pArc = new ArcNode;
     (*pArc)->adjvex = 6;  // 5->7
     (*pArc)->weight = 6;

     (*pArc)->nextarc = NULL;
   
     // Create Adjacency List for node 6
     pArc = &(graph->vertices[5].firstarc);
     *pArc = new ArcNode;
     (*pArc)->adjvex = 2;  // 6->3
     (*pArc)->weight = 4;

     pArc = &((*pArc)->nextarc);
     *pArc = new ArcNode;
     (*pArc)->adjvex = 3;  // 6->4
     (*pArc)->weight = 2;

     pArc = &((*pArc)->nextarc);
     *pArc = new ArcNode;
     (*pArc)->adjvex = 4;  // 6->5
     (*pArc)->weight = 6;
    
     pArc = &((*pArc)->nextarc);
     *pArc = new ArcNode;
     (*pArc)->adjvex = 6;  // 6->7
     (*pArc)->weight = 10;

     (*pArc)->nextarc = NULL;
   
     // Create Adjacency List for node 7
     pArc = &(graph->vertices[6].firstarc);
     *pArc = new ArcNode;
     (*pArc)->adjvex = 3;  // 7->4
     (*pArc)->weight = 8;

     pArc = &((*pArc)->nextarc);
     *pArc = new ArcNode;
     (*pArc)->adjvex = 4;  // 7->5
     (*pArc)->weight = 3;

     pArc = &((*pArc)->nextarc);
     *pArc = new ArcNode;
     (*pArc)->adjvex = 5;  // 7->6
     (*pArc)->weight = 10;

     pArc = &((*pArc)->nextarc);
     *pArc = new ArcNode;
     (*pArc)->adjvex = 7;  // 7->8
     (*pArc)->weight = 4;

     (*pArc)->nextarc = NULL;

     // Create Adjacency List for node 8
     pArc = &(graph->vertices[7].firstarc);
     *pArc = new ArcNode;
     (*pArc)->adjvex = 0;  // 8->1
     (*pArc)->weight = 9;

     pArc = &((*pArc)->nextarc);
     *pArc = new ArcNode;
     (*pArc)->adjvex = 1;  // 8->2
     (*pArc)->weight = 6;

     pArc = &((*pArc)->nextarc);
     *pArc = new ArcNode;
     (*pArc)->adjvex = 3;  // 8->4
     (*pArc)->weight = 5;

     pArc = &((*pArc)->nextarc);
     *pArc = new ArcNode;
     (*pArc)->adjvex = 6;  // 8->7
     (*pArc)->weight = 4;

     (*pArc)->nextarc = NULL;
     return graph;
}

/*
 * Func Name    :  GetArcsToArray
 * Desc         :  
 *      Retrieve all the arcs in graph.
 *      arcGraph is an unsorted array. SortArcs will be called to sort the arcs by weight.
 * Input        :  
 *      - graph     The graph that we want to retrieve arcs from.
 * Output       :  
 *      -
 * Return Value :  The allocated array ArcGraph that has arcs copied from graph.
 * Remarks      :  None
 * */
ArcGraph* GetArcsToArray (ALGraph *graph){
    cout << "GetArcsToArray" << endl;
    int numArcs = graph->arcnum;
    int i,j;
    ArcGraph *arcGraph = new ArcGraph[numArcs];

    for (i = 0, j = 0; i < graph->vexnum && j < numArcs; i++){
        ArcNode *pArcNode = graph->vertices[i].firstarc;
        while(pArcNode)
        {
            if (pArcNode->adjvex > i)
            {
               arcGraph[j].VStart = i;
               arcGraph[j].VEnd   = pArcNode->adjvex;
               arcGraph[j].weight = pArcNode->weight;
               j++;
            }
            pArcNode = pArcNode->nextarc;
        }
    }

    PrintArcGraph (arcGraph, numArcs);
    return arcGraph;
}


/*
 * Func Name    :  SortArcs 
 * Desc         :  
 *      Sort the arcs by weight.
 *      arcGraph is sorted for those application who want to loop arcs by weight.
 *      The complexity should be less than O(nlogn);
 * Input        :  
 *      - arcGraph  The array that has unsorted arcs. 
 *      - numArcs   The number of arcs.
 * Output       :  
 *      - arcGraph  The sorted array.
 * Return Value :  None
 * Remarkg      :  None
 * */
void SortArcs ( ArcGraph *arcGraph, int numArcs ){
    // Use classic sorting algrithm to sort arcs.
    MergeSort_ArcGraph (arcGraph, 0, numArcs-1);
    cout << "After Merge Sort for arcs with weight:"<< endl;
    PrintArcGraph (arcGraph, numArcs);
}

void MergeSort_ArcGraph (ArcGraph *E, int first, int last)
{
   if (first < last)
   {
      int mid = ( first + last )/2;
      MergeSort_ArcGraph (E, first, mid);    // MergeSort E form E[first] to E[mid];
      MergeSort_ArcGraph (E, mid+1, last);   // MergeSort E from E[mid+1] to E[last];
      // Merge the sorted sub sequence E[first]...E[mid] and E[mid+1]...E[last] into a whole sequenced array E;
      Merge_ArcGraph (E, first, mid, last); 
   }
   return;

}

void Merge_ArcGraph (ArcGraph *E, int first, int mid, int last)
{
   // Merge the sorted sub sequence E[first]...E[mid] and E[mid+1]...E[last] into array E;
   ArcGraph * pE = 0;
   int i, j, k;
   pE = new ArcGraph[last - first + 1];

   for (i = first, j = mid+1, k = 0; (i <= mid) && (j <= last); )
   {
       if (E[i].weight < E[j].weight)
           pE[k++] = E[i++];
       else
           pE[k++] = E[j++];
   }
  
   if ( i > mid )
   {
       if ( j <= last )
        for ( ; j <= last ; k++, j++)
            pE[k] = E[j];
   }
   else if ( j > last )
   {
       if ( i <= mid )
           for ( ; i <= mid; k++, i++ )
               pE[k] = E[i];
   }
   for ( i = first, k = 0; i <= last; i++,k++ )
       E[i] = pE[k];

   delete []pE;
   return;
}

void PrintArcGraph (ArcGraph *arcGraph, int numArcs)
{
    int i;
    for (i = 0; i < numArcs; i++)
    {
        cout << "arcGraph["<<i<<"]: VStart: "<<arcGraph[i].VStart<<", VEnd: "<< arcGraph[i].VEnd<<", weight: "<< arcGraph[i].weight<< endl;  
    }

    return;
}
/************************** end of file: graph.cpp *****************************/

/*******************************************************************************/
/***************** file: MiniSpanTree_Kruskal_TreeImpl.h ***********************/
/*******************************************************************************/
#ifndef __MINISPANTREE_KRUSKAL_TREEIMPL_H___
#define __MINISPANTREE_KRUSKAL_TREEIMPL_H___

#include "graph.h"

/* **************************************************************************
 *
 *           Dynamic Set Structure - Tree Implementation
 *
 *            Index: 0   1   2   ...  
 *           ________________________   Data - data, parent, setID,numChilds, memCtrl, height.
 *          | Data | P | C1 | C2 | ^ |  parChildrenArray: P   - Pointer to Parent Node.
 *          |______|___|____|____|___|                    C1  - Pointer to 1st Child
 *                       /      \                         C2  - Pointer to 2nd Child
 *                     /          \                       C3  - NULL. End of child.
 *                   /              \   The size of parChildrenArray is increased dynamically. 
 *                 /                  \ This is to same memery and enhance memery allocation performence.
 *   _________________________     __________________
 *  | data | P | C1 | C2 | ^ |    |data| P | C1 | ^ |
 *  |______|___|____|____|___|    |____|___|____|___|
 *           ...       ...                    ...                   
 *         ...           ...                    ...
 *       ...               ...                     ...
 *
 *
 * **************************************************************************/

const int MAX_TREE_SIZE   = 1000;
const int INIT_TREE_SIZE  = 1;
typedef int TElemType;
typedef struct PTNode{
    TElemType       data;
    int             parent;             // Index of parent node.
    unsigned int    setID;              // only valid if this is root
    int             numChilds;
    int             memCtrl;            // Memery Control;
    int             height;             // The height of this tree. Consider this node as root node.
    struct PTNode **parChildrenArray;   // pointer array.
}PTNode;

typedef int TDynSetElemType;
typedef struct TDynamicSetElem{
    TDynSetElemType  *data;
    PTNode           *node;      // The node of this elem.
}TDynamicSetElem;

typedef int TDynamicSetDataType;
typedef struct TDynamicSet{
    TDynamicSetDataType    *data;
    PTNode                 *root;
}TDynamicSet;

typedef struct TDynamicSetCP{
    TDynamicSetElem        *allSetsElemArray;
    unsigned int            numAllSetsElems;
    TDynamicSet            *sets;
    unsigned int            numSets;
}TDynamicSetCP;

/******************************************************************************/

TDynamicSetCP* CreateTDynSetsCP (ALGraph *graph);
TDynamicSetCP* MiniSpanTree_Kruskal_Tree (ALGraph *grapha);
void InitTDynamicSets (TDynamicSetCP *dynSetsCP, int numSets);
void TMergeSet (TDynamicSetCP *dynSetsCP, ArcGraph *arcGraph, int curArc);
void TDoMergeSet (TDynamicSetCP *dynSetsCP, int setID1, int setID2);
int  Union_Find (TDynamicSetCP *dynSetsCP, int elemIndex);
void AddChildToNode (PTNode *parent, PTNode *child);
void UpdateTreeHeight (PTNode *oldParent, PTNode *delNode);
#endif

/************* end of file: MiniSpanTree_Kruskal_TreeImpl.h ********************/

/*******************************************************************************/
/************ file: MiniSpanTree_Kruskal_TreeImpl.cpp **************************/
/*******************************************************************************/
#include <iostream>
#include "MiniSpanTree_Kruskal_TreeImpl.h"
#include "graph.h"
using namespace std;

typedef PTNode *PPTNode;

TDynamicSetCP* MiniSpanTree_Kruskal_Tree (ALGraph *graph)
{
    ArcGraph *arcGraph;
    arcGraph = GetArcsToArray (graph);   // Memery allocated in GetArcsToArray;
    SortArcs (arcGraph, graph->arcnum);  // Sort the arcs and store it in arcGraph

    TDynamicSetCP *dynSetsCP;             // The Dynamic Set Control Point
    dynSetsCP = CreateTDynSetsCP (graph);
    // Init all the dynamic sets.
    InitTDynamicSets (dynSetsCP, graph->vexnum);
   
    int curArc;
    for (curArc = 0; curArc < graph->arcnum && dynSetsCP->numSets > 1; curArc++)
    {
        TMergeSet (dynSetsCP, arcGraph, curArc);
    }
    return dynSetsCP;
}

void TMergeSet (TDynamicSetCP *dynSetsCP, ArcGraph *arcGraph, int curArc)
{
    int elemIndex1 = arcGraph[curArc].VStart;
    int elemIndex2 = arcGraph[curArc].VEnd;
    int setID1, setID2;
   
    setID1 = Union_Find (dynSetsCP, elemIndex1);
    setID2 = Union_Find (dynSetsCP, elemIndex2);

    // Check if it really need to merge.
    if ( setID1 != setID2 )
    {
        TDoMergeSet (dynSetsCP, setID1, setID2);
        cout<< "arc: "<< elemIndex1 + 1 <<" <-> "<<elemIndex2 + 1<<" Added. "
            << "Arc Weight: "<<arcGraph[curArc].weight<<endl;
    }
    return;
}

/*
 * Func Name    :  Union_Find  
 * Desc         : 
 *                 O(h) = O(log n) ;  h is height of tree,
 *                 When loop from bottom to root node, we could let each node point directly to root.
 *                 This will reduce the Uion_Find complexity for other nodes.
 * Input        :  
 *      -
 * Output       :  
 *      -
 * Return Value :  
 * Remarks      :  
 * */
int Union_Find (TDynamicSetCP *dynSetsCP, int elemIndex)
{
    int setID;
    PTNode *pnode = dynSetsCP->allSetsElemArray[elemIndex].node;
    while (pnode->parChildrenArray[0])
    {
        pnode = pnode->parChildrenArray[0];
    }
    setID = pnode->setID;

    /* Support optimization of Union_Find */
    PTNode *root = pnode;
    pnode = dynSetsCP->allSetsElemArray[elemIndex].node;
    while (pnode->parChildrenArray[0])
    {
        PTNode *oldParent = pnode->parChildrenArray[0];
        AddChildToNode (root, pnode); // Add pnode as child of root. 
       
        // pnode is the deleted node, update oldParent child and height.
        UpdateTreeHeight (oldParent, pnode);
        pnode = oldParent;     // Go on
    }

    return setID;
}

/*
 *  Update the oldParent->parChildrenArray since delNode is deleted.
 *  1) If delNode is in index i, then move index i+1,...,numChilds forward, and decrease numChilds by 1.
 *  2) Update the height of oldParent if the deleted node is the highest node.
 * */
void UpdateTreeHeight (PTNode *oldParent, PTNode *delNode)
{
    if ( oldParent == delNode->parChildrenArray[0] )
    {
        /* oldParent is still delNode's parent,
         * AddChildToNode didn't actually remove delNode from oldParent to new parent.
         * so do not need to do anything. */
        return;
    }
   
    // Update children list and Height.
    int i,j;
    int numChilds = oldParent->numChilds;
    int maxHeightOfChildren = 0;   // Record the max height of other children.
    /* The height of the deleted one.
     * The */
    int delNodeHeight = delNode->height;
    for (i = 1; i <= numChilds; i++)
    {
        int height = oldParent->parChildrenArray[i]->height;
        if (oldParent->parChildrenArray[i] != delNode)
        {
            if (height > maxHeightOfChildren)
                maxHeightOfChildren = height;
        }
        else  // oldParent->parChildrenArray[i] == delNode
        {
            for (j = i; j < numChilds; j++)
            {
                int height = oldParent->parChildrenArray[j]->height;
                oldParent->parChildrenArray[j] = oldParent->parChildrenArray[j+1];
                if (height > maxHeightOfChildren)
                    maxHeightOfChildren = height;
            }
            oldParent->parChildrenArray[numChilds] = NULL;
            oldParent->numChilds--;
            break;
        }
    }
   
    /* Update the height of oldParent if the deleted node is the heighest child.*/
    if (maxHeightOfChildren < delNodeHeight)
        oldParent->height = maxHeightOfChildren;
}

/*
 * 1. Add child to parent.
 *    Increase parent->parChildrenArray if needed.
 * 2. Change child->parChildrenArray[0] to new parent.
 * */
void AddChildToNode (PTNode *parent, PTNode *child)
{
    if (parent == child->parChildrenArray[0])
    {
        /* child is already child of parent
         * Do need to do anything.
         * */
        return;
    }
    PTNode *oldParent = child->parChildrenArray[0];
    parent->numChilds += 1;
    int numChilds = parent->numChilds;
   
    /* Memery Optimization */
    if ( numChilds > parent->memCtrl )
    {
        if (numChilds > MAX_TREE_SIZE )
        {
            cout <<"Tree size over load, MAX_TREE_SIZ : "<<MAX_TREE_SIZE<<endl;
            exit (1);
        }
        if ( 2 * parent->memCtrl <  MAX_TREE_SIZE)
        {
            /* Realloc memery by 2 times. */
            parent->parChildrenArray = (PTNode **) realloc (parent->parChildrenArray, 2 * parent->memCtrl);
            parent->memCtrl *= 2;
        }
        else
        {
            parent->parChildrenArray = (PTNode **) realloc (parent->parChildrenArray, MAX_TREE_SIZE);
            parent->memCtrl = MAX_TREE_SIZE;
        }
    }
    /* End of Memery optimization */

    /* Add this child to this tree.
     * the i'th child will be put to index i. Because index 0 is parent.
     * * */
    parent->parChildrenArray[numChilds] = child;
    /* parent is now the new parent of node child */
    child->parChildrenArray[child->parent] = parent;
}

void TDoMergeSet (TDynamicSetCP *dynSetsCP, int setID1, int setID2)
{
    // Merge two sets.
    PTNode *pSmallSetRoot;
    unsigned int height1 = dynSetsCP->sets[setID1].root->height;
    unsigned int height2 = dynSetsCP->sets[setID2].root->height;
    unsigned int LargeSetID;
   
    /* Move from 'small' tree to 'big' tree
     * The height only need to increase by 1 if the two trees have same height.
     * */
    if (height1 >= height2)
    {
        pSmallSetRoot = dynSetsCP->sets[setID2].root;
        LargeSetID = setID1;
       
        if (height1 = height2)
            dynSetsCP->sets[setID1].root->height += 1;
    }
    else
    {
        pSmallSetRoot = dynSetsCP->sets[setID1].root;
        LargeSetID = setID2;
    }

    /* Add pSmallSetRoot to LargeSetID root */
    AddChildToNode (dynSetsCP->sets[LargeSetID].root, pSmallSetRoot);
}

TDynamicSetCP* CreateTDynSetsCP (ALGraph *graph)
{
    TDynamicSetCP *dynSetsCP = new TDynamicSetCP;
    dynSetsCP->sets = new TDynamicSet[graph->vexnum];
    dynSetsCP->allSetsElemArray = new TDynamicSetElem[graph->vexnum];
   
    return dynSetsCP;
}

void InitTDynamicSets (TDynamicSetCP *dynSetsCP, int numSets)
{
    int i,j;
    dynSetsCP->numSets = numSets;
    dynSetsCP->numAllSetsElems = numSets;
    for (i = 0; i < numSets; i++)
    {
        dynSetsCP->allSetsElemArray[i].data = NULL;
        dynSetsCP->allSetsElemArray[i].node = new PTNode;
        dynSetsCP->allSetsElemArray[i].node->setID = i;
        dynSetsCP->allSetsElemArray[i].node->parent = 0;       // The index of parent is always 0.
        dynSetsCP->allSetsElemArray[i].node->numChilds = 0;
      
        dynSetsCP->allSetsElemArray[i].node->parChildrenArray =
            (PTNode**) new PPTNode[INIT_TREE_SIZE + 1]; // Parent + children

        dynSetsCP->allSetsElemArray[i].node->memCtrl = INIT_TREE_SIZE;
        for ( j = 0; j < dynSetsCP->allSetsElemArray[i].node->numChilds+ 1; j++)
            dynSetsCP->allSetsElemArray[i].node->parChildrenArray[j] = NULL;
      
        //It is root, no parent. 
        dynSetsCP->allSetsElemArray[i].node->parChildrenArray[dynSetsCP->allSetsElemArray[i].node->parent] = NULL;
       
        dynSetsCP->sets[i].root    = dynSetsCP->allSetsElemArray[i].node;

        dynSetsCP->sets[i].root->height  = 1;
    }
    return;
}
/*************** MiniSpanTree_Kruskal_TreeImpl.cpp  ****************************/

/****************************** main.cpp ***************************************/
#include <iostream>
#include "graph.h"
//#include "MiniSpanTree_Kruskal_ArrayImpl.h"
#include "MiniSpanTree_Kruskal_TreeImpl.h"
using namespace std;

int main()
{
    ALGraph *graph;
    graph = CreateALGraph ();
   // cout << "MiniSpanTree_Kruskal_Array: "<<endl;
   // MiniSpanTree_Kruskal_Array (graph);
    cout << "**********************************************"<<endl
         << "MiniSpanTree_Kruskal_Tree: "<<endl;
    MiniSpanTree_Kruskal_Tree (graph);
}
/*******************************end of file main.cpp **************************/

责任编辑 webmaster

 
 
 
 
 
评论更多>>
 
 
 
发表
 
姓名: QQ:
性别: MSN:
E-mail: 主页:
评分: 1 2 3 4 5
评论内容:
验证码:
  
  • 请遵守《互联网电子公告服务管理规定》及中华人民共和国其他各项有关法律法规。
  • 严禁发表危害国家安全、损害国家利益、破坏民族团结、破坏国家宗教政策、破坏社会稳定、侮辱、诽谤、教唆、淫秽等内容的评论 。
  • 用户需对自己在使用本站服务过程中的行为承担法律责任(直接或间接导致的)。
  • 本站管理员有权保留或删除评论内容。
  • 评论内容只代表网友个人观点,与本网站立场无关。
  •