數(shù)據(jù)結構課程設計-最小生成樹問題_第1頁
已閱讀1頁,還剩11頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、<p><b>  課程設計報告</b></p><p>  課程名稱 《數(shù)據(jù)結構》 </p><p>  課題名稱 最小生成樹問題 </p><p>  專業(yè) 計算機科學與技術 </p><p>  班級 10計本2班

2、 </p><p>  “最小生成樹問題”課程設計</p><p>  題目: 編制一個求出N個頂點圖的最小生成樹程序</p><p><b>  一 需求分析:</b></p><p>  (1)在n個城市間建設通信網(wǎng)絡,只需要架設n-1條線路即可。以最低的代價建設這個通信網(wǎng),即求圖的最小生成樹。 </p>

3、;<p>  (2)利用克魯斯卡爾算法求網(wǎng)的最小生成樹。</p><p>  (3)利用自定義的隊列結構存放連通分量。</p><p>  (4)以文本形式輸出最小生成樹中的各條邊及它們的權值。輸出格式為(int a,int b,int n),其中a,b為頂點序號,n為ab邊的權;</p><p>  (5)程序運行流程:</p><

4、;p>  1)提示輸入頂點數(shù)目;</p><p>  2)接受輸入,按照項目要求產(chǎn)生邊權值的隨機矩陣;然后求解最小生成樹;</p><p>  3)輸出最小生成樹并且退出;</p><p><b>  (6)測試數(shù)據(jù):9</b></p><p><b>  二 概要設計:</b></p&

5、gt;<p>  1.表示邊的類定義和接口:</p><p>  class MyArc</p><p><b>  {</b></p><p><b>  public:</b></p><p>  int m_beginVex;</p><p>  int

6、m_endVex;</p><p>  int m_weight;</p><p>  MyArc(int beginVex,int endVex,int weight);</p><p><b>  MyArc(){}</b></p><p><b>  //重載運算符</b></p>

7、<p>  inline bool operator < (const MyArc& arc){ return m_weight<arc.m_weight;}</p><p>  inline bool operator == (const MyArc& arc){ return m_weight==arc.m_weight;}</p>&l

8、t;p>  inline bool operator > (const MyArc& arc){ return m_weight>arc.m_weight; }</p><p><b>  };</b></p><p>  2. 用鄰接矩陣表示的圖類的定義和接口:</p><p>  class Graph&l

9、t;/p><p><b>  {</b></p><p><b>  private:</b></p><p>  int m_vexnum;</p><p>  int m_arcnum;</p><p>  int *m_pmatrix;</p><p&g

10、t;<b>  public:</b></p><p><b>  ~Graph();</b></p><p>  Graph(int vexnum);</p><p>  Graph(int vexnum,int *pmatrix);</p><p>  void insert(MyArc arc

11、);//連通arc 邊</p><p>  bool bound(int x); //判斷頂點x是否已與其它頂點連通</p><p><b>  };</b></p><p>  3. 自定義隊列,用于存放連通圖,或按權排列后的邊:</p><p>  class MyQueues</p><p&

12、gt;<b>  {</b></p><p><b>  public:</b></p><p>  list<MyArc> m_list;</p><p>  MyQueues(){}</p><p>  void insert(const MyArc& arc); //按權值

13、大小排序插入</p><p>  void InsertGraph(const Graph &graph); //將圖的連通分量插入隊列</p><p>  MyArc pop();//出隊列</p><p><b>  };</b></p><p><b>  4.本程序的結構</b>&l

14、t;/p><p><b>  1)主程序模塊:</b></p><p>  void main()</p><p><b>  {</b></p><p>  申明邊權值矩陣數(shù)組并用隨機函數(shù)初始化;</p><p><b>  創(chuàng)建圖;</b></p&

15、gt;<p>  調用克魯斯卡爾算法函數(shù);</p><p>  輸出邊的權值矩陣,最小生成樹中的各條邊及它們的權值</p><p><b>  退出;</b></p><p><b>  }</b></p><p>  2)帶權的邊類模塊---實現(xiàn)帶權邊的存儲和運算。</p>

16、;<p>  鄰接矩陣類模塊---實現(xiàn)圖的狀態(tài)記錄和相關操作。</p><p>  自定義隊列類模塊---實現(xiàn)邊的按權存貯和相關操作。</p><p>  3)核心kruskal算法模塊---用克魯斯卡爾算法求出最小生成樹 </p><p><b>  各模塊調用關系:</b></p><p><b&

