Prim算法实现最小生成树(图模型+小根堆)

来源:互联网 发布:php autoload怎么用 编辑:程序博客网 时间:2024/05/22 15:53

Prim算法实现最小生成树的思想是:在图中取一个顶点为起始点,找出其邻接的所有顶点,将该点和邻接的顶点和边的权值一一压入小根堆中,接着从小根堆中退出小根堆的根,将没访问过的两个顶点及其关联边的权值插入到最小生成树中,以此类推,总共需要循环n-1次。


小根堆模块:

int heapNum=0; //记录堆的结点个数//堆的结点结构struct Heap{int sta,en;int weight;} heap[100];//下滑操作void siftDown(int start,int end){//将start号结点向下调整直到endint i=start,j=2*i;heap[0]=heap[i]; //用heap[0]来临时保存i结点的值while(j<=end){//有右孩子并且右孩子比左孩子小时,将j保存右孩子if(j<end&&heap[j].weight>heap[j+1].weight) ++j;//比j号结点小时,不需调整if(heap[0].weight<=heap[j].weight) break;else{//向下调整heap[i]=heap[j];i=j;j=2*j;}}heap[i]=heap[0];}void siftUp(int start){int j=start,i=j/2;heap[0]=heap[j];while(j>0){if(heap[i].weight<=heap[0].weight)break;else{//向上调整工作heap[j]=heap[i];j=i;i=i/2;}}heap[j]=heap[0];}//插入操作的实现bool insert(Heap temp){++heapNum;heap[heapNum]=temp;siftUp(heapNum);return true;}//删除操作bool removeMin(Heap& temp){//保留下根结点temp=heap[1];heap[1]=heap[heapNum]; //填补树根--heapNum;siftDown(1,heapNum); //将根结点下滑到尾部return true;}

图模块:

struct LinkNode{int vex; //邻接的结点在数组中的编号LinkNode* next;int weig; //结点的权值};//定义图结点的最大个数const int MaxSize=10;bool visited[10]={false};struct Node{int data;LinkNode* head;//将结点邻接的链表头置为空Node(){ head=0;}} Adj[MaxSize],miniTree[MaxSize]; //Adj数组表示原来的图//miniTree表示最小生成树//建立图的算法void createLink(int& numNode){int numLink=0;LinkNode* ptr;cin>>numNode;for(int i=1;i<=numNode;++i){cin>>Adj[i].data;cin>>numLink;//头插入建表for(int j=0;j<numLink;++j){ptr=new LinkNode;cin>>ptr->vex;cin>>ptr->weig;ptr->next=Adj[i].head;Adj[i].head=ptr;}}}

Prim算法模块:

//将图中v所关联的边存入堆中void inHeap(int v){LinkNode* ptr=0;ptr=Adj[v].head;//每个邻接点都有机会访问while(ptr!=0){if(!visited[ptr->vex]){Heap temp;temp.sta=v;temp.en=ptr->vex;temp.weight=ptr->weig;//将图中的边和所关联的两个结点压入堆中insert(temp);}ptr=ptr->next; //到下个邻接点}}//将两个结点及其对应关系插入最小生成树中void insertTree(int st,int en,int weig){LinkNode* ptr=new LinkNode;ptr->vex=en;ptr->weig=weig;ptr->next=miniTree[st].head;miniTree[st].head=ptr;}//求从u结点开始遍历生成的最小生成树的算法void prim(int u){int nodeNum=0;createLink(nodeNum);visited[u]=true;int cntNum=1;while(cntNum<nodeNum){//将u所关联的边存入堆中inHeap(u);while(heapNum!=0){Heap temp;//取堆中权值最小的结点removeMin(temp);if(!visited[temp.en]){//将两个顶点及其关联边插入最小生成树中miniTree[temp.sta].data=Adj[temp.sta].data;miniTree[temp.en].data=Adj[temp.en].data;insertTree(temp.sta,temp.en,temp.weight);insertTree(temp.en,temp.sta,temp.weight);u=temp.en;visited[u]=true;++cntNum;break;}}}}