1 / 49

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

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

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

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

• 等价类与并查集

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}

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

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

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

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

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

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

k*16=n, k=(n+15)/16, k=(n+15)>>4.

unsigned short *member;

member=new unsigned short[k];

15

31

1 1 1 1 1

A={a1,a7,a13,a18,a25}

i=s/16=s>>4;

j=s%16=1 << (s & 15);

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号位

#ifndef SET_CLASS

#define SET_CLASS

#include <iostream.h>

#include <stdlib.h>

enumErrorType

{

InvalidMember, ExpectRightBrace, MissingValue,

MissingComma, InvalidChar, MissingLeftBrace,

InvalidInputData, EndOfFile, OutOfMemory,

InvalidMemberRef, SetsDifferentSize

};

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;

public:

Set(int sz);

Set(const Set<T>& x);

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

};

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;

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

}

template <classT>

int Set<T>::ArrayIndex(const T& elt) const

{

// convert elt to int and shift

returnint(elt) >> 4;

}

template <classT>

{

// use & to find remainder after dividing by

// 16. 0 stays in right-most bit, 15 goes on far left

return 1 << (int(elt) & 15);

}

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

}

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

}

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;

}

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

}

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;

}

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;

}

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;

}

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

}

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

}

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

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;

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

needComma = 1;

haveComma = 0;

break;

}

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

x.Error(EndOfFile);

}

if (haveComma == 1)

x.Error(MissingValue);

return istr;

}

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))] &

{ elt = T(setElt);

if (needComma == 1) ostr << ", " << elt;

else { ostr << elt; needComma = 1; }

} }

ostr << "} ";

return ostr; }

#include <iostream.h>

#include <iomanip.h>

#pragma hdrstop

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

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;

}

voidmain(void)

{

int n;

cout << "Enter n: ";

cin >> n;

cout << endl;

PrintPrimes(n);

}

### 二、等价类和并查集

0≡4，3≡1，6≡10，8≡9，7≡4，6≡8，3≡5，2≡11，11≡0

A

D

B

C

E

F

#define MAX_TREE_SIZE 100

template <class T>

class PNode

{ T data;

int Parent;

public:

PNode(T item, int pr);

T GetData( );

int GetParent( );

}

}

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

};

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;

}

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 的性能分析

n

n-1

2

1

0

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

}

WeightUnion 的性能分析

n

1

0

n-1

2

n-1

n

2

1

0

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;

}

A

A

D

H

D

B

C

F

B

C

E

G

E

F

G

H