求最小生成樹Kruskal算法

                                                                            求最小生成樹Kruskal算法

      本文取自《數據結構與算法》(C語言版)(第三版),出版社是清華大學出版社。

      本博文作爲學習資料整理。源代碼是VC++ 6.0上可執行程序,我挪到了VS2010中執行。

    在VS2010中新建C++ Win32 控制檯應用程序項目,創建結果截圖:

         

     Kruskal算法的基本思想是:將圖G中的邊按權值從小到大的順序依次添加,如果添加的邊使生成樹T構成迴路,則將其捨棄,依此下去,直到T中包含的邊數爲n-1條邊爲止,此時的T即爲最小生樹。

        Kruskal算法步驟圖示例:

                                
       爲了方便輸出,將最小生成樹的輸入格式規定爲以下形式:
       (頂點1, 頂點2): 權值1
       表示頂點1到頂點2有路徑,路徑上的權值爲1.
       其程序如下:

   #include "stdafx.h"
   #include<stdio.h>
   #include<stdlib.h>
   #include<string.h>
   #define MaxVertexNum 100
   //隊列的聲明
   typedef struct Qnode
   {
     int data;
     struct Qnode* next;
     struct Qnode* prev;
   }Qnode;

   typedef struct queue
   {
     Qnode* first;
     Qnode* tail;
   }Queue;

   int isQueueEmpty(Queue* pQue)
   {
     if(pQue->first==pQue->tail)
       return 1;
     else
       return 0;
   }

   Queue* queueInit(Queue* pQue)
   {
     pQue->first=(Qnode*)malloc(sizeof(Queue));
     pQue->first->data=-1;
     pQue->tail=pQue->first;
     return pQue;
   }

   Qnode* queuePull(Queue* pQue)
   {
     pQue->tail=pQue->tail->prev;
     return pQue->tail->next;
   }

   void queuePush(Queue* pQue, Qnode* pNode)
   {
     pNode->next=pQue->first;
     pQue->first->prev=pNode;
     pQue->first=pNode;
   }

   Queue* queueEmpty(Queue* pQue)
   {
     while(pQue->first!=pQue->tail)
     {
       Qnode* pCurr=pQue->first;
       pQue->first=pQue->first->next;
       free(pQue->first);
     }
     return pQue;
   }

   //圖的聲明
   typedef struct node
   {
     int adjvex;
     int hostvex;
     struct node *nextrarc;
     int info;
   }EdgeNode;

   typedef struct vnode
   {
     char vexdate;
     EdgeNode *firstarc;
   }VertexNode;

   typedef VertexNode AdjList[MaxVertexNum];

   typedef struct
   {
     AdjList adjlist;
     int n,e;
   }ALGraph;

   int initGraph(ALGraph* aGraph);
   int mFind(char aChar, ALGraph* aGraph);
   int createHead(char aChar, ALGraph* aGraph);
   void addBody(char aChar, int aPos, ALGraph* aGraph, int weight);
   void Kruskal(ALGraph* aGraph);

   int main(void)
   {
     char a;
     int isFinish=0;
     int headPos=-1;
     char a1='@', a2='@', a3='@', a4='@', a5='@', a6='@', a7='@';
     ALGraph g_graph;
     initGraph(&g_graph);

     printf("Input arcs like this '(start,end:weight)',end with $\n");
     while(isFinish==0)
     {
        while(1)
        {
          a=getchar();
          if(a=='$'||a=='#')
          {
            if(a=='#')
              isFinish=1;
            break;
          }
          if(a==' '||a=='\n')
            continue;
          a1=a2;
          a2=a3;
          a3=a4;
          a4=a5;
          a5=a6;
          a6=a7;
          a7=a;
          if(a1=='('&&a3==','&&a5==':'&&a7==')')
          {
            if((headPos=mFind(a2,&g_graph))==-1)
              headPos=createHead(a2,&g_graph);
            addBody(a4,headPos,&g_graph,a6);
          }
        }
     }
     Kruskal(&g_graph);
     return 0;
   }

   void Kruskal(ALGraph* aGraph)
    {
      int i,j,u1,v1,sn1,sn2,k;
      int vset[MaxVertexNum];
      EdgeNode* E[MaxVertexNum];
      k=0;
      for(i=0; i<aGraph->n; i++)
      {
        EdgeNode* temEdge;
        for(temEdge=aGraph->adjlist[i].firstarc; temEdge!=NULL;
                temEdge=temEdge->nextrarc)
        {
          E[k]=temEdge;
          k++;
        }
      }
      //將邊的權值進行排序
      for(i=0; i<aGraph->e; i++)
      {
        for(j=aGraph->e-1; j>i; j--)
          if(E[j]->info<E[j-1]->info)
          {
            EdgeNode* tem=E[j];
            E[j]=E[j-1];
            E[j-1]=tem;
          }
      }
      for(i=0; i<aGraph->n; i++)
        vset[i]=i;
      k=1;
      j=0;
      //添加邊
      while(k<aGraph->n)
      {
        u1=E[j]->hostvex;
        v1=E[j]->adjvex;
        sn1=vset[u1];
        sn2=vset[v1];
        if(sn1!=sn2)
        {
          printf("(%d,%d):%c\n",u1,v1,E[j]->info);
          k++;
          for(i=0; i<aGraph->n; i++)
            if(vset[i]==sn2)
              vset[i]=sn1;
        }
        j+=2;
      }
    }

    void addBody(char aChar, int aPos, ALGraph* aGraph, int weight)
    {
      int inversePos;
      EdgeNode* node=(EdgeNode*) malloc(sizeof(EdgeNode));
      node->info=weight;
      if((node->adjvex=mFind(aChar,aGraph))==-1)
        node->adjvex=createHead(aChar,aGraph);
      node->hostvex=aPos;
      node->nextrarc=NULL;
      if(aGraph->adjlist[aPos].firstarc==NULL)
        aGraph->adjlist[aPos].firstarc=node;
      else
      {
        EdgeNode* tail=aGraph->adjlist[aPos].firstarc;
        while(tail->nextrarc!=NULL)
          tail=tail->nextrarc;
        tail->nextrarc=node;
      }
      aGraph->e++;

      inversePos=node->adjvex;
      node=(EdgeNode*) malloc(sizeof(EdgeNode));
      node->info=weight;
      node->hostvex=inversePos;
      node->adjvex=aPos;
      node->nextrarc=NULL;
      if(aGraph->adjlist[inversePos].firstarc==NULL)
        aGraph->adjlist[inversePos].firstarc=node;
      else
      {
        EdgeNode* tail=aGraph->adjlist[inversePos].firstarc;
        while(tail->nextrarc!=NULL)
          tail=tail->nextrarc;
        tail->nextrarc=node;
      }
      aGraph->e++;
    }

   int createHead(char aChar, ALGraph* aGraph)
   {
     int currPos=aGraph->n;
     aGraph->adjlist[currPos].vexdate=aChar;
     aGraph->n++;
     return currPos;
   }

   int mFind(char aChar, ALGraph* aGraph)
   {
     int i=0;
     for(i=0; i<aGraph->n; i++)
     {
       if(aChar==aGraph->adjlist[i].vexdate)
         return i;
     }
     return -1;
   }

   int initGraph(ALGraph* aGraph)
   {
     int i=0;
     aGraph->e=0;
     aGraph->n=0;
     for(i=0; i<MaxVertexNum; i++)
     {
       aGraph->adjlist[i].firstarc=NULL;
     }
     return 0;
   }
         程序運行結果截圖如下:Ctrl+F5執行程序Kruskal.cpp

     

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章