17、gt;  三 詳細設計</b></p><p>  #include<iostream></p><p>  #include<stdlib.h>//產(chǎn)生隨機數(shù)組用</p><p>  #include<time.h> //同上</p><p>  //#include "basic.

18、h" //所用到的自定義數(shù)據(jù)結構定義和實現(xiàn)文件</p><p>  using namespace std;</p><p>  #include<list></p><p>  /*MyStack 堆棧類的結構 [ 0 1 ... curlen ... size] [棧底(bottom) ... prt ... ]*/

19、</p><p>  #define BASESIZE 64 //默認堆棧數(shù)組空間大?。?*8),可以自擴充</p><p>  template <class Type> </p><p>  class MyStack</p><p><b>  {</b></p><p>

20、;<b>  private:</b></p><p>  Type *bottom; // 元素存放的動態(tài)數(shù)組 </p><p>  int size,ptr; // 堆棧大小和當前棧頂元素索引</p><p><b>  public: </b></p><p><b&

21、gt;  //構造函數(shù)</b></p><p>  MyStack() </p><p><b>  {</b></p><p>  bottom=new Type[BASESIZE];ptr=-1;size=BASESIZE;</p><p><b>  };</b><

22、;/p><p><b>  //析構函數(shù)</b></p><p>  ~MyStack(){delete []bottom;};</p><p><b>  //清棧還原</b></p><p>  inline void clear()</p><p><b>  {

23、</b></p><p>  if(bottom!=NULL)</p><p>  delete []bottom;</p><p>  bottom=new Type[size];</p><p>  ptr=-1; </p><p><b>  };</b><

24、/p><p><b>  //判???lt;/b></p><p>  inline bool IsEmpty()</p><p><b>  {</b></p><p>  if(ptr==-1) return true;</p><p>  else return false;&l

25、t;/p><p><b>  }</b></p><p><b>  //入棧</b></p><p>  int push(Type e);</p><p><b>  //出棧</b></p><p>  int pop(Type &e);<

26、;/p><p><b>  //獲得棧頂元素</b></p><p>  int top(Type &e);</p><p>  int settop(Type e);</p><p>  // 用callback函數(shù)對棧從低向上遍歷</p><p>  void traverse(void

27、callback(Type *),Type *); </p><p><b>  private:</b></p><p>  inline int extent()</p><p><b>  {</b></p><p>  int s=size;</p><p>  Ty

28、pe *temp=new Type[size];</p><p>  for(int i=0;i<s;i++)</p><p>  temp[i]=bottom[i];</p><p><b>  size*=2;</b></p><p><b>  clear();</b></p>

29、;<p><b>  ptr=s+1;</b></p><p>  for(int i=0;i<s;i++)</p><p>  bottom[i]=temp[i];</p><p>  delete [] temp;</p><p>  return size;</p><p&g

30、t;<b>  }</b></p><p><b>  };</b></p><p>  /*MyStack的實現(xiàn) */</p><p><b>  /*壓棧*/</b></p><p>  template <class Type> </p><

31、;p>  int MyStack<Type>::push(Type e) // </p><p>  { </p><p>  if(++ptr==size) extent();</p><p>  bottom[ptr]=e; </p><p>  return ptr; </p>&

32、lt;p><b>  }</b></p><p><b>  /*出棧*/</b></p><p>  template <class Type> </p><p>  int MyStack<Type>::pop(Type &e) // </p><p>&l

33、t;b>  {</b></p><p>  if(ptr==-1)</p><p>  return -2;//??眨祷?-2 !</p><p><b>  else </b></p><p>  e=bottom[ptr--]; </p><p>  ret

34、urn ptr;</p><p><b>  }</b></p><p>  /*獲取棧頂元素*/</p><p>  template <class Type></p><p>  int MyStack<Type>::top(Type &e) // </p><p&

35、gt;<b>  {</b></p><p>  if(ptr==-1)</p><p>  return -1;//???返回 -1 !</p><p><b>  else</b></p><p>  e=bottom[ptr];</p><p>  return ptr

36、;</p><p><b>  }</b></p><p>  /*設置棧定元素*/</p><p>  template <class Type></p><p>  int MyStack<Type>::settop(Type e) //</p><p><b&g

