版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
集合及其表示等價(jià)類與并查集靜態(tài)搜索表二叉搜索樹最優(yōu)二叉搜索樹AVL樹小結(jié)第七章集合與搜索集合及其表示第七章集合與搜索1集合基本概念集合及其表示集合是成員(對象或元素)的一個(gè)群集。集合中的成員可以是原子(單元素),也可以是集合。集合的成員必須互不相同。在算法與數(shù)據(jù)結(jié)構(gòu)中所遇到的集合,其單元素通常是整數(shù)、字符、字符串或指針,且同一集合中所有成員具有相同的數(shù)據(jù)類型。colour={red,orange,yellow,green,black,blue,purple,white}name={“An”,“Cao”,“Liu”,“Ma”,“Peng”,“Wang”,“zhang”}集合基本概念集合及其表示集合是成員(對象或元素)的一個(gè)群集。2集合中的成員一般是無序的,沒有先后次序關(guān)系。但在表示它時(shí),常常寫在一個(gè)序列里。我們常設(shè)定集合中的單元素具有線性有序關(guān)系,此關(guān)系可記作“<”,表示“優(yōu)先于”。若a,b是集合中的兩個(gè)單元素,則a<b,a==b,a>b三者必居其一;若a,b,c是集合中的三個(gè)單元素,且a>b,b>c,則a>c。(傳遞性)整數(shù)、字符和字符串都有一個(gè)自然的線性順序。而指針也可以依據(jù)其在序列中安排的位置給予一個(gè)線性順序。集合操作有求集合的并、交、差、判存在等。集合中的成員一般是無序的,沒有先后次序關(guān)系。但在表示它時(shí),常3集合運(yùn)算的文氏(Venn)圖集合(Set)的抽象數(shù)據(jù)類型Template<classType>class
Set{
Set(intMaxSetSize):MaxSize(MaxSetSize);
void
MakeEmpty(Set
&s);
int
AddMember(Set
&s,constTypex);
intDelMember(Set
&s,constType
&x);集合運(yùn)算的文氏(Venn)圖集合(Set)的抽象數(shù)據(jù)類型Te4
void
Assign
(Set&s1,
Set&s2
);
void
Union
(Set&s1,
Set&s2
);
voidIntersection
(Set&s1,
Set&s2
);
void
Difference
(Set&s1,
Set&s2
);
int
Contains(Set
&s,constType
&
x);
intEqual(Set
&s1,Set&s2);
int
SubSet(Set
&s1,Set&s2
);}voidAssign(Set&s1,Se5用位向量實(shí)現(xiàn)集合抽象數(shù)據(jù)類型集合的位向量(bitVector)類的定義#include<assert.h>constint
DefaultSize=100;classSet{
當(dāng)集合是全集合{0,1,2,…,n}的一個(gè)子集,且n是不大的整數(shù)時(shí),可用位(0,1)向量來實(shí)現(xiàn)集合。當(dāng)全集合是由有限的可枚舉的成員組成的集合時(shí),可建立全集合成員與整數(shù)0,1,2,…的一一對應(yīng)關(guān)系,用位向量來表示該集合的子集。用位向量實(shí)現(xiàn)集合抽象數(shù)據(jù)類型集合的位向量(bitVecto6private:int*bitVector;
int
MaxSize;public:
Set(intMaxSetSize=DefaultSize);~Set(){delete[]bitVector;}
void
MakeEmpty(){for(int
i=0;
i<MaxSize;
i++)
bitVector[i]=0;
}
intAddMember(constintx);
int
DelMember(constintx);
Set&operator=(Set
&right);
private:7
Set&operator+(Set
&
right);
Set&operator*(Set
&
right);Set&operator
-(Set
&
right);
int
Contains(constint
x);
int
SubSet(Set
&
right);
intoperator==(Set
&right);};使用示例
Sets1,s2,s3,s4,s5;
intindex,equal;
//構(gòu)造集合
for(int
k=0;
k<10;
k++)//集合賦值
{
s1.AddMember(k);
s2.AddMember(k+7);}
//s1:{0,1,2,…,9},s2:{7,8,9,…,16}Set&operator+(Set&ri8
s3=s1+s2;//求s1與s2的并{0,1,…,16}
s4=s1*s2;//求s1與s2的交{
7,8,9}
s5=s1-
s2;//求s1與s2的差{0,1,2,3,4,5,6}
index=s1.SubSet(s4);//求s4在s1中首次匹配
cout<<index<<endl;//位置,index=7
equal=s1==s2;
//集合s1與s2比較相等
cout<<equal<<endl;
//equal為0,兩集合不等用位向量實(shí)現(xiàn)集合時(shí)部分操作的實(shí)現(xiàn)Set::Set(int
MaxSetSize):
MaxSize(MaxSetSize){
assert(MaxSize>0);
bitVector=newint[MaxSize];
assert(bitVector!=0);
s3=s1+s2;//求s1與s2的9for(int
i=0;
i<MaxSize;
i++)bitVector[i]=0;}intSet::Addmember(constint
x){
assert(x>=0&&
x<MaxSize);
if(!bitVector[x]){
bitVector[x]=1;
return1;
}
return0;}int
Set::DelMember(constint
x){
assert(x>=0&&
x<MaxSize);
if(bitVector[x]){
bitVector[x]=0;
return1;
}
return0; }for(inti=0;i<MaxSi10Set&
Set::operator=(Set&
right){
assert(MaxSize==right.MaxSize);for(int
i=0;
i<MaxSize;
i++)
bitVector[i]=right.bitVector[i]; return*this;}Set&
Set::operator+(Set&
right){
assert(MaxSize==right.MaxSize);
for(int
i=0;
i<MaxSize;
i++)
bitVector[i]=bitVector[i]||right.bitVector[i];return*this;}Set&Set::operator=(Set&11Set&
Set::operator*(Set
&right){
assert(MaxSize==right.MaxSize);
for(inti=0;
i<MaxSize;
i++)
bitVector[i]=bitVector[i]&&
right.bitVector[i];return*this;}Set&
Set::operator
-(Set&
right){
assert(MaxSize==right.MaxSize);
for(inti=0;
i<MaxSize;
i++)
bitVector[i]=bitVector[i]&&!right.bitVector[i];return*this;}
Set&Set::operator*(Set&12int
Set::Contains(constint
x){
assert(x>=0&&x<MaxSize);
returnbitVector[x]; }intSet::operator
==(Set&
right){
assert(MaxSize==right.MaxSize);
for(inti=0;
i<MaxSize;i++)
if(bitVector[i]!=right.bitVector[i])return0;
return1;}int
Set::SubSet(Set&
right){
assert(MaxSize==right.MaxSize);intSet::Contains(constin13
for(int
i=0;
i<MaxSize;i++)
if(bitVector[i]&&!right.bitVector[i])return0;
return1;
}用有序鏈表實(shí)現(xiàn)集合的抽象數(shù)據(jù)類型用帶表頭結(jié)點(diǎn)的有序鏈表表示集合for(inti=0;i<MaxSiz14用有序鏈表來表示集合時(shí),鏈表中的每個(gè)結(jié)點(diǎn)表示集合的一個(gè)成員。各結(jié)點(diǎn)所表示的成員e0,e1,…,en
在鏈表中按升序排列,即e0<e1<…<en。在一個(gè)有序鏈表中尋找一個(gè)集合成員時(shí),一般不用搜索整個(gè)鏈表,搜索效率可以提高很多。集合成員可以無限增加。因此,用有序鏈表可以表示無窮全集合的子集。集合的有序鏈表類的定義template<classType>classSetList;
用有序鏈表來表示集合時(shí),鏈表中的每個(gè)結(jié)點(diǎn)表示集合的一個(gè)成員。15template<classType>
classSetNode{ friendclassSetList<Type>;public:
SetNode(constType&item):
data(item),link(NULL); private:
Typedata;
SetNode<Type>*link;};template<classType>class
SetList
{private:
SetNode<Type>*first,*last;public:template<classType>classSe16SetList();
void
MakeEmpty();
intAddMember(constType&
x);int
DelMember(constType&
x);
SetList<Type>&operator=(SetList<Type>&
right);
SetList<Type>&operator+(SetList<Type>&
right);
SetList<Type>&operator*(SetList<Type>&
right);
SetList<Type>&operator-(SetList<Type>&
right);int
Contains(constType&x);
SetList();17int
operator
==(SetList<Type>&
right);
Type&
Min();
Type&
Max(); }集合構(gòu)造函數(shù)template<classType>voidSetList<Type>::SetList(){
SetNode<Type>*first=*last=
new
SetNode<Type>(0);
}intoperator==(SetList<18集合的搜索、加入和刪除操作template<classType>intSetList<Type>::Contains(constType&
x){
SetNode<Type>*temp=first→link;
while(temp!=NULL
&&
temp→data<x)
temp=temp→link;
if(temp!=NULL
&&
temp→data==x)
return1;
elsereturn0;}集合的搜索、加入和刪除操作19template<classType>int
SetList<Type>::AddMember(constType&x){SetNode<Type>*p=first→link,*q=first;while(p!=NULL
&&
p→data<x)
{q=p;
p=p→link;
}
if(p!=NULL&&p→data==x)return0;
SetNode<Type>*s=new
SetNode(x);
s→link=p;
q→link=s;
if(p==NULL)last=s;
return1;}template<classType>intSetL20template<classType>intSetList<Type>::DelMember(constType&
x){
SetNode<Type>*p=first→link,*q=first;
while(p!=NULL&&
p→data<x)
{
q=p;
p=p→link;
}
if(p!=NULL
&&
p→data==x){
q→link=p→link;
if(p==last)last
=q;
delete
p;
return1;}
elsereturn0;}template<classType>intSetL21用有序鏈表表示集合時(shí)的幾個(gè)重載函數(shù)template<classType>SetList<Type>&SetList<Type>::operator=(SetList<Type>&
right){
SetNode<Type>*pb=right.first→link;
SetNode<Type>*pa=first=newSetNode<Type>;
while(pb!=NULL){
pa→link=new
SetNode<Type>(pb→data);
pa=pa→link;
pb=pb→link;
}
pa→link=NULL;
last=pa;return*this; }用有序鏈表表示集合時(shí)的幾個(gè)重載函數(shù)22template<classType>SetList<Type>&
SetList<Type>::operator+(SetList<Type>&right){
SetNode<Type>*pb=right.first→link;
SetNode<Type>*pa=first→link;
SetNode<Type>*pc=first;
while(pa!=NULL
&&
pb!=NULL){if(pa→data==pb→data)
{pc→link=pa;
pa=pa→link;
pb=pb→link;
}
elseif(pa→data<pb→data)
{
pc→link=pa;
pa=pa→link;
}
elsetemplate<classType>23
{pc→link=new
SetNode<Type>(pb→data);
pb=pb→link;
}pc=pc→link;}if(pa!=NULL)pc→link=pa;else{while(pb!=NULL){
pc→link=new
SetNode<Type>(pb→data);pc=pc→link;
pb=pb→link;
}pc→link=NULL;
last=pc;}return*this;}{pc→link=newSetN24template<classType>SetList<Type>&
SetList<Type>::operator*(SetList<Type>&right){
SetNode<Type>*pb=right.first→link;
SetNode<Type>*pa=first→link;
SetNode<Type>*pc=first;
while(pa!=NULL
&&
pb!=NULL){
if(pa→data==pb→data)
{pc=pc→link;
pa=pa→link;
pb=pb→link;
}
elseif(pa→data<pb→data)
{
pc→link=pa→link;
delete
pa;
pa=pc→link;
}
else
pb=pb→link;
}
template<classType>25while(pa!=NULL){
pc→link=pa→link;
delete
pa;
pa=pc→link;
}
last=pc;return*this;}template<classType>SetList<Type>&
SetList<Type>::operator
-(SetList<Type>&right){
SetNode<Type>*pb=right.first→link;
SetNode<Type>*pa=first→link;
while(pa!=NULL){26
SetNode<Type>*pc=first; while(pa!=NULL
&&pb!=NULL){
if(pa→data==pb→data)
{
pc→link=pa→link;
delete
pa;
pa=pc→link;
pb=pb→link;
}elseif(pa→data<pb→data)
{
pc=pc→link;
pa=pa→link;
}
else
pb=pb→link;
}
if(pa==NULL)last=pc;return*this;}SetNode<Type>*pc=first;27template<classType>intSetList<Type>::operator==(SetList<Type>&
right){SetNode<Type>*pb=right.first→link;
SetNode<Type>*pa=first→link;
while(pa!=NULL
&&
pb!=NULL)
if(pa→data==pb→data)
{pa=pa→link;
pb=pb→link;
}elsereturn0;
if(pa!=NULL
||
pb!=NULL)return0;
return1;}template<classType>intSetL28等價(jià)關(guān)系與等價(jià)類(EquivalenceClass)等價(jià)類與并查集在求解實(shí)際應(yīng)用問題時(shí)常會(huì)遇到等價(jià)類問題。從數(shù)學(xué)上看,等價(jià)類是一個(gè)對象(或成員)的集合,在此集合中所有對象應(yīng)滿足等價(jià)關(guān)系。若用符號“”表示集合上的等價(jià)關(guān)系,那么對于該集合中的任意對象x,y,
z,下列性質(zhì)成立:自反性:xx(即等于自身)。對稱性:若x
y,則y
x。傳遞性:若x
y且y
z,則x
z。因此,等價(jià)關(guān)系是集合上的一個(gè)自反、對稱、傳遞的關(guān)系。等價(jià)關(guān)系與等價(jià)類(EquivalenceClass)等價(jià)類29
“相等”(=)就是一種等價(jià)關(guān)系,它滿足上述的三個(gè)特性。一個(gè)集合S
中的所有對象可以通過等價(jià)關(guān)系劃分為若干個(gè)互不相交的子集S1,S2,S3,…,它們的并就是
S。這些子集即為等價(jià)類。確定等價(jià)類的方法分兩步走。第一步,讀入并存儲(chǔ)所有的等價(jià)對(i,j);第二步,標(biāo)記和輸出所有的等價(jià)類?!跋嗟取?=)就是一種等價(jià)關(guān)系,它滿足上述的三個(gè)特30void
equivalence(){
初始化;
while等價(jià)對未處理完
{讀入下一個(gè)等價(jià)對
(i,j);存儲(chǔ)這個(gè)等價(jià)對
;}
輸出初始化;
for(尚未輸出的每個(gè)對象)
輸出包含這個(gè)對象的等價(jià)類
;}給定集合
S={0,1,2,3,4,5,6,7,8,9,10,11},及如下等價(jià)對:
0
4,3
1,6
10,8
9,7
4,
6
8,3
5,2
11,11
0voidequivalence(){給定集合S=31初始
{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11}0
4
{0,4},{1},{2},{3},{5},{6},{7},{8},{9},{10},{11}3
1
{0,4},{1,3},{2},{5},{6},{7},{8},{9},{10},{11}6
10{0,4},{1,3},{2},{5},{6,10},{7},{8},{9},{11}
8
9
{0,4},{1,3},{2},{5},{6,10},{7},{8,9},{11}7
4
{0,4,7},{1,3},{2},{5},{6,10},{8,9},{11}6
8
{0,4,7},{1,3},{2},{5},{6,8,9,10},{11}3
5
{0,4,7},{1,3,5},{2},{6,8,9,10},{11}2
11{0,4,7},{1,3,5},{2,11},{6,8,9,10}11
0{0,2,4,7,11},{1,3,5},{6,8,9,10}初始{0},{1},{2},{3},{4},{5},{6}32確定等價(jià)類的鏈表方法
設(shè)等價(jià)對個(gè)數(shù)為m,對象個(gè)數(shù)為n。一種可選的存儲(chǔ)表示為單鏈表。可為集合的每一對象建立一個(gè)帶表頭結(jié)點(diǎn)的單鏈表,并建立一個(gè)一維的指針數(shù)組seq[n]作為各單鏈表的表頭結(jié)點(diǎn)向量。seq[i]是第i個(gè)單鏈表的表頭結(jié)點(diǎn),第i個(gè)單鏈表中所有結(jié)點(diǎn)的data域存放在等價(jià)對中與i等價(jià)的對象編號。
當(dāng)輸入一個(gè)等價(jià)對(i,j)后,就將集合元素i鏈入第j個(gè)單鏈表,且將集合元素j鏈入第i個(gè)單鏈表。在輸出時(shí),設(shè)置一個(gè)布爾數(shù)組out[n],用out[i]標(biāo)記第i個(gè)單鏈表是否已經(jīng)輸出。
確定等價(jià)類的鏈表方法設(shè)等價(jià)對個(gè)數(shù)為m,對象個(gè)數(shù)為n。33void
equivalence(){
讀入n;
將seq
初始化為
0
且將
out
初始化為
False;
while等價(jià)對未處理完
{
讀入下一個(gè)等價(jià)對(i,j);
將
j
鏈入
seq[i]鏈表;將i
鏈入
seq[j]鏈表;
}
for(i=0;i<n;i++) //檢測所有對象
if(out[i]==False){//若對象i未輸出
out[i]=True;//對象i做輸出標(biāo)志
輸出包含對象i的等價(jià)類;
}}voidequivalence(){34算法的輸出從編號i=0的對象開始,對所有的對象進(jìn)行檢測。在i=0時(shí),循第0個(gè)單鏈表先找出形式為(0,j)的等價(jià)對,把0和j作為同一個(gè)等價(jià)類輸出。再根據(jù)等價(jià)關(guān)系的傳遞性,找所有形式為(j,k)的等價(jià)對,把k也納入包含0的等價(jià)類中輸出。如此繼續(xù),直到包含0的等價(jià)類完全輸出為止。接下來再找一個(gè)未被標(biāo)記的編號,如i=1,該對象將屬于一個(gè)新的等價(jià)類,我們再用上述方法劃分、標(biāo)記和輸出這個(gè)等價(jià)類。在算法中使用了一個(gè)棧。每次輸出一個(gè)對象編號時(shí),都要把這個(gè)編號進(jìn)棧,記下以后還要檢測輸出的等價(jià)對象的單鏈表。算法的輸出從編號i=0的對象開始,對所有的對象進(jìn)行檢35輸入所有等價(jià)對后的seq數(shù)組及各單鏈表的內(nèi)容輸入所有等價(jià)對后的seq數(shù)組及各單鏈表的內(nèi)容36等價(jià)類鏈表的定義enum
Boolean
{False,True
};
class
ListNode
{ //定義鏈表結(jié)點(diǎn)類
friendvoidequivalence();
private:
intdata; //結(jié)點(diǎn)數(shù)據(jù)
ListNode*link; //結(jié)點(diǎn)鏈指針
ListNode(intd){
data=d;link=NULL;}
};
typedefListNode*ListNodePtr;等價(jià)類鏈表的定義37建立等價(jià)類算法(輸入等價(jià)對并輸出等價(jià)類)每當(dāng)一個(gè)對象的單鏈表檢測完,就需要從棧中退出一個(gè)指針,以便繼續(xù)輸出等價(jià)類中的其它對象。如果棧空,說明該等價(jià)類所有對象編號都已輸出,再找一個(gè)使得out[i]==False的最小的i,標(biāo)記并輸出下一個(gè)等價(jià)類。void
equivalence(){
ifstream
inFile("equiv.in",
ios::in);
//輸入文件
if(!inFile){
cout
<<“不能打開輸入文件"<<
endl;exit(1);}int
i,j,n;建立等價(jià)類算法(輸入等價(jià)對并輸出等價(jià)類)voidequi38
inFile>>n; //讀入對象個(gè)數(shù)seq=
new
ListNodePtr[n];
out=
new
Boolean[n];//初始化seq和out
for(i=0;i<n;i++)
{seq[i]=0;
out[i]=False;
}inFile>>i>>j; //輸入等價(jià)對(i,j)
while(inFile.good()){ //輸入文件結(jié)束轉(zhuǎn)出循環(huán)
x=
newListNode(j);//創(chuàng)建結(jié)點(diǎn)j
x→link=seq[i];
seq[i]=x;//鏈入第i個(gè)鏈表
y=
new
ListNode(i);//創(chuàng)建結(jié)點(diǎn)iy→link=seq[j];
seq[j]=y;//鏈入第j個(gè)鏈表
inFile>>i>>j; //輸入下一個(gè)等價(jià)對
}inFile>>n; //讀入對象個(gè)39
for
(i=0;i<n;i++)
if(out[i]==False)
{ //未輸出,需要輸出
cout<<endl
<<“Anewclass:”<<i;//輸出
out[i]=True; //作輸出標(biāo)記
ListNode*x=seq[i];
//取第i鏈表頭指針
ListNode*top=NULL;//棧初始化
while
(1)
{ //找類的其它成員
while(x)
{ //處理鏈表,直到x=0
j=x→data; //成員j
if(out[j]==False){//未輸出,輸出
cout
<<“,”<<j;
out[j]=True;
ListNode*y=x→link;x→link=top;top=x; //結(jié)點(diǎn)x進(jìn)棧for(i=0;i<n;i++)
40
x=y; //x進(jìn)到鏈表下一個(gè)結(jié)點(diǎn)
}
else
x=x→link;//已輸出過,跳過
}
if
(top==NULL)break;//棧空退出循環(huán)
else{x=seq[top→data];top=top→link;}
//棧不空,退棧,x是根據(jù)結(jié)點(diǎn)編號回//溯的另一個(gè)鏈表的頭指針
}
}
delete
[]
seq;
delete[]
out;}x=y; //x41并查集(Union-FindSets)建立等價(jià)類的另一種解決方案是先把每一個(gè)對象看作是一個(gè)單元素集合,然后按一定順序?qū)儆谕坏葍r(jià)類的元素所在的集合合并。在此過程中將反復(fù)地使用一個(gè)搜索運(yùn)算,確定一個(gè)元素在哪一個(gè)集合中。能夠完成這種功能的集合就是并查集。它支持以下三種操作:
Union(Root1,Root2)
//并操作;
Find(x)
//搜索操作;
UFSets(s)
//構(gòu)造函數(shù)。一般情形,并查集主要涉及兩種數(shù)據(jù)類型:集合名類型和集合元素的類型。并查集(Union-FindSets)建立等價(jià)類的另一種42
對于并查集來說,每個(gè)集合用一棵樹表示。集合中每個(gè)元素的元素名分別存放在樹的結(jié)點(diǎn)中,此外,樹的每一個(gè)結(jié)點(diǎn)還有一個(gè)指向其雙親結(jié)點(diǎn)的指針。為此,需要有兩個(gè)映射:集合元素到存放該元素名的樹結(jié)點(diǎn)間的對應(yīng);集合名到表示該集合的樹的根結(jié)點(diǎn)間的對應(yīng)。設(shè)S1={0,6,7,8},S2={1,4,9},S3={2,3,5}對于并查集來說,每個(gè)集合用一棵樹表示。43利用并查集來解決等價(jià)問題的步驟如下:利用UFSets操作,建立UFSets型集合this,集合中每一個(gè)元素初始化為0,各自形成一個(gè)單元素子集合,i=1,2,…,n。n是集合中元素個(gè)數(shù)。重復(fù)以下步驟,直到所有等價(jià)對讀入并處理完為止。讀入一個(gè)等價(jià)對[i][j];用Find(i),Find(j)搜索i、j所屬子集合的名字x和y;若x
y.用Union(x,y)或Union(y,x)將它們合并,前者的根在x;后者的根在y。利用并查集來解決等價(jià)問題的步驟如下:利用UFSets操作,44為簡化討論,忽略實(shí)際的集合名,僅用表示集合的樹的根來標(biāo)識集合。如果我們確定了元素i在根為j的樹中,而且j有一個(gè)指向集合名字表中第k項(xiàng)的指針,則集合名即為name[k]。為此,采用樹的雙親表示作為集合存儲(chǔ)表示。集合元素的編號從0到n-1。其中n是最大元素個(gè)數(shù)。在雙親表示中,第i個(gè)數(shù)組元素代表包含集合元素i的樹結(jié)點(diǎn)。根結(jié)點(diǎn)的雙親為-1,表示集合中的元素個(gè)數(shù)。為了區(qū)別雙親指針信息(0),集合元素個(gè)數(shù)信息用負(fù)數(shù)表示。為簡化討論,忽略實(shí)際的集合名,僅用表示集合的樹的根來標(biāo)識集合45S1S2的可能的表示方法下標(biāo)parent集合S1,S2和S3的雙親表示-14-12-1200040123456789S1S2的可能的表示方法下標(biāo)集合S1,S2和S3的雙46constintDefaultSize=10;class
UFSets{//并查集的類定義public:
UFSets(int
s=DefaultSize); ~UFSets(){
delete[]parent;}
constUFSets
&
operator=(UFSets
const&
Value);
void
Union(intRoot1,intRoot2);
intFind(int
x);
voidUnionByHeight(int
Root1,int
Root2); private:
int*parent;
intsize;};constintDefaultSize=10;47UFSets::UFSets(int
s){//構(gòu)造函數(shù)
size=s;
parent=newint[size+1];
for(int
i=0;
i<=size;
i++)parent[i]=-1;
}unsignedint
UFSets::Find(int
x){//搜索操作
if(parent[x]<=0)return
x;
elsereturnFind(parent[x]);}void
UFSets::Union(int
Root1,int
Root2){//并
parent[Root2]=Root1;//Root2指向Root1}UFSets::UFSets(ints){48Find和Union操作性能不好。假設(shè)最初n個(gè)元素構(gòu)成n棵樹組成的森林,parent[i]=-1。做處理Union(n-2,n-1),…,
Union(1,2),Union(0,1)后,將產(chǎn)生如圖所示的退化的樹。
執(zhí)行一次Union操作所需時(shí)間是O(1),n-1次Union操作所需時(shí)間是O(n)。若再執(zhí)行Find(0),Find(1),…,Find(n-1),
若被搜索的元素為i,完成Find(i)操作需要時(shí)間為O(i),完成n次搜索需要的總時(shí)間將達(dá)到Find和Union操作性能不好。假設(shè)最初n個(gè)元素構(gòu)成49為避免產(chǎn)生退化的樹,改進(jìn)方法是先判斷兩集合中元素的個(gè)數(shù),如果以
i為根的樹中的結(jié)點(diǎn)個(gè)數(shù)少于以
j為根的樹中的結(jié)點(diǎn)個(gè)數(shù),即parent[i]>parent[j],則讓
j成為i的雙親,否則,讓i成為j的雙親。此即Union的加權(quán)規(guī)則。Union操作的加權(quán)規(guī)則parent[0](==-4)<parent[4](==-3)為避免產(chǎn)生退化的樹,改進(jìn)方法是先判斷兩集合中元素的個(gè)數(shù),如果50void
UFSets::WeightedUnion(intRoot1,intRoot2){//按Union的加權(quán)規(guī)則改進(jìn)的算法
inttemp=parent[Root1]+parent[Root2];if(parent[Root2]<parent[Root1]){
parent[Root1]=Root2;//Root2中結(jié)點(diǎn)數(shù)多
parent[Root2]=temp;//Root1指向Root2}
else{
parent[Root2]=Root1;//Root1中結(jié)點(diǎn)數(shù)多
parent[Root1]=temp;//Root2指向Root1
}}voidUFSets::51
使用加權(quán)規(guī)則得到的樹使用加權(quán)規(guī)則得到的樹52使用并查集處理等價(jià)對,形成等價(jià)類的過程使用并查集處理等價(jià)對,形成等價(jià)類的過程53Union操作的折疊規(guī)則為進(jìn)一步改進(jìn)樹的性能,可以使用如下折疊規(guī)則來“壓縮路徑”。即:如果j是從i到根的路徑上的一個(gè)結(jié)點(diǎn),且parent[j]
root[j],則把parent[j]置為root[i]。Union操作的折疊規(guī)則為進(jìn)一步改進(jìn)樹的性能,可以使用如下折54int
UFSets::CollapsingFind(int
i){//使用折疊規(guī)則的搜索算法
for(intj=i;
parent[j]>=0;
j=parent[j]);
//讓j
循雙親指針走到根
while(i!=j)//換parent[i]到j(luò)
{int
temp=parent[i];
parent[i]=j;
i=temp;}
returnj;}
使用折疊規(guī)則完成單個(gè)搜索,所需時(shí)間大約增加一倍。但是,它能減少在最壞情況下完成一系列搜索操作所需的時(shí)間。intUFSets::CollapsingFind(55搜索(Search)的概念靜態(tài)搜索表
所謂搜索,就是在數(shù)據(jù)集合中尋找滿足某種條件的數(shù)據(jù)對象。搜索的結(jié)果通常有兩種可能:
搜索成功,即找到滿足條件的數(shù)據(jù)對象。這時(shí),作為結(jié)果,可報(bào)告該對象在結(jié)構(gòu)中的位置,還可進(jìn)一步給出該對象中的具體信息。
搜索不成功,或搜索失敗。作為結(jié)果,也應(yīng)報(bào)告一些信息,如失敗標(biāo)志、失敗位置等。通常稱用于搜索的數(shù)據(jù)集合為搜索結(jié)構(gòu),它是由同一數(shù)據(jù)類型的對象(或記錄)組成。搜索(Search)的概念靜態(tài)搜索表所謂搜索,就是在數(shù)據(jù)集56在每一個(gè)對象中有若干屬性,其中應(yīng)當(dāng)有一個(gè)屬性,其值可唯一地標(biāo)識這個(gè)對象。它稱為關(guān)鍵碼。使用基于關(guān)鍵碼的搜索,搜索結(jié)果應(yīng)是唯一的。但在實(shí)際應(yīng)用時(shí),搜索條件是多方面的,這樣,可以使用基于屬性的搜索方法,但搜索結(jié)果可能不唯一。實(shí)施搜索時(shí)有兩種不同的環(huán)境。
靜態(tài)環(huán)境,搜索結(jié)構(gòu)在執(zhí)行插入和刪除等操作的前后不發(fā)生改變。靜態(tài)搜索表
動(dòng)態(tài)環(huán)境,為保持較高的搜索效率,搜索結(jié)構(gòu)在執(zhí)行插入和刪除等操作的前后將自動(dòng)進(jìn)行調(diào)整,結(jié)構(gòu)可能發(fā)生變化。動(dòng)態(tài)搜索表在每一個(gè)對象中有若干屬性,其中應(yīng)當(dāng)有一個(gè)屬性,其值可唯一地標(biāo)57靜態(tài)搜索表template<classType>classdataList;template<classType>class
Node{friendclassdataList<Type>;public:
Node(constType&value):key
(value){}TypegetKey()const
{return
key;
}
void
setKey(Type
k){
key=k;
}private:
Type
key;
other;};靜態(tài)搜索表58template<classType>class
dataList{public:
dataList(int
sz=10):
ArraySize(sz),
Element(new
Node<Type>[sz]){}
virtual~dataList(){
delete[]Element;}
friendostream
&operator<<(ostream&
OutStream,
const
dataList<Type>
&OutList);
friendistream
&operator>>(istream&
InStream,dataList<Type>
&InList);protected:
Type*Element;
int
ArraySize,CurrentSize;};template<classType>classda59template<classType>class
searchList
:public
dataList<Type>{//作為派生類的靜態(tài)搜索表的類定義public:
searchList(intsz=10):
dataList<Type>(sz){}
virtual~searchList(){}
virtualint
Search(constType&
x)const;};template<classType>classse60template<classType>istream&operator>>(istream&
InStream,dataList<Type>
&
InList){//從輸入流對象InStream輸入數(shù)據(jù)到數(shù)據(jù)表InList
cout<<“輸入數(shù)組當(dāng)前大小
:”;
Instream>>InList.CurrentSize;cout<<“輸入數(shù)組元素值
:\n”;
for(int
i=0;
i<InList.CurrentSize;i++){cout<<“元素”<<i<<“:”;
InStream>>InList.Element[i];}return
InStream;}template<classType>istream61template<classType>ostream&operator<<(ostream&
OutStream,
const
dataList<Type>&
OutList){//將數(shù)據(jù)表OutList內(nèi)容輸出到輸出流對象OutStream
OutStream<<“數(shù)組內(nèi)容
:\n”;
for(int
i=0;
i<OutList.CurrentSize;i++)
OutStream<<OutList.Element[i]<<‘’;
OutStream<<endl;
OutStream<<“數(shù)組當(dāng)前大小
:”<<
OutList.CurrentSize<<endl;
return
OutStream;}template<classType>ostream62衡量一個(gè)搜索算法的時(shí)間效率的標(biāo)準(zhǔn)是:在搜索過程中關(guān)鍵碼的平均比較次數(shù)或平均讀寫磁盤次數(shù)(只適合于外部搜索),這個(gè)標(biāo)準(zhǔn)也稱為平均搜索長度ASL(AverageSearchLength),通常它是搜索結(jié)構(gòu)中對象總數(shù)n或文件結(jié)構(gòu)中物理塊總數(shù)n的函數(shù)。另外衡量一個(gè)搜索算法還要考慮算法所需要的存儲(chǔ)量和算法的復(fù)雜性等問題。在靜態(tài)搜索表中,數(shù)據(jù)對象存放于數(shù)組中,利用數(shù)組元素的下標(biāo)作為數(shù)據(jù)對象的存放地址。搜索算法根據(jù)給定值x,在數(shù)組中進(jìn)行搜索。直到找到x在數(shù)組中的存放位置或可確定在數(shù)組中找不到x為止。衡量一個(gè)搜索算法的時(shí)間效率的標(biāo)準(zhǔn)是:在搜索過程中關(guān)鍵碼的平均63順序搜索
(SequentialSearch)所謂順序搜索,又稱線性搜索,主要用于在線性結(jié)構(gòu)中進(jìn)行搜索。設(shè)若表中有CurrentSize個(gè)對象,則順序搜索從表的先端開始,順序用各對象的關(guān)鍵碼與給定值x進(jìn)行比較,直到找到與其值相等的對象,則搜索成功,給出該對象在表中的位置。若整個(gè)表都已檢測完仍未找到關(guān)鍵碼與x相等的對象,則搜索失敗。給出失敗信息。順序搜索(SequentialSearch)所謂順序搜索64template<classType>intsearchList<Type>::Search(constType&
x)const{//順序搜索的迭代算法,0號元素為監(jiān)視哨
Element[0].setKey(x);
int
i=CurrentSize;
while(Element[i].getKey()!=x)i--;
return
i;}template<classType>intearchList<Type>::Search(constType&
x,int&loc)const{//順序搜索的遞歸算法
if(loc>=CurrentSize)return
-1;
elseif(Element[loc].getKey()==
x)returnloc;elsereturn
Search(x,loc+1);}template<classType>intsear65constint
Size=10;main
(){//順序搜索的主過程searchList<float>
List1(Size);
float
Target;
intLocation;
cin>>List1;
cout<<List1;
//輸入/輸出數(shù)據(jù)表List1
cout<<“搜索浮點(diǎn)數(shù)
:”;
cin>>Target;
if((Location=List1.search(Target))!=0)
cout<<“找到下標(biāo)”<<Location<<endl;
else
cout<<“沒有找到.\n”;}constintSize=10;66順序搜索的平均搜索長度
設(shè)搜索第
i個(gè)元素的概率為pi,搜索到第
i個(gè)元素所需比較次數(shù)為
ci,則搜索成功的平均搜索長度:在順序搜索情形,ci=i+1,i=0,1,,n-1,因此在等概率情形,pi=1/n,
i=0,1,,n-1。
順序搜索的平均搜索長度設(shè)搜索第i個(gè)元素的概率為pi,67基于有序順序表的折半搜索設(shè)n個(gè)對象存放在一個(gè)有序順序表中,并按其關(guān)鍵碼從小到大排好了序。采用對分搜索時(shí),先求位于搜索區(qū)間正中的對象的下標(biāo)mid,用其關(guān)鍵碼與給定值x比較:
Element[mid].getKey()=x,搜索成功;
Element[mid].getKey()>x,把搜索區(qū)間縮小到表的前半部分,再繼續(xù)進(jìn)行對分搜索;
Element[mid].getKey()<x,把搜索區(qū)間縮小到表的后半部分,再繼續(xù)進(jìn)行對分搜索。每比較一次,搜索區(qū)間縮小一半。如果搜索區(qū)間已縮小到一個(gè)對象,仍未找到想要搜索的對象,則搜索失敗。基于有序順序表的折半搜索設(shè)n個(gè)對象存放在一個(gè)有序順序表中,并68搜索成功的例子 搜索失敗的例子搜索成功的例子 搜索失敗的例子69template<classType>class
orderedList
:public
dataList<Type>{//有序表的類定義,繼承了數(shù)據(jù)表public:
orderedList(intsz=10):
dataList<Type>(sz){}
virtual~orderedList(){}
virtualint
Search(constType&
x)const;};
template<classType>classor70temp
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 雞眼病因介紹
- 債務(wù)如何轉(zhuǎn)讓協(xié)議書
- 關(guān)于就業(yè)協(xié)議
- 個(gè)人單位租車協(xié)議
- 1.2《風(fēng)景談》【中職專用】高一語文(高教版2023基礎(chǔ)模塊上冊)
- (2024)年產(chǎn)噸鋰電池負(fù)極材料石墨化項(xiàng)目可行性研究報(bào)告寫作模板(一)
- 2022-2023學(xué)年天津一中高一(上)期末語文試卷
- 2023年天津市南開區(qū)高考語文一模試卷
- 解析:內(nèi)蒙古通遼市科爾沁左翼中旗2024-2025學(xué)年七年級上學(xué)期期中語文試題(原卷版)-A4
- 2024(半成品預(yù)制菜篇)餐飲供應(yīng)鏈指南
- 第26課《詩詞五首:春望》教學(xué)實(shí)錄 統(tǒng)編版語文八年級上冊
- 天津市津南區(qū)2023-2024學(xué)年七年級上學(xué)期期末數(shù)學(xué)測試卷(含答案)
- 田徑大單元教學(xué)計(jì)劃
- 物理化學(xué)題庫(含答案)
- 嵌入式軟件設(shè)計(jì)方案
- 包裝工培訓(xùn)方案范本
- 華為財(cái)務(wù)管理(6版)-華為經(jīng)營管理叢書
- 語言領(lǐng)域核心經(jīng)驗(yàn)學(xué)前兒童語言學(xué)習(xí)與發(fā)展核心經(jīng)驗(yàn)
- 一次性工傷醫(yī)療補(bǔ)助金申請表(新表3)1
- 第七課經(jīng)濟(jì)全球化與中國學(xué)案高中政治選擇性必修一當(dāng)代國際政治與經(jīng)濟(jì)
- 中國傳統(tǒng)制墨工藝研究
評論
0/150
提交評論