图的最小生成树算法的实现 prim and kruskal

两种算法的讲解请观看:

https://www.bilibili.com/video/BV1Eb41177d1?from=search&seid=5569805741961941597

先来prim算法

//0:first vertex  1:second vertex 3:arc value
int primArc[14][3] = 
{
    {0, 1, 4},
    {0, 7, 8},
    {1, 7, 11},
    {1, 2, 8},
    {2, 3, 7},
    {2, 5, 4},
    {2, 8, 2},
    {3, 4, 9},
    {3, 5, 14},
    {4, 5, 10},
    {5, 6, 2},
    {6, 7, 1},
    {6, 8, 6},
    {7, 8, 7}
};


typedef struct{
    int selected;       //vertex selected or not
    int miniDistance;   //distance between parent and this vetex
    int parant;         //parent of this vertex, not use now
}primAsistArray;

void primGraph_Init(int (*G)[9], primAsistArray *primArr)
{
    memset(G, 0, 81 * sizeof(int));//init this graph element by 0
    int j = 0;
    for(int i = 0; i < 9; i++)
    {
        while(i == primArc[j][0])
        {
            G[i][primArc[j][1]] = primArc[j][2];
            G[primArc[j][1]][i] = primArc[j][2];
            j++;
        }
        primArr[i].miniDistance = 99;   
        primArr[i].selected = 0;
        primArr[i].parant = 99;
    }
    //printf this graph element
    for(int i = 0; i < 9; i++)
    {
        for(int j = 0; j < 9; j++)
        {
            std::cout << std::setw(3) << G[i][j] ;
        }
        std::cout << std::endl;
    }
    std::cout << std::endl;
}

int findMiniDistance(primAsistArray *primArr, int *tempValue)
{
    int miniDistance = 99;
    int k;
    for(int i = 0; i < 9; i++)
    {
        if (miniDistance > primArr[i].miniDistance)
        {
            miniDistance = primArr[i].miniDistance;
            //primArr[i].parant = temp;
            *tempValue = miniDistance;
            k = i;
        }
    }
    return k;
}

void primResolv(int (*Graph)[9], primAsistArray *primArr, const int n)
{
    int temp = n;
    int tempMiniValue[8];
    memset(tempMiniValue, 0, 8 * sizeof(int));
    //std::cout << std::setw(3) << temp;  //cout the first element
    primArr[temp].selected = 1;
    //find the last 8 rout
    for(int i = 0; i < 8; i++)
    {
        for(int j = 0; j < 9; j++)
        {
            if(Graph[temp][j] != 0 && primArr[j].selected == 0 )
            {
                //primArr[j].miniDistance = primArr[j].miniDistance > Graph[temp][j] ? Graph[temp][j] : primArr[j].miniDistance;
                if(primArr[j].miniDistance > Graph[temp][j])
                {
                    primArr[j].miniDistance = Graph[temp][j];//find the mini value of the prim array
                    primArr[j].parant = temp;       //update the element's parament value
                }
            }
        }
       // std::cout << std::setw(3) << temp << " ---> "; 
       temp =  findMiniDistance(primArr, &tempMiniValue[i]);
       //printf relation vertex of mini arc value which is separated with ','
       std::cout << primArr[temp].parant << "[" << tempMiniValue[i] << "]" << temp << " , " ;
       primArr[temp].selected = 1;  //set the vertex as a selected element
       primArr[temp].miniDistance = 99;
    }
    //output sum value
    int sum = 0;
    for(int i = 0; i < 8; i++)
    {
        sum = sum + tempMiniValue[i];
    }
    std::cout << "sum value is:" << sum;
    std::cout << std::endl;
}

//
void additionaryArr_Init(primAsistArray *primArr)
{
    for(int i = 0; i < 9; i++)
    {
        primArr[i].miniDistance = 99;   
        primArr[i].selected = 0;
        primArr[i].parant = 99;
    }
}

