一、实验名称:最小代价生成树
二、实验目的:
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 }
补充后的程序:
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 }
程序问题
- 分析算法,说明算法中涉及到的变量k、nearest、lawcast、mark,分别表示的语义是什么。
- 画出Prim算法的流程图。
- 运行课本第109页图6-10的普里姆算法,生成的子树是什么? (程序自带输入部分)
- 在程序的适当位置,增加“cout<<"第"<<k<<"个节点加入生成树\n";”语句,输出加入节点的次序。
- 试着推理,或者在程序中增加输出语句,说明从第1个节点开始,每一次循环三元组<nearest[i], i, lowcost[i]>的变化。
- 若是8个节点的图,如下所示,设计相应的输入邻接矩阵,通过普里姆算法得出的最小生成子树是什么?
7.(选作)若是使用克鲁斯卡尔算法,课本第109页图6-10生成的最小子图应该是什么?
8.(选作)若是使用克鲁斯卡尔算法,(图1)生成的最小子图应该是什么?
四、实验总结