37、t;  {</b></p><p>  if(ptr==-1)</p><p>  return -1;//???返回 -1 !</p><p><b>  else</b></p><p>  bottom[ptr]=e;</p><p>  return ptr;</p>

38、;<p><b>  }</b></p><p>  /*用callback函數(shù)對棧從低向上遍歷*/</p><p>  template <class Type></p><p>  void MyStack<Type>::traverse(void callback(Type *),Type *e)&l

39、t;/p><p><b>  {</b></p><p>  if(callback!=NULL)</p><p><b>  {</b></p><p>  for(int i=0;i<=ptr;i++)</p><p><b>  {</b><

40、;/p><p>  e=&bottom[i];</p><p>  callback(e);</p><p><b>  }</b></p><p><b>  }</b></p><p><b>  }; // </b></p>&l

41、t;p>  /*MyPoint 坐標結構 */</p><p>  typedef struct MyPoint</p><p><b>  {</b></p><p><b>  int x, y;</b></p><p>  } *pMyPoint;</p><p&g

42、t;<b>  //</b></p><p><b>  /*表示邊的類*/</b></p><p>  class MyArc</p><p><b>  {</b></p><p><b>  public:</b></p><p&

43、gt;  int m_beginVex;</p><p>  int m_endVex;</p><p>  int m_weight;</p><p>  MyArc(int beginVex,int endVex,int weight);</p><p><b>  MyArc(){}</b></p>

44、<p>  bool operator < (const MyArc& arc)</p><p><b>  {</b></p><p>  return m_weight<arc.m_weight;</p><p><b>  }</b></p><p>  bool

45、 operator == (const MyArc& arc)</p><p><b>  {</b></p><p>  return m_weight==arc.m_weight;</p><p><b>  }</b></p><p>  bool operator > (con

46、st MyArc& arc)</p><p><b>  {</b></p><p>  return m_weight>arc.m_weight;</p><p><b>  }</b></p><p><b>  };</b></p><p

47、>  MyArc::MyArc(int beginVex,int endVex,int weight):m_beginVex(beginVex),m_endVex(endVex),m_weight(weight)</p><p><b>  {}</b></p><p>  /*用鄰接矩陣表示的圖類,可以帶權,權不可以為0*/</p><p&

48、gt;  class Graph</p><p><b>  {</b></p><p><b>  public:</b></p><p>  int m_vexnum;</p><p>  int m_arcnum;</p><p>  int *m_pmatrix;&l

49、t;/p><p><b>  public:</b></p><p><b>  ~Graph();</b></p><p>  Graph(int vexnum);</p><p>  Graph(int vexnum,int *pmatrix);</p><p>  void

50、 insert(MyArc arc);//按權值大小排序插入</p><p>  bool bound(int x); //判斷頂點x是否已與其它頂點連通</p><p><b>  };</b></p><p><b>  //構造函數(shù)</b></p><p>  Graph::Graph(i

51、nt vexnum)</p><p><b>  {</b></p><p>  m_pmatrix=new int[vexnum*vexnum];</p><p>  m_vexnum=vexnum;m_arcnum=0;</p><p>  for(int i=0;i<vexnum*vexnum;++i) m_

52、pmatrix[i]=0;</p><p><b>  }</b></p><p><b>  //構造函數(shù)</b></p><p>  Graph::Graph(int vexnum,int *pmatrix)</p><p><b>  {</b></p>&

53、lt;p>  m_vexnum=vexnum;</p><p>  // m_arcnum=arcnum;</p><p>  m_pmatrix=new int[m_vexnum*m_vexnum];</p><p>  for(int i=0;i<m_vexnum*m_vexnum;++i)</p><p>  m_pmatr

54、ix[i]=pmatrix[i];</p><p><b>  }</b></p><p>  //測試 頂點x是否已與其他點連通</p><p>  bool Graph::bound(int x)</p><p><b>  {</b></p><p>  for(int

55、 i=0;i<m_vexnum;++i) if(m_pmatrix[x+i*m_vexnum]!=0) return true;</p><p>  return false;</p><p><b>  }</b></p><p>  //在鄰接表中連通 arc表示的邊,并且設置權</p><p>  void

