1. 程式人生 > 其它 >Kruskal最小生成樹邊權相同的情況

Kruskal最小生成樹邊權相同的情況

技術標籤:c++資料結構

平時我們在利用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;
    }
};