实验六 最小代价生成树

时间:2021-09-11 11:36:33

一、实验名称:最小代价生成树

二、实验目的:

1.掌握贪心算法解决问题的思想和一般过程,
2.学会使用普里姆算法解决实际问题。

三、实验内容

完善下列程序,并回答问题。

 

实验六 最小代价生成树实验六 最小代价生成树
 1 #include<iostream.h>
 2 #define G_NODE_NUM 6  //结点个数
 3 #define INFTY 65535
 4 template<class T>
 5 struct ENode
 6 {//带权图的边结点
 7     int adjVex;
 8     T w;
 9     ENode* nextArc;
10 };
11 template <class T>
12 class Graph
13 {
14 public:
15     Graph (int mSize){
16         n = mSize;
17         a = new ENode<T> *[mSize];
18         for(int i = 0; i< n ;i++){
19             a[i] = NULL;
20         }
21     }
22     void Prim(int s);
23     void putin(T X[G_NODE_NUM][G_NODE_NUM]);
24     void putout();
25 protected:
26     void Prim(int k, int* nearest, T* lowcost);
27     ENode<T>** a;
28     int n; 
29 };
30 
31 template<class T>
32 void Graph<T>::putin(T X[G_NODE_NUM][G_NODE_NUM]){
33     ENode<T> *e;
34     for(int i = 0; i < n; i++){
35         for(int j = 0; j < n; j++){
36             if(X[i][j]>0){
37                 e = new ENode<T>();
38                 e->adjVex = j;
39                 e->w = X[i][j];
40                 e->nextArc = a[i];
41                 a[i] = e;
42             }
43         }
44     }
45 }
46 template<class T>
47 void Graph<T>::putout(){
48     ENode<T> *e;
49     cout<<"---图输出---"<<endl;
50     for(int i=0; i<n; i++){
51         e = a[i];
52         cout<<endl<<""<<i<<"个节点:";
53         while(e!=NULL){
54             cout<<" "<<e->adjVex<<"("<<e->w<<")";
55             e=e->nextArc;
56         }
57     }
58     cout<<endl;
59 }
60 
61 template<class T>
62 void Graph<T>::Prim(int s)
63 { 
64     学生书写部分
65 };
66 
67 template<class T>
68 void Graph<T>::Prim(int k, int* nearest, T* lowcost)
69 {
70     学生书写部分
71 }
72 
73 void main(){
74     Graph<int> *G;
75     int data[G_NODE_NUM][G_NODE_NUM]={    {0,6,1,5,0,0},
76                                             {6,0,5,0,3,0},
77                                             {1,5,0,5,6,4},
78                                             {5,0,5,0,0,2},
79                                             {0,3,6,0,0,6},
80                                             {0,0,4,2,6,0}};
81     int n = G_NODE_NUM;
82     G = new Graph<int>(n);
83     G->putin(data);
84     G->putout();
85     G->Prim(0);
86 }
View Code

 

补充后的程序:

实验六 最小代价生成树实验六 最小代价生成树
  1 #include<iostream.h>
  2 #define G_NODE_NUM 6  //结点个数
  3 #define INFTY 65535
  4 template<class T>
  5 struct ENode
  6 {//带权图的边结点
  7     int adjVex;
  8     T w;
  9     ENode* nextArc;
 10 };
 11 template <class T>
 12 class Graph
 13 {
 14 public:
 15     Graph (int mSize){
 16         n = mSize;
 17         a = new ENode<T> *[mSize];
 18         for(int i = 0; i< n ;i++){
 19             a[i] = NULL;
 20         }
 21     }
 22     void Prim(int s);
 23     void putin(T X[G_NODE_NUM][G_NODE_NUM]);
 24     void putout();
 25 protected:
 26     void Prim(int k, int* nearest, T* lowcost);
 27     ENode<T>** a;
 28     int n; 
 29 };
 30 
 31 template<class T>
 32 void Graph<T>::putin(T X[G_NODE_NUM][G_NODE_NUM]){
 33     ENode<T> *e;
 34     for(int i = 0; i < n; i++){
 35         for(int j = 0; j < n; j++){
 36             if(X[i][j]>0){
 37                 e = new ENode<T>();
 38                 e->adjVex = j;
 39                 e->w = X[i][j];
 40                 e->nextArc = a[i];
 41                 a[i] = e;
 42             }
 43         }
 44     }
 45 }
 46 template<class T>
 47 void Graph<T>::putout(){
 48     ENode<T> *e;
 49     cout<<"---图输出---"<<endl;
 50     for(int i=0; i<n; i++){
 51         e = a[i];
 52         cout<<endl<<""<<i<<"个节点:";
 53         while(e!=NULL){
 54             cout<<" "<<e->adjVex<<"("<<e->w<<")";
 55             e=e->nextArc;
 56         }
 57     }
 58     cout<<endl;
 59 }
 60 
 61 template<class T>
 62 void Graph<T>::Prim(int s)
 63 { 
 64     //学生书写部分
 65     int *nearest=new int[n],*lowcost=new int[n];
 66     Prim(s,nearest,lowcost);
 67     for(int j=0;j<n;j++){
 68        cout<<"("<<nearest[j]<<","<<j<<","<<","<<lowcost[j]<<")"; 
 69     }
 70     cout<<endl;
 71     delete[]nearest;
 72     delete[]lowcost;
 73 };
 74 
 75 template<class T>
 76 void Graph<T>::Prim(int k, int* nearest, T* lowcost)
 77 {
 78     //学生书写部分
 79     bool*mark=new bool[n];   //创建mark数组 
 80     ENode<T>*p;
 81     if(k<0||k>n-1)    throw  OutofBounds;    
 82     
 83     for(int i=0;i<n;i++){   //初始化 
 84         nearest[i]=-1;
 85         mark[i]=false;   
 86         lowcost[i]=INFTY; //常量INFTY的值大于所有边的权值 
 87     }
 88     
 89     //源点k加入生成树 
 90     lowcost[k]=0;
 91     nearest[k]=k;
 92     mark[k]=true; 
 93     for(int i=1;i<n;i++){
 94         for(p=a[k];p;p=p-nextArc){
 95             int j=p->adjVex;
 96             if((!mark[j])&&(lowcost    [j]>p->w)){
 97                lowcost[j]=p->w;
 98                nearest[j]=k;
 99             }
100         }
101     }
102     
103     T min=INFTY;   //求下一条最小权值的边 
104     for(int j=0;j<n;j++){
105         if((!mark[j])&&(lowcost    [j]<min)){
106            min=lowcost[j];
107            k=j;
108         }
109     }
110     
111     mark[k]=true;     //将节点k加到生成树上 
112 }
113 
114 int main(){
115     Graph<int> *G;
116     int data[G_NODE_NUM][G_NODE_NUM]={    {0,6,1,5,0,0},
117                                             {6,0,5,0,3,0},
118                                             {1,5,0,5,6,4},
119                                             {5,0,5,0,0,2},
120                                             {0,3,6,0,0,6},
121                                             {0,0,4,2,6,0}};
122     int n = G_NODE_NUM;
123     G = new Graph<int>(n);
124     G->putin(data);
125     G->putout();
126     G->Prim(0);
127 }
View Code

 

程序问题
  1. 分析算法,说明算法中涉及到的变量k、nearest、lawcast、mark,分别表示的语义是什么。
  2. 画出Prim算法的流程图。
  3. 运行课本第109页图6-10的普里姆算法,生成的子树是什么? (程序自带输入部分)
  4. 在程序的适当位置,增加“cout<<"第"<<k<<"个节点加入生成树\n";”语句,输出加入节点的次序。
  5. 试着推理,或者在程序中增加输出语句,说明从第1个节点开始,每一次循环三元组<nearest[i], i, lowcost[i]>的变化。
  6. 若是8个节点的图,如下所示,设计相应的输入邻接矩阵,通过普里姆算法得出的最小生成子树是什么?

实验六 最小代价生成树

      7.(选作)若是使用克鲁斯卡尔算法,课本第109页图6-10生成的最小子图应该是什么?

      8.(选作)若是使用克鲁斯卡尔算法,(图1)生成的最小子图应该是什么?

 

四、实验总结