56、Graph::insert(MyArc arc)</p><p><b>  {</b></p><p>  m_pmatrix[arc.m_beginVex*m_vexnum+arc.m_endVex]=arc.m_weight;</p><p>  m_pmatrix[arc.m_endVex*m_vexnum+arc.m_beginVex

57、]=arc.m_weight;</p><p>  ++m_arcnum;</p><p><b>  }</b></p><p>  Graph::~Graph()</p><p><b>  {</b></p><p>  delete[] m_pmatrix;</

58、p><p><b>  }</b></p><p>  /*自定義隊列,用于存放連通圖,或按權排列后的邊*/</p><p>  class MyQueues</p><p><b>  {</b></p><p><b>  public:</b><

59、/p><p>  list<MyArc> m_list;</p><p>  MyQueues(){}</p><p>  void insert(const MyArc& arc);//邊按權值插入隊列中合適位置,</p><p>  void InsertGraph(const Graph &graph);//將圖

60、的連通分量插入隊列</p><p>  MyArc pop();</p><p><b>  };</b></p><p><b>  //邊出隊</b></p><p>  MyArc MyQueues::pop()</p><p><b>  {</b&g

61、t;</p><p>  MyArc arc=m_list.front();</p><p>  m_list.pop_front(); </p><p>  return arc;</p><p><b>  }</b></p><

62、p>  //邊按權值插入隊列中合適位置,</p><p>  void MyQueues::insert(const MyArc& arc)</p><p><b>  {</b></p><p>  list<MyArc>::iterator pos=m_list.begin();</p><p&

63、gt;  while(pos!=m_list.end())</p><p><b>  {</b></p><p>  if(*pos>arc) break;</p><p>  else ++pos;</p><p><b>  }</b></p><p>  m_l

64、ist.insert(pos,arc);</p><p><b>  }</b></p><p>  //將圖的連通分量插入隊列</p><p>  void MyQueues::InsertGraph(const Graph &graph)</p><p><b>  {</b></

65、p><p>  for(int i=0;i<graph.m_vexnum;++i)</p><p><b>  {</b></p><p>  for(int j=i+1;j<graph.m_vexnum;++j)</p><p>  if(graph.m_pmatrix[i*graph.m_vexnum+j])

66、 insert(MyArc(i,j,graph.m_pmatrix[i*graph.m_vexnum+j]));</p><p><b>  }</b></p><p><b>  }</b></p><p>  bool IsCycle(Graph &graph,MyArc& arc); //

67、判斷是否構成回路</p><p>  void kruskal(const Graph& graph,Graph& smtree);//克魯斯卡爾算法</p><p>  void SmallestTreeOutput(const Graph& smtree); //輸出最小生成樹 </p><p>  void SetMatrix(int

68、vexnum,int *matrix); //用隨機數(shù)組初始化matrix數(shù)組并且打印</p><p><b>  /*主函數(shù)*/</b></p><p>  void main()</p><p><b>  {</b></p><p><b>  char i;</b&g

69、t;</p><p>  cout<<"************************************************"<<endl;</p><p>  cout<<”標題:最小生成樹”<<endl;</p><p>  cout<<"班級:計本2班&quo

70、t;<<endl;</p><p>  cout<<"姓名:張娟"<<endl;</p><p>  cout<<"學號:10012121 "<<endl;</p><p>  cout<<"***************************

71、*********************"<<endl;</p><p>  cout<<"請輸入頂點數(shù)目:";</p><p><b>  cin>>i;</b></p><p>  int vex=i-'0';</p><p>  i

72、nt *matrix=new int[vex*vex];</p><p>  cout<<endl;</p><p>  SetMatrix(vex,matrix); </p><p>  Graph graph(vex,matrix),smtree(vex);</p><p>  kruskal(graph,smtree

73、);</p><p>  SmallestTreeOutput(smtree);</p><p>  delete []matrix;</p><p><b>  }</b></p><p>  //用隨機數(shù)組初始化matrix數(shù)組并且打印</p><p>  void SetMatrix(int

74、 vexnum,int *pmatrix)</p><p><b>  { </b></p><p>  srand((unsigned)time(NULL));</p><p>  for(int i=0;i<vexnum;++i)//產(chǎn)生隨機權值矩陣</p><p><b>  {</b

75、></p><p>  for(int j=i;j<vexnum;++j)</p><p><b>  { </b></p><p><b>  if(j==i)</b></p><p><b>  {</b></p><p>  p

76、matrix[i*vexnum+j]=0;</p><p><b>  continue;</b></p><p><b>  }</b></p><p>  int rnum=rand();rnum%=99;rnum++;//產(chǎn)生1~99的隨機整數(shù)作為邊的權值</p><p>  pmatrix[

77、i*vexnum+j]=rnum;</p><p>  pmatrix[j*vexnum+i]=rnum;</p><p><b>  }</b></p><p><b>  }</b></p><p>  cout<<"***隨機產(chǎn)生的各邊權值矩陣 [頂點數(shù)為 "&

