日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

不相交集的求并算法(按集合大小求并+按高度求并)

發布時間:2023/12/3 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 不相交集的求并算法(按集合大小求并+按高度求并) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【0】README

0.1)本文總結于 數據結構與算法分析, 但源代碼均為原創,旨在實現 不相交集ADT的兩個操作:合并集合union+查找集合find;
0.2) 不相交集ADT 的 Introduction , 參見 http://blog.csdn.net/PacosonSWJTU/article/details/49716905


【1】靈巧求并算法——按集合大小求并

1.1)大小求并法定義:上面的Union執行是相當任意的, 通過使第二棵樹 成為第一棵樹的子樹而完成合并;對其的改進是借助任意的方法打破現有關系, 使得總讓較小的樹成為較大樹的子樹,我們把這種方法叫做 大小求并法
1.2)可以看到, 如果Union 操作都是按照大小求并的話,那么任何節點的深度均不會超過 logN;
1.3)首先注意節點的深度為0, 然后它的深度隨著一次 Union 的結果而增加的時候,該節點則被置于至少是 它以前所在樹兩倍大的一棵樹上;因此,它的深度最多可以增加 logN次;

  • 1.3.2) Find 操作 的運行時間為 O(logN), 而連續M次操作則花費 O(MlogN);
  • 1.3.3) 下圖指出在16次Union操作后可能得到這種最壞的樹;而且如果所有的Union都對相等大小的樹進行, 那么這樣的樹是會得到的;

1.4)為了實現這種方法, 我們需要記住每個樹的大小。由于我們實際上只使用一個數組,因此可以讓每個根的數組元素包含它 的樹的大小的負值;
1.5)已經證明:若使用按大小求并則連續 M次運算需要 O(M)平均時間, 這是因為 當隨機的Union執行時, 整個算法一般只有一些很小的集合(通常是一個元素)與 大 集合 合并;

1.6)souce code + printing

  • 1.6.1)download source code :
    https://github.com/pacosonTang/dataStructure-algorithmAnalysis/blob/master/chapter8/p203_unionBySize.c
  • Source Code Statements:
    • S1)顯然,本源代碼只對元素的size進行了加,沒有減;因為我想的話, 元素只能合并一次,也即是元素C起初合并到了集合A,就不能再次合并到集合B, 元素C就一直屬于集合A的子集了;
    • S2)當然,這個代碼只是 大致上實現了按大小求并的思想,如果元素C還可以再次合并到其他集合的話,這就涉及到集合根元素的size的加減問題了;需要的話,添加之即可;
  • 1.6.2)souce code at a glance
#include <stdio.h> #include <malloc.h>#define ElementType int #define Error(str) printf("\n error: %s \n",str) struct UnionSet; typedef struct UnionSet* UnionSet;// we adopt the child-sibling expr struct UnionSet {int parent;int size;ElementType value; };UnionSet makeEmpty(); UnionSet* initUnionSet(int size, ElementType* data); void printSet(UnionSet* set, int size); void printArray(ElementType data[], int size); int find(ElementType index, UnionSet* set);// initialize the union set UnionSet* initUnionSet(int size, ElementType* data) {UnionSet* set; int i;set = (UnionSet*)malloc(size * sizeof(UnionSet));if(!set){Error("out of space, from func initUnionSet"); return NULL;} for(i=0; i<size; i++){set[i] = makeEmpty();if(!set[i])return NULL;set[i]->value = data[i];}return set; }// allocate the memory for the single UnionSet and evaluate the parent and size -1 UnionSet makeEmpty() {UnionSet temp;temp = (UnionSet)malloc(sizeof(struct UnionSet));if(!temp){Error("out of space, from func makeEmpty!"); return NULL;}temp->parent = -1;temp->size = 1;return temp; }// merge set1 and set2 by size void setUnion(UnionSet* set, int index1, int index2) {//judge whether the index1 or index2 equals to -1 ,also -1 represents the rootif(index1 != -1)index1 = find(index1, set);if(index2 != -1)index2 = find(index2, set);if(set[index1]->size > set[index2]->size){set[index2]->parent = index1;set[index1]->size += set[index2]->size;}else{set[index1]->parent = index2;set[index2]->size += set[index1]->size;} } //find the root of one set whose value equals to given value int find(ElementType index, UnionSet* set) {UnionSet temp; while(1){temp = set[index];if(temp->parent == -1)break;index = temp->parent;}return index; } int main() {int size;UnionSet* unionSet;ElementType data[] = {110, 245, 895, 658, 321, 852, 147, 458, 469, 159, 347, 28};size = 12;printf("\n\t====== test for union set by size ======\n");//printf("\n\t=== the initial array is as follows ===\n");//printArray(data, size); printf("\n\t=== the init union set are as follows ===\n");unionSet = initUnionSet(size, data); // initialize the union set overprintSet(unionSet, size);printf("\n\t=== after union(1,5) + union(2,5) + union(3,4) + union(4,5) ===\n");setUnion(unionSet, 1, 5);setUnion(unionSet, 2, 5);setUnion(unionSet, 3, 4);setUnion(unionSet, 4, 5);printSet(unionSet, size);printf("\n\t=== after union(9,8) + union(7,6) + union(3,6) ===\n");setUnion(unionSet, 9, 8);setUnion(unionSet, 7, 6);setUnion(unionSet, 3, 6); printSet(unionSet, size);return 0; }void printArray(ElementType data[], int size) {int i;for(i = 0; i < size; i++) printf("\n\t data[%d] = %d", i, data[i]); printf("\n\n"); } void printSet(UnionSet* set, int size) {int i;UnionSet temp;for(i = 0; i < size; i++){ temp = set[i];printf("\n\t parent[%d] = %d", i, temp->parent); }printf("\n"); }
  • 1.6.3)printing result