void PRIM_Test(void)
{
    primAsistArray usrPrimArr[9];
    int primGraph[9][9];
    primGraph_Init(primGraph, usrPrimArr);
    for(int i = 0; i < 9; i++)
    {
        primResolv(primGraph, usrPrimArr, i);
        std::cout << std::endl;
        additionaryArr_Init(usrPrimArr);
    }
}

运行结果如下:

再来kruskal

//kruskal

//1:start  2:end  3:weight of arc
 int kArc [14][3] = 
 {
     {0, 1, 4},
     {0, 7, 8},
     {1, 2, 8},
     {1, 7, 11},
     {2, 3, 7},
     {2, 5, 4},
     {2, 8, 2},
     {3, 4, 9},
     {3, 5, 14}, 
     {4, 5, 10},
     {5, 6, 2},
     {6, 7, 1},
     {6, 8, 6},
     {7, 8, 7}
 };
//reference kArc[][]
 typedef struct 
 {
     int start;
     int end;
     int weigth;
 }krArc;


int findTreeRoot(krArc *Tree, int *parentArr, int vertex)
{
    int tempval = vertex;
    while(parentArr[tempval] != -1)
    {
        tempval = parentArr[tempval]; 
    }
    return tempval;
}

//return 0: find a ring, 1: no ring
//parentArr[14]  index of arc's parent, such as ParentArr[5] = 8 means vertex 5's parent is 8
//numberOfArc: how many arcs of this tree now
 bool kFindRing(int *parentArr, krArc *miniSizeTree, int numberOfarc, krArc newArc)
 {
     parentArr[newArc.end] = newArc.start;//smaller vertex number value is configur as father
     int rootA = -1;
     int rootB = -1;
     for(int i = 0; i < numberOfarc; i++)
     {
         if(miniSizeTree[i].start == newArc.start || miniSizeTree[i].end == newArc.start)
         {
             rootA = findTreeRoot(miniSizeTree, parentArr, newArc.start);
         }
         else if(miniSizeTree[i].start == newArc.end || miniSizeTree[i].end == newArc.end)
         {
             rootB = findTreeRoot(miniSizeTree, parentArr, newArc.end);
         }
     }
    if(rootA == rootB && rootA != -1 && rootA != newArc.start)//if two vertices have the same root, the tree has a ring ,abandon this arc.
    {
        parentArr[newArc.end] = -1;
        std::cout << "find a ring" << std::endl;
        return 0;
    }
    return 1;
 }

//union a new arc to minisizeTree
void unionArc(krArc *minisizeTree, int *n, krArc newArc, int *parentArr)
{
    if(kFindRing(parentArr, minisizeTree, *n, newArc))//no ring 
    {
        minisizeTree[*n] = newArc;
        *n += 1;//the number of arcs ++
    }
}

//find the minist arc value from KArc
void findMiniValue(int (*kArc)[3], int *isVisited, krArc *newArc)
{
    int tempArcValue = 99;
    int tempi;
    for(int i = 0; i < 14; i++)
    {
        if(tempArcValue > kArc[i][2] && isVisited[i] == -1)
        {
            tempArcValue = kArc[i][2];
            tempi = i;
        }
    }
    isVisited[tempi] = 1;
    newArc->start = kArc[tempi][0];
    newArc->end = kArc[tempi][1];
    newArc->weigth = kArc[tempi][2];
}

void kruskal_Test(void)
{
    krArc newArc;
    krArc minisizeTree[8];//mini size tree
    int parentArr[9];
    int isVisited[14];
    memset(parentArr, -1, 9 * sizeof(int)); //init aux array parentArr which corrospanding the index of parent value
    memset(isVisited, -1, 14 * sizeof(int));//note which arcs had been selected
    int n = 0;
    for(int i = 0; i < 14; i++)
    {
        findMiniValue(kArc, isVisited, &newArc);        //find mini arc
        unionArc(minisizeTree, &n, newArc, parentArr);  //union arc
        if(n == 8)  //end of this mini tree
        {
            std::cout << "find mini tree" << std::endl;
            return;
        }
    }
}

运行结果如下:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值