Kruskal最小生成樹邊權相同的情況
阿新 • • 發佈:2020-12-10
平時我們在利用Kruskal演算法和優先佇列解決最小生成樹問題時,圖的每個邊權一般不相同。但要是有兩個邊權相同的邊,這兩個邊的優先順序怎麼處理?
答案是再結構體中再設定一個變數。
例如:要是規定兩個相同邊權的邊誰先進佇列誰的優先順序就高,則結點設定一個時間變數,具體樣例程式碼如下:
struct NodeInfo
{
int from;
int to;
int weight;
int time;//設定時間是為了如果邊權相同,先進佇列的優先順序高
/********************易錯*************/
bool operator<=(const NodeInfo& node)
{
return weight<=node.weight;
}
bool operator<(const NodeInfo& node)
{
if(weight==node.weight)
return time<node.time;
else
return weight<node.weight;
}
bool operator>(const NodeInfo& node)
{
if(weight==node.weight)
return time>node.time;
else
return weight>node.weight;
}
bool operator>=(const NodeInfo& node)
{
return weight>=node.weight;
}
};
這裡以鄰接矩陣為例
有邊權相同的邊,如果規定矩陣從上往下進入優先佇列(最小生成樹),則每遍歷時間變數加一。如下
int stime=0;
for(int i=0; i<n; i++) //因為對稱矩陣,所以取矩陣的一半
{
for(int j=0; j<i; j++)
{
if(Tlist[j][i]!=0)
{
iter.from=j;
iter.to=i;
iter.weight=Tlist[j][i];
iter.time=stime++;
q.EnQueue(iter);
}
}
}
優先佇列(最小生成樹)的程式碼如下:
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <assert.h>
using namespace std;
int defaultNumVertices = 100;
int defaultWeight=0;
int maxWeight=0x7fffffff;
#define defaultSize 100
template <typename T>
class MinHeap
{
private:
T* heap;
int currentSize;
int maxHeapSize;
void SiftDown(int start,int m)
{
/*刪除頂點,做法是陣列最前面的和最後面的
互換,然後最大長度減一,然後調整順序,這時要>=下滑*/
int i=start;//start=0,從零開始
int j=2*i+1;//j為下方的
T temp = heap[i];
while(j<=m)//m為最後位置
{
if(j<m && heap[j]>heap[j+1])//得到較小孩子的位置
j++;
if(temp<heap[j])//小於後面的停止,等於也要下滑
break;//加=75,不加50
else
{
heap[i]=heap[j];
i=j;
j=2*j+1;
}
}
heap[i]=temp;
}
void SiftUp(int start)
{
int j=start;
int i=(j-1)/2;
T temp = heap[j];//temp當前節點
while(j>0)
{
//if(heap[i]<=temp),後面的過載操作符也要修改
if(heap[i]<temp)
break;
else//如果temp<上個頂點則,上滑
{
heap[j]=heap[i];
j=i;
i=(j-1)/2;
}
}
heap[j]=temp;
}
public:
MinHeap(int sz=defaultSize)
{
maxHeapSize=(defaultSize<sz)?sz:defaultSize;
heap = new T[maxHeapSize];
if(!heap)
{
cout<<"¶Ñ´æ´¢·ÖÅäʧ°Ü"<<endl;
exit(1);
}
currentSize=0;
}
MinHeap(T* ary, int n)
{
maxHeapSize=(defaultSize<n)?n:defaultSize;
heap=new T [maxHeapSize];
if(heap==NULL)
{
cout<<"¶Ñ´æ´¢·ÖÅäʧ°Ü"<<endl;
exit(1);
}
for(int i=0; i<n; i++)
{
heap[i]=ary[i];
}
currentSize = n;
int curPos=(currentSize-2)/2;
while(curPos>=0)
{
SiftDown(curPos,currentSize-1);
curPos--;
}
}
~MinHeap()
{
delete [] heap;
}
bool Insert(const T& x)
{
if(currentSize==maxHeapSize)
{
cout<<"Heap Full"<<endl;
return false;
}
heap[currentSize++]=x;
SiftUp(currentSize-1);
return true;
}
bool Remove(T& x)
{
if(!currentSize)
{
cout<<"Heap empty"<<endl;
return false;
}
x=heap[0];//最小堆,權值小的在上面,對應陣列下標也小
heap[0]=heap[currentSize-1];
currentSize--;
SiftDown(0,currentSize-1);
return true;
}
bool IsEmpty()
{
return currentSize==0;
}
void MakeEmpty()
{
currentSize=0;
}
};
template <typename T>
class PriorityQueue: public MinHeap<T>//子類,用父類的建構函式
{
public:
bool EnQueue(const T& elem)
{
return MinHeap<T>::Insert(elem);
}
bool DeQueue(T& elem)
{
return MinHeap<T>::Remove(elem);
}
bool IsEmpty()
{
return MinHeap<T>::IsEmpty();
}
};
struct NodeInfo
{
int from;
int to;
int weight;
int time;
bool operator<=(const NodeInfo& node)
{
return weight<=node.weight;
}
bool operator<(const NodeInfo& node)
{
if(weight==node.weight)
return time<node.time;
else
return weight<node.weight;
}
bool operator>(const NodeInfo& node)
{
if(weight==node.weight)
return time>node.time;
else
return weight>node.weight;
}
bool operator>=(const NodeInfo& node)
{
return weight>=node.weight;
}
};