slide1 n.
Download
Skip this Video
Loading SlideShow in 5 Seconds..
集合 等价类与并查集 PowerPoint Presentation
Download Presentation
集合 等价类与并查集

Loading in 2 Seconds...

play fullscreen
1 / 49

集合 等价类与并查集 - PowerPoint PPT Presentation


  • 121 Views
  • Uploaded on

集合 等价类与并查集. 第七章 集合. 一、集合. 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}. 集合的实现. 用 数组 实现 用 指针 实现 用 链表 实现 用 位运算 实现 整形集合.

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about '集合 等价类与并查集' - aria


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.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
slide1
集合
  • 等价类与并查集

第七章 集合

slide2
一、集合

A={a,b,c}, B={b,d}

若干个同一类型互不相同的以一定次序排

列的元素

整形集合(整数,字符,枚举,记录)

若干离散有序元素组成的集合

每个元素可以对应唯一一个整数

int(a); //a对应的整数

slide3

集合的运算

a∈A

A∪B={a,b,c,d}

A∩B={b}

A-B={a,c}

slide4
集合的实现

用数组实现

用指针实现

用链表实现

用位运算实现整形集合

slide5
位运算 或 | 与& 非~ 异或^右移位>> 左移位<<

——————————————————

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

x 11100011 y 01110110
x=11100011 y=01110110

x|y 11100011

01110110

11110111

x&y 11100011

01110110

01100010

~x = 00011100

x^y 11100011

01110110

10010101

unsigned short x 10 y 13 z 2 16 x 1010 y 1101
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

slide8
用01数组存储n个整形元素的集合

将n个元素固定成一列,每个下标代表一个元素

每个元素elt的下标可以由int(elt)或用一个公式算出

用一个01数组存储集合

每一位写0或1

0代表某个元素不在集合中,

1代表某个元素在集合中,

n个元素最少用多长的数组呢?

unsigned short 16 k unsigned short k 16
一个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];

slide10

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);

slide11
两集合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号位

slide12

#ifndef SET_CLASS

#define SET_CLASS

#include <iostream.h>

#include <stdlib.h>

enumErrorType

{

InvalidMember, ExpectRightBrace, MissingValue,

MissingComma, InvalidChar, MissingLeftBrace,

InvalidInputData, EndOfFile, OutOfMemory,

InvalidMemberRef, SetsDifferentSize

};

slide13
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);

slide14
~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);

};

slide15
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;

slide16
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);

}

slide17
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);

}

slide18
// 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;

}

slide19
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];

}

slide20
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;

}

slide21
// 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);

}

slide22
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;

}

slide23
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;

}

slide24
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;

}

slide25
// 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);

}

slide26
// 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);

}

slide27
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);

slide28
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;

slide29
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;

}

slide30
if (istr.get(c) == 0)

x.Error(EndOfFile);

}

if (haveComma == 1)

x.Error(MissingValue);

return istr;

}

slide31
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; }

slide33
打印素数

#include <iostream.h>

#include <iomanip.h>

#pragma hdrstop

#include "set.h" // use the Set class

slide34
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;

}

slide35
voidmain(void)

{

int n;

cout << "Enter n: ";

cin >> n;

cout << endl;

PrintPrimes(n);

}

slide36

二、等价类和并查集

一个等价关系把一个集合划分成互不相交的等价类

设 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}

怎样用一个算法实现

slide37
用集合运算

先把S的每个元素都做成单点集

再把有关系的集合做并:

每读入一对等价元素a≡b

查找a,b所在的集合,如不同则做并。

slide38
用双亲表示法的树结构表示集合

双亲表示法树表示集合

树根同时作集合名

A

D

B

C

E

F

slide40
双亲表示法结点定义

#define MAX_TREE_SIZE 100

template <class T>

class PNode

{ T data;

int Parent;

public:

PNode(T item, int pr);

T GetData( );

int GetParent( );

}

}

slide41
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);

};

slide42
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;

}

slide43
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;}

union
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

union weightunion
改进Union为WeightUnion

改根结点的权值为集合中元素个数的

相反数-t

两树结合

元素少的树联到元素多的树的根

再将两树根的权相加(两树元素个数相加)

slide46
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;}

}

weightu nion
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

slide48
压缩路径

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;

}

ufset char u u collapsingfind h
压缩路径UFSet<char> u;…………… u.CollapsingFind(H);

A

A

D

H

D

B

C

F

B

C

E

G

E

F

G

H