1 / 49

集合 等价类与并查集

集合 等价类与并查集. 第七章 集合. 一、集合. A={a,b,c}, B={b,d}. 若干个 同一类型 互不相同 的以 一定次序排 列 的元素 整形 集合 (整数,字符,枚举,记录) 若干 离散 有序元素组成的集合 每个元素可以 对应 唯一一个整数 int(a) ; //a 对应的整数. 集合的运算 a∈A A∪B={a,b,c,d} A∩B={b} A-B={a,c}. 集合的实现. 用 数组 实现 用 指针 实现 用 链表 实现 用 位运算 实现 整形集合.

aria
Download Presentation

集合 等价类与并查集

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 集合 • 等价类与并查集 第七章 集合

  2. 一、集合 A={a,b,c}, B={b,d} 若干个同一类型互不相同的以一定次序排 列的元素 整形集合(整数,字符,枚举,记录) 若干离散有序元素组成的集合 每个元素可以对应唯一一个整数 int(a); //a对应的整数

  3. 集合的运算 a∈A A∪B={a,b,c,d} A∩B={b} A-B={a,c}

  4. 集合的实现 用数组实现 用指针实现 用链表实现 用位运算实现整形集合

  5. 位运算 或 | 与& 非~ 异或^右移位>> 左移位<< —————————————————— x y ~x x|y x&y x^y —————————————————— 0 0 1 0 0 0 0 1 1 1 0 1 1 0 0 1 0 1 1 1 0 1 1 0

  6. x=11100011 y=01110110 x|y 11100011 01110110 11110111 x&y 11100011 01110110 01100010 ~x = 00011100 x^y 11100011 01110110 10010101

  7. unsigned short x=10, y=13,z;//2字节16位//x=1010, y=1101 z=x|y; //z=15 z=x&y; //z=8 z=x^y; //z=7 z=~0<<2; //z=65532 z=~0&(y>>2); //z=3

  8. 用01数组存储n个整形元素的集合 将n个元素固定成一列,每个下标代表一个元素 每个元素elt的下标可以由int(elt)或用一个公式算出 用一个01数组存储集合 每一位写0或1 0代表某个元素不在集合中, 1代表某个元素在集合中, n个元素最少用多长的数组呢?

  9. 一个unsigned short 整数占两个字节16位k个unsigned short 整数占两个字节k*16位 只要一个二进制位就可以存储0,1 k*16=n, k=(n+15)/16, k=(n+15)>>4. 存储n个元素只要k个unsigned short 整数 unsigned short *member; member=new unsigned short[k];

  10. 15 31 1 1 1 1 1 A={a1,a7,a13,a18,a25} 确定一个元素在哪一个字节第几位 第18号元素a18, 在member[1] 2号位 设第s号元素,在member[i] j号位 i=s/16=s>>4; j=s%16=1 << (s & 15);

  11. 两集合A,B的并 按对应字节求或| for(i=0;i<k;i++) C.member[i]= A.member[i] | B.member[i]; 两集合的交 按对应字节求与& for(i=0;i<k;i++) C.member[i]= A.member[i] & B.member[i]; x∈A 只要 A∩{x}非空 A.member[i] & (1<<j); //x在member[i] j号位

  12. #ifndef SET_CLASS #define SET_CLASS #include <iostream.h> #include <stdlib.h> enumErrorType { InvalidMember, ExpectRightBrace, MissingValue, MissingComma, InvalidChar, MissingLeftBrace, InvalidInputData, EndOfFile, OutOfMemory, InvalidMemberRef, SetsDifferentSize };

  13. template <classT> class Set { private: int setrange; // max number of elements in the set int arraysize; unsigned short *member; void Error(ErrorType n) const; int ArrayIndex(constT& elt) const; unsigned short BitMask(constT& elt) const; public: Set(int sz); Set(const Set<T>& x);

  14. ~Set(void); Set<T>& operator= (const Set<T>& rhs); int IsMember(constT& elt); intoperator== (const Set<T>& x) const; Set operator+ (const Set<T>& x) const; // union Set operator* (const Set<T>& x) const; void Insert(constT& elt); // set insertion void Delete(constT& elt); //deletion operations friend istream& operator>> (istream& istr, Set<T>& x); friend ostream& operator<<(ostream&ostr, const Set<T>& x); };

  15. template <classT> void Set<T>::Error (ErrorType n) const { cout << endl; switch(n) { case InvalidMember: cerr << "Invalid set member"; break; case ExpectRightBrace: cerr << "Expect right brace '}'"; break; case MissingValue: cerr<< "Missing a value after a comma"; break; case MissingComma: cerr << "Separate members with a comma";break; case InvalidChar: cerr << "Invalid set character"; break;

  16. case MissingLeftBrace: cerr << "Missing left brace '{'"; break; case InvalidInputData: cerr << "Invalid input data element"; break; case EndOfFile: cerr << "Premature end of file"; break; case OutOfMemory: cerr << "Memory allocation failure"; break; case InvalidMemberRef: cerr << "Invalid member reference"; break; case SetsDifferentSize: cerr << "Sets are not the same size"; break; } cout << endl; exit(1); }

  17. template <classT> int Set<T>::ArrayIndex(const T& elt) const { // convert elt to int and shift returnint(elt) >> 4; } template <classT> unsigned short Set<T>::BitMask(constT& elt) const { // use & to find remainder after dividing by // 16. 0 stays in right-most bit, 15 goes on far left return 1 << (int(elt) & 15); }

  18. // constructor. create an empty set template <classT> Set<T>::Set(int sz): setrange(sz) {// number of unsigned shorts needed to hold set elements arraysize = (setrange+15) >> 4; // allocate the array member = newunsigned short [arraysize]; if (member == NULL) Error(OutOfMemory); // create an empty set by setting all bits to 0 for (int i = 0; i < arraysize; i++) member[i] = 0; }

  19. template <classT> Set<T>::Set(const Set<T>& x) { setrange = x.setrange; arraysize = x.arraysize; member = new unsigned short [arraysize]; if (member == NULL) Error(OutOfMemory); // copy set elements from x for (int i = 0; i < arraysize; i++) member[i] = x.member[i]; }

  20. template <classT> Set<T>::~Set(void) { delete [] member; } template <classT> Set<T>& Set<T>::operator= (const Set<T>& rhs) { if (setrange != rhs.setrange) Error(SetsDifferentSize); // copy set elements from rhs for (int i = 0; i < arraysize; i++) member[i] = rhs.member[i]; return *this; }

  21. // determine whether elt is in the set template <classT> int Set<T>::IsMember(const T& elt) { // is int(elt) in range 0 to setrange-1 ? if (int(elt) < 0 || int(elt) >= setrange) Error(InvalidMemberRef); // return the bit corresponding to elt return member[ArrayIndex(elt)] & BitMask(elt); }

  22. template <classT> int Set<T>::operator= = (const Set<T>& x) const { int retval = 1; // the sets must have the same range if (setrange != x.setrange) Error(SetsDifferentSize); for(int i=0;i < arraysize;i++) if (member[i] != x.member[i]) { retval = 0; break; } return retval; }

  23. template <classT> Set<T> Set<T>::operator+ (const Set<T>& x) const { // the sets must have the same range if (setrange != x.setrange) Error(SetsDifferentSize); // form the union in tmp Set<T> tmp(setrange); // each array element of tmp is the bitwise // OR of the current object and x for (int i = 0; i < arraysize; i++) tmp.member[i] = member[i] | x.member[i]; // return the union return tmp; }

  24. template <classT> Set<T> Set<T>::operator* (const Set<T>& x) const { // the sets must have the same range if (setrange != x.setrange) Error(SetsDifferentSize); // form the intersection in tmp Set<T> tmp(setrange); // each array element of tmp is the bitwise // AND of the current object and x for (int i = 0; i < arraysize; i++) tmp.member[i] = member[i] & x.member[i]; // return the intersection return tmp; }

  25. // insert elt into the set template <classT> void Set<T>::Insert(const T& elt) { // is int(elt) in range 0 to setrange-1 ? if (int(elt) < 0 || int(elt) >= setrange) Error(InvalidMemberRef); // set bit corresponding to elt member[ArrayIndex(elt)] |= BitMask(elt); }

  26. // delete elt from the set template <classT> void Set<T>::Delete(constT& elt) { // is int(elt) in range 0 to setrange-1 ? if (int(elt) < 0 || int(elt) >= setrange) Error(InvalidMemberRef); // clear the bit corresponding to elt. note // that ~BitMask(elt) has a 0 in the bit // we are interested in an 1 in all others member[ArrayIndex(elt)] &= ~BitMask(elt); }

  27. template <classT> istream& operator>> (istream& istr, Set<T>& x) { char c; int haveComma = 0, needComma = 0; T elt; int i; for (i = 0; i < x.arraysize; i++) x.member[i] = 0; c = ' '; // skip leading white space while (c == ' ' || c == '\t' || c == '\n') if (istr.get(c) == 0) x.Error(EndOfFile); if (c != '{') x.Error(MissingLeftBrace); if (istr.get(c) == 0) x.Error(EndOfFile);

  28. while (c != '}') { switch(c) { case' ': case'\t': case'\n': break; case '{': x.Error(ExpectRightBrace); break; case',': if (haveComma == 1) x.Error(MissingValue); else { haveComma = 1; needComma = 0; } break;

  29. default: if (needComma) x.Error(MissingComma); istr.putback(c); if(istr >> elt == 0) x.Error(InvalidInputData); if (int(elt) < 0 || int(elt) >= x.setrange) x.Error(InvalidInputData); x.member[x.ArrayIndex(elt)] |= x.BitMask(elt); needComma = 1; haveComma = 0; break; }

  30. if (istr.get(c) == 0) x.Error(EndOfFile); } if (haveComma == 1) x.Error(MissingValue); return istr; }

  31. template <classT> ostream& operator<< (ostream& ostr, const Set<T>& x) { int i, j, setElt; int needComma = 0; T elt; ostr << "{"; for (setElt = 0; setElt < x.setrange; setElt++) { if (x.member[x.ArrayIndex(T(setElt))] & x.BitMask(T(setElt))) { elt = T(setElt); if (needComma == 1) ostr << ", " << elt; else { ostr << elt; needComma = 1; } } } ostr << "} "; return ostr; }

  32. #endif // SET_CLASS

  33. 打印素数 #include <iostream.h> #include <iomanip.h> #pragma hdrstop #include "set.h" // use the Set class

  34. void PrintPrimes(int n) { Set<int> S(n+1); int m, k, count; for(m=2; m <= n; m++) S.Insert(m); for( m=2;m*m <= n; m++) if( S.IsMember(m)) for( k=m+m; k<= n; k += m) if (S.IsMember(k)) S.Delete(k); count = 1; for(m=2;m <= n;m++) if (S.IsMember(m)) { cout << setw(3) << m << " "; if (count++ % 10 == 0) cout << endl;} cout << endl; }

  35. voidmain(void) { int n; cout << "Enter n: "; cin >> n; cout << endl; PrintPrimes(n); }

  36. 二、等价类和并查集 一个等价关系把一个集合划分成互不相交的等价类 设 S={0,1,2,3,4,5,6,7,8,9,10,11} 0≡4,3≡1,6≡10,8≡9,7≡4,6≡8,3≡5,2≡11,11≡0 则S={0,2,4,7,11}∪{1,3,5}∪{6,8,9,10} 怎样用一个算法实现

  37. 用集合运算 先把S的每个元素都做成单点集 再把有关系的集合做并: 每读入一对等价元素a≡b 查找a,b所在的集合,如不同则做并。

  38. 用双亲表示法的树结构表示集合 双亲表示法树表示集合 树根同时作集合名 A D B C E F

  39. 不交集合的并只要连接两颗树 G A H I J D B C E F G H I J

  40. 双亲表示法结点定义 #define MAX_TREE_SIZE 100 template <class T> class PNode { T data; int Parent; public: PNode(T item, int pr); T GetData( ); int GetParent( ); } }

  41. const int defaultsize=15; template <class T> class UFSet //并查集的类 { PNode<T> *nodes; int size; int Find(int i);///找结点i所在集合的根 public: UFset(int sz=defaultsize ); ~UFSet( ){delete[ ] nodes;} void Union(Titem1, Titem2); int Find(Titem);//找item所在集合的根 void WeightedUnion(Titem1, Titem2); int CollapsingFind(Titem); };

  42. template <class T> int UFSet<T>::Find(int i) {if(i<0||i>=size)return -1; for(int j=i; nodes[j].Parent>=0;j=nodes[j].Parent) ; return j; } template <class T> UFSet<T>::UFSet( int sz) { nodes=new PNode<T>[sz]; size=sz; for(int i=0;i<size;i++) nodes[i].Parent=-1; }

  43. template <class T> int UFSet<T>::Find(Titem) { int i=0; while(nodes[i].Getdata( )!=item)i++; return Find(i) ; } template <class T> void UFSet<T>:: Union( T item1, Titem2) { int root1, root2; if( root1=Find(item1)!=( root2=Find(item2)) nodes[root1].Parent=root2;}

  44. Union 的性能分析 设 S={0,1,2,…,n}, 0≡1≡2≡…≡n-1≡n 作Union(0,1), Union(1,2), …,Union(n-1,n) 得到 n 每个元查找复杂度O(n) 总复杂度O(n2) n-1 … 2 1 0

  45. 改进Union为WeightUnion 改根结点的权值为集合中元素个数的 相反数-t 两树结合 元素少的树联到元素多的树的根 再将两树根的权相加(两树元素个数相加)

  46. template <class T> void UFSet<T>::WeightedUnion(Titem1, Titem2) {int root1=Find(item1), root2=Find( item2); int temp= nodes[root1].Parent+nodes[root2].Parent; if(nodes[root2].Parent<nodes[root1].Parent) {nodes[root1].Parent=root2; nodes[root2].Parent =temp;} else{nodes[root2].Parent=root1; nodes[root1].Parent =temp;} }

  47. WeightUnion 的性能分析 设 S={0,1,2,…,n}, 0≡1≡2≡…≡n-1≡n 作WeightedUnion(0,1), WeightedUnion(1,2), …,WeightedUnion(n-1,n) 变为 n 1 … 0 n-1 2 n-1 n … 2 每个元查找复杂度O(log2n) 总复杂度O(nlog2n) 1 0

  48. 压缩路径 template<class T> int UFSet<T>::CollapsingFind(int i) {int j=Find(i); while(i!=j) { int temp=nodes[i].Parent; nodes[i].Parent=j; i=temp; } return j; }

  49. 压缩路径UFSet<char> u;…………… u.CollapsingFind(H); A A D H D B C F B C E G E F G H

More Related