【2】靈巧求并算法——按集合高度求并

2.1)按高度求并定義: 另外一種方法是按照高度求并(按照高度求并是按大小求并的簡單修改)(推薦)
2.2)它同樣保證所有的樹的深入最多是 O(logN)。我們使得 淺的樹 成為深 的樹的子樹,這是一種平緩算法, 因為只有當兩顆相等深度的樹求并時樹的高度才會增加(此時樹的高度增加1)。
2.3)source code + printing result

  • 2.3.1)download source code :
    https://github.com/pacosonTang/dataStructure-algorithmAnalysis/blob/master/chapter8/p205_unionByHeight.c

  • 2.3.2)source code at a glance:

#include <stdio.h> #include <malloc.h>#define ElementType int #define Error(str) printf("\n error: %s \n",str) struct UnionSet; typedef struct UnionSet* UnionSet;// we adopt the depth-sibling expr struct UnionSet {int parent;int height;ElementType value; };UnionSet makeEmpty(); UnionSet* initUnionSet(int depth, ElementType* data); void printSet(UnionSet* set, int depth); void printArray(ElementType data[], int depth); int find(ElementType index, UnionSet* set);// initialize the union set UnionSet* initUnionSet(int size, ElementType* data) {UnionSet* set; int i;set = (UnionSet*)malloc(size * sizeof(UnionSet));if(!set){Error("out of space, from func initUnionSet"); return NULL;} for(i=0; i<size; i++){set[i] = makeEmpty();if(!set[i])return NULL;set[i]->value = data[i];}return set; }// allocate the memory for the single UnionSet and evaluate the parent and depth -1 UnionSet makeEmpty() {UnionSet temp;temp = (UnionSet)malloc(sizeof(struct UnionSet));if(!temp){Error("out of space, from func makeEmpty!"); return NULL;}temp->parent = -1;temp->height = 0;return temp; }// merge set1 and set2 by depth void setUnion(UnionSet* set, int index1, int index2) {//judge whether the index1 or index2 equals to -1 ,also -1 represents the rootif(index1 != -1)index1 = find(index1, set);if(index2 != -1)index2 = find(index2, set);if(set[index1]->height > set[index2]->height) set[index2]->parent = index1; else if(set[index1]->height < set[index2]->height) set[index1]->parent = index2; else{set[index1]->parent = index2;set[index2]->height++; // only if the height of both of subtrees is equal, the height increases one} } //find the root of one set whose value equals to given value int find(ElementType index, UnionSet* set) {UnionSet temp; while(1){temp = set[index];if(temp->parent == -1)break;index = temp->parent;}return index; } int main() {int size;UnionSet* unionSet;ElementType data[] = {110, 245, 895, 658, 321, 852, 147, 458, 469, 159, 347, 28};size = 12;printf("\n\t====== test for union set by depth ======\n");//printf("\n\t=== the initial array is as follows ===\n");//printArray(data, depth); printf("\n\t=== the init union set are as follows ===\n");unionSet = initUnionSet(size, data); // initialize the union set overprintSet(unionSet, size);printf("\n\t=== after union(0, 1) + union(2, 3) + union(4, 5) + union(6, 7) + union(8, 9) + union(10 ,11) ===\n");setUnion(unionSet, 0, 1);setUnion(unionSet, 2, 3);setUnion(unionSet, 4, 5);setUnion(unionSet, 6, 7);setUnion(unionSet, 8, 9); setUnion(unionSet, 10, 11); printSet(unionSet, size);printf("\n\t=== after union(1, 3) + union(5, 7) + union(9, 11) ===\n");setUnion(unionSet, 1, 3);setUnion(unionSet, 5, 7);setUnion(unionSet, 9, 11);printSet(unionSet, size); printf("\n\t=== after union(3, 7) + union(7, 11) ===\n");setUnion(unionSet, 3, 7);setUnion(unionSet, 7, 11); printSet(unionSet, size); return 0; }void printArray(ElementType data[], int size) {int i;for(i = 0; i < size; i++) printf("\n\t data[%d] = %d", i, data[i]); printf("\n\n"); } void printSet(UnionSet* set, int size) {int i;UnionSet temp;for(i = 0; i < size; i++){ temp = set[i];printf("\n\t parent[%d] = %d", i, temp->parent); }printf("\n"); }
  • 2.3.3)printing results:

總結

以上是生活随笔為你收集整理的不相交集的求并算法(按集合大小求并+按高度求并)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。