78、lt;<vexnum<<"] ****\n";</p><p>  for( i=0;i<vexnum;++i)//輸出隨機權值矩陣</p><p><b>  {</b></p><p>  for(int j=0;j<vexnum;++j)</p><p><b

79、>  { </b></p><p>  cout<<pmatrix[i*vexnum+j]<<"\t";</p><p><b>  }</b></p><p>  cout<<endl;</p><p><b>  }</

80、b></p><p><b>  }</b></p><p>  //判斷連通邊arc后 圖graph 是否存在回路 </p><p>  bool IsCycle(Graph& graph, MyArc& arc) </p><p><b>  {</b></p&g

81、t;<p>  list<int> mylist;</p><p>  mylist.push_back(arc.m_beginVex);</p><p>  int *ps=new int[graph.m_vexnum];</p><p>  for(int i=0;i<graph.m_vexnum;++i)</p>

82、<p><b>  ps[i]=0;</b></p><p>  while(!mylist.empty())</p><p><b>  {</b></p><p>  int x=mylist.front();</p><p><b>  ps[x]=1;</b>

83、</p><p>  mylist.pop_front();</p><p>  for(int i=0;i<graph.m_vexnum;++i)</p><p><b>  {</b></p><p>  if(graph.m_pmatrix[i+x*graph.m_vexnum]!=0)</p>

84、<p><b>  {</b></p><p>  if(i==arc.m_endVex) return true;</p><p>  if(ps[i]!=1) mylist.push_back(i);</p><p><b>  }</b></p><p><b>  }&

85、lt;/b></p><p><b>  }</b></p><p>  delete[] ps; </p><p>  return false;</p><p><b>  }</b></p><p><b>  //克魯斯卡爾算法</b>&l

86、t;/p><p>  void kruskal(const Graph& graph,Graph& smtree)</p><p><b>  {</b></p><p>  MyQueues arcqueues;//保存從小到大排列的邊</p><p>  arcqueues.InsertGraph(gra

87、ph);</p><p>  MyArc myarc;//Arc表示邊的類型</p><p>  int arcnum=0; //邊的個數(shù)</p><p>  while(arcnum<graph.m_vexnum-1)</p><p><b>  {</b></p><p>  myarc

88、=arcqueues.pop();</p><p>  if(!IsCycle(smtree,myarc))</p><p><b>  {</b></p><p>  smtree.insert(myarc);</p><p><b>  ++arcnum;</b></p><

89、p><b>  }</b></p><p><b>  }</b></p><p><b>  }</b></p><p><b>  //輸出最小生成樹</b></p><p>  void SmallestTreeOutput(const Gra

90、ph& smtree)</p><p><b>  {</b></p><p>  cout<<"最小生成樹:"<<endl;</p><p>  for(int i=0;i<smtree.m_vexnum;++i)//輸出最小樹</p><p>  for(in

91、t j=i+1;j<smtree.m_vexnum;++j)</p><p>  if(smtree.m_pmatrix[i*smtree.m_vexnum+j]) cout<<'('<<i<<','<<j<<','<<smtree.m_pmatrix[i

92、*smtree.m_vexnum+j]<<')'<<endl;</p><p><b>  }</b></p><p><b>  四 設計和調試分析</b></p><p>  1.在調試MyQueues類的時候,由于對數(shù)組的按行存儲理解的不夠好導致開始時未能獲得正確的數(shù)據(jù),經(jīng)單步

93、跟蹤調試后發(fā)現(xiàn)下標超出范圍,修正后即可正常運行。</p><p>  2.在本實驗中,自定義了3個類,定義了基于它們的數(shù)據(jù)和操作,它們是本程序的實現(xiàn)基礎。</p><p>  3.由于翻譯核心算法 kruskal的時間復雜度與邊的數(shù)目的函數(shù)有線性關系,同時IsCycle函數(shù)含有while和for循環(huán),在頂點數(shù)目不多的時候,算法時間很快,適用于稀疏矩陣。 </p><p&

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論