隨筆 - 251  文章 - 504  trackbacks - 0
          <2006年11月>
          2930311234
          567891011
          12131415161718
          19202122232425
          262728293012
          3456789

          本博客系個人收集材料及學習記錄之用,各類“大俠”勿擾!

          留言簿(14)

          隨筆分類

          收藏夾

          My Favorite Web Sites

          名Bloger

          非著名Bloger

          搜索

          •  

          積分與排名

          • 積分 - 202353
          • 排名 - 285

          最新評論

          若要在n個城市之間建設通訊網絡,只需要架設n-1條線路即可。如何以最低的經濟代價建設這個通訊網絡,是一個網的最小生成樹問題。本單元的實驗內容主要是利用克魯斯卡爾算法求出網的最小生成樹,并且以文本形式輸出樹中的各條邊以及他們的權值。

          #include<iostream>
          #include<stdlib.h>//產生隨機數組用
          #include<time.h> //同上
          ?#include<list>

          ?// 1) 帶權邊的類MyArc:

          class MyArc
          {
          public:
          ??? int m_beginVex;
          ??? int m_endVex;
          ??? int m_weight;
          ??? MyArc(int beginVex,int endVex,int weight);
          ??? MyArc(){}
          ??? bool operator < (const MyArc& arc)
          ??? {
          ??????? return m_weight<arc.m_weight;
          ??? }
          ??? bool operator == (const MyArc& arc)
          ??? {
          ??????? return m_weight==arc.m_weight;
          ??? }
          ??? bool operator > (const MyArc& arc)
          ??? {
          ??????? return m_weight>arc.m_weight;
          ??? }
          }? ;

          MyArc::MyArc(int beginVex,int endVex,int weight):m_beginVex(beginVex),m_endVex(endVex),m_weight(weight)
          {}
          //2) 表示圖的鄰接矩陣類Graph:
          class Graph
          {
          public:
          ??? int m_vexnum;
          ??? int m_arcnum;
          ??? int *m_pmatrix;
          public:
          ??? ~Graph();
          ??? Graph(int vexnum);
          ??? Graph(int vexnum,int *pmatrix);
          ??? void insert(MyArc arc);//按權值大小排序插入
          ??? bool bound(int x);?? //判斷頂點x是否已與其它頂點連通
          };
          //構造函數
          Graph::Graph(int vexnum)
          {
          ??? m_pmatrix=new int[vexnum*vexnum];
          ??? m_vexnum=vexnum;m_arcnum=0;
          ??? for(int i=0;i<vexnum*vexnum;++i)
          ??? m_pmatrix[i]=0;

          }

          //構造函數
          Graph::Graph(int vexnum,int *pmatrix)
          {
          ??? m_vexnum=vexnum;
          ??? // m_arcnum=arcnum;
          ??? m_pmatrix=new int[m_vexnum*m_vexnum];
          ??? for(int i=0;i<m_vexnum*m_vexnum;++i)
          ??????? m_pmatrix[i]=pmatrix[i];
          }

          //測試 頂點x是否已與其他點連通
          bool Graph::bound(int x)
          {
          ??? for(int i=0;i<m_vexnum;++i) if(m_pmatrix[x+i*m_vexnum]!=0) return true;
          ??? return false;
          }

          //在鄰接表中連通 arc表示的邊,并且設置權
          void Graph::insert(MyArc arc)
          {
          ??? m_pmatrix[arc.m_beginVex*m_vexnum+arc.m_endVex]=arc.m_weight;
          ??? m_pmatrix[arc.m_endVex*m_vexnum+arc.m_beginVex]=arc.m_weight;
          ??? ++m_arcnum;
          }
          //析構
          Graph::~Graph()
          {
          ??? delete[] m_pmatrix;
          }
          //3) 按權存儲邊的有序隊列類MyQueues:

          //邊按權值插入隊列中合適位置,
          class MyQueues
          {
          public:
          ??? list<MyArc> m_list;
          ??? MyQueues(){}
          ??? void insert(const MyArc& arc);//邊按權值插入隊列中合適位置,
          ??? void InsertGraph(const Graph &graph);//將圖的連通分量插入隊列
          ??? MyArc pop();
          };
          //邊出隊
          MyArc MyQueues::pop()
          {
          ??? MyArc arc=m_list.front();
          ??? m_list.pop_front();
          ??? return arc;
          }
          //邊按權值插入隊列中合適位置,
          void MyQueues::insert(const MyArc& arc)
          {
          ??? list<MyArc>::iterator pos;
          ??? pos=m_list.begin();
          ??? while(pos!=m_list.end())
          ??? {
          ??????? if(*pos>arc) break;
          ??????? else ++pos;
          ??? }
          ??? m_list.insert(pos,arc);
          }
          //將圖的連通分量插入隊列
          void MyQueues::InsertGraph(const Graph &graph)
          {
          ??? for(int i=0;i<graph.m_vexnum;++i)
          ??? {
          ??????? for(int j=i+1;j<graph.m_vexnum;++j)
          ????????????? if(graph.m_pmatrix[i*graph.m_vexnum+j]) insert(MyArc(i,j,graph.m_pmatrix[i*graph.m_vexnum+j]));
          ??? }
          }

          ?//5)判斷是否有回路的IsCycle函數:
          bool IsCycle(Graph& graph, MyArc& arc)
          {
          ??? list<int> my_list;
          ??? my_list.push_back(arc.m_beginVex);
          ??? int *ps=new int[graph.m_vexnum];
          ??? for(int i=0;i<graph.m_vexnum;++i)
          ??????? ps[i]=0;
          ??? while(!my_list.empty())
          ??? {
          ??????? int x=my_list.front();
          ??????? ps[x]=1;
          ??????? my_list.pop_front();
          ??????? for(int i=0;i<graph.m_vexnum;++i)
          ??????? {
          ????????????? if(graph.m_pmatrix[i+x*graph.m_vexnum]!=0)
          ????????????? {
          ????????????????? if(i==arc.m_endVex) return true;
          ????????????????? if(ps[i]!=1) my_list.push_back(i);
          ????????????? }
          ??????? }
          ??? }
          ??? delete[] ps;
          ??? return false;
          }
          //4) kruskal算法:
          void kruskal(const Graph& graph,Graph& smtree)
          {
          ??? MyQueues arcqueues;//保存從小到大排列的邊
          ??? arcqueues.InsertGraph(graph);
          ??? MyArc myarc;//Arc表示邊的類型
          ??? int arcnum=0; //邊的個數
          ??? while(arcnum<graph.m_vexnum-1)
          ??? {
          ??????? myarc=arcqueues.pop();
          ??????? if(!IsCycle(smtree,myarc))
          ??????? {
          ????????????? smtree.insert(myarc);
          ????????????? ++arcnum;
          ??????? }
          ??? }
          }


          void SetMatrix(int vexnum,int *pmatrix)
          {
          ??? srand((unsigned)time(NULL));
          ??? for(int i=0;i<vexnum;++i)//產生隨機權值矩陣
          ??? {
          ??????? for(int j=i;j<vexnum;++j)
          ??????? {
          ????????????? if(j==i)
          ????????????? {
          ????????????????? pmatrix[i*vexnum+j]=0;
          ????????????????? continue;
          ????????????? }
          ????????????? int rnum=rand();rnum%=99;rnum++;//產生1~99的隨機整數作為邊的權值
          ????????????? pmatrix[i*vexnum+j]=rnum;
          ????????????? pmatrix[j*vexnum+i]=rnum;
          ??????? }
          ??? }
          ??? cout<<"***隨機產生的各邊權值矩陣 [頂點數為 "<<vexnum<<"] ****\n";
          ? for(int i=0;i<vexnum;++i)//輸出隨機權值矩陣
          ??? {
          ??????? for(int j=0;j<vexnum;++j)
          ??????? {
          ????????????? cout<<pmatrix[i*vexnum+j]<<"\t";
          ??????? }
          ??????? cout<<endl;
          ??? }

          }

          void SmallestTreeOutput(const Graph& smtree)
          {
          ??? cout<<"最小生成樹:"<<endl;
          ??? for(int i=0;i<smtree.m_vexnum;++i)//輸出最小樹
          ??????? for(int j=i+1;j<smtree.m_vexnum;++j)
          ????????????? if(smtree.m_pmatrix[i*smtree.m_vexnum+j])
          ????????????????? cout<<'('<<i<<','<<j<<','<<smtree.m_pmatrix[i*smtree.m_vexnum+j]<<')'<<endl;
          }

          ?

          void main()
          {
          ??? char i;
          ??? cout<<"請輸入頂點數目:";
          ??? cin>>i;
          ? int vex=i-'0';
          ??? int *matrix=new int[vex*vex];
          ??? cout<<endl;
          ??? SetMatrix(vex,matrix);
          ??? Graph graph(vex,matrix),smtree(vex);
          ??? kruskal(graph,smtree);
          ??? SmallestTreeOutput(smtree);
          ??? delete []matrix;
          }


          結果輸出:
          請輸入頂點數目:6

          ***隨機產生的各邊權值矩陣 [頂點數為 6] ****
          0?????? 64????? 7?????? 15????? 22????? 43
          64????? 0?????? 72????? 86????? 53????? 40
          7?????? 72????? 0?????? 53????? 37????? 22
          15????? 86????? 53????? 0?????? 87????? 82
          22????? 53????? 37????? 87????? 0?????? 9
          43????? 40????? 22????? 82????? 9?????? 0
          最小生成樹:
          (0,2,7)
          (0,3,15)
          (0,4,22)
          (1,5,40)
          (4,5,9)

          posted on 2006-11-20 14:59 matthew 閱讀(3855) 評論(6)  編輯  收藏 所屬分類: 數據結構與算法設計

          FeedBack:
          # re: 數據結構之圖及其應用—網的最小生成樹  2006-12-30 14:38 jdf
          好像有點問題,我用vc++6.0編譯不過  回復  更多評論
            
          # re: 數據結構之圖及其應用—網的最小生成樹  2006-12-30 18:41 matthew[匿名]
          我試過了,能夠編譯運行。編譯環境:C-Free3.5  回復  更多評論
            
          # re: 數據結構之圖及其應用—網的最小生成樹  2007-04-13 08:53 45655
          請教用java 怎么編寫————最小生成樹的應用。
          【例】網絡G表示n個城市之間的通信線路網(其中頂點表示城市,邊表示兩個城市之間的通信線路,邊上的權值表示線路的長度或造價。可通過求該網絡的最小生成樹達到求解通信線路或總代價最小的最佳方案。

          問題的實現:
          要求用java語言動態實現此過程,步驟:
          (1)首先在文本框內輸入城市的個數,即頂點數;
          (2)根據輸入的頂點個數點擊鼠標分別顯示出①②③④⑤;
          (3)在文本框內分別輸入兩個城市的名字以及權值,與此同時,在圖中自動畫出兩點之間的連線,并在線的中央顯示其權值。

            回復  更多評論
            
          # re: 數據結構之圖及其應用—網的最小生成樹  2007-04-13 08:53 45655
          謝謝拉
            回復  更多評論
            
          # re: 數據結構之圖及其應用—網的最小生成樹  2007-06-01 13:21 wyx860216@sina.com
          請教下面這題的C語言源程序:

          網絡G表示n個城市之間的通信線路網(其中頂點表示城市,邊表示兩個城市之間的通信線路,邊上的權值表示線路的長度或造價。可通過求該網絡的最小生成樹達到求解通信線路或總代價最小的最佳方案。

          要求用visual C++編寫..

          謝謝!
            回復  更多評論
            
          # re: 數據結構之圖及其應用—網的最小生成樹 [未登錄] 2008-12-22 20:37 ZY
          萬分感謝,寫的很精彩,無私的博主!  回復  更多評論
            
          主站蜘蛛池模板: 龙川县| 梅河口市| 长沙县| 青铜峡市| 德州市| 天门市| 韩城市| 阿合奇县| 鄯善县| 梧州市| 鹿邑县| 磐安县| 卢湾区| 江孜县| 商丘市| 尚义县| 黔西县| 交口县| 那坡县| 东乡| 五华县| 昌图县| 东安县| 桐梓县| 邢台县| 溧阳市| 茌平县| 万宁市| 桑日县| 城固县| 太谷县| 南宫市| 宜黄县| 阳谷县| 团风县| 赣榆县| 乌拉特中旗| 陵川县| 石河子市| 修文县| 普陀区|