1. 程式人生 > >10. 樹--並查集

10. 樹--並查集

並查集

定義

並查集是一種樹型的資料結構,用於處理一些不相交集合(Disjoint Sets)的合併及查詢問題。常常在使用中以森林來表示。

儲存實現

  • 邏輯結構:使用樹結構表示集合,樹的每個結點代表一個集合元素
  • 物理結構:採用陣列儲存,使用雙親表示法(孩子指向雙親)

有三個整數集合:
* S1={1,2,4,7}
* S2={3,5,8}
* S3={6,9,10}

邏輯結構

image

物理結構

下標 Data Parent
0 1 -1
1 2 0
2 3 -1
3 4 0
4 5 2
5 6 -1
7 8 2
8 9 5
9 10 5

Parent:

  • 負數表示根結點
  • 非負數表示雙親結點的下標

集合的運算

結構定義

typedef struct {
    ElementType Data;
    int Parent;
} SetType;

查詢集合

查詢某個元素所在的集合,用根結點下標表示

演算法:

  1. 從陣列中找到該元素的下標
  2. 根據該元素的Parent找到樹根結點的下標
// 在陣列S中查詢值為X的元素所屬的集合
int Find(SetType S[], ElementType X) {
    int
i; for (i = 0; i < MaxSize && S[i].Data != X; i++); // 將i定位到X所在下標 if (i > MaxSize) // 未找到X,返回-1 return -1; for (; S[i].Parent >= 0; i = S[i].Parent); //將i定位到x所在集合的根結點下標 return i; }

集合的並運算

基本實現

演算法:

  1. 分別找到X1和X2兩個元素所在集合樹的根結點
  2. 如果它們不同根,則將其中一個根結點的父結點指標設定成另一個根結點的陣列下標
void Union(SetType S[], ElementType X1, ElementType X2) {
    int Root1, Root2;

    Root1 = Find(X1);
    Root2 = Find(X2);

    if (Root1 != Root2)     // 當X1和X2不屬於同一集合時才需要合併
        S[Root2].Parent = Root1;
}

優化

  1. 在儲存時,使用Parent域進行集合數量的記錄。例如1個元素,Parent為-1;7個元素Parent為-7
  2. 合併時,採用小的集合合併到相對大的集合中