![《數(shù)據(jù)結(jié)構(gòu)與算法》PPT課堂課件-第8章-集合_第1頁](http://file4.renrendoc.com/view/8ea1b8d25f4211b4d3ff7bde16dc7f6a/8ea1b8d25f4211b4d3ff7bde16dc7f6a1.gif)
![《數(shù)據(jù)結(jié)構(gòu)與算法》PPT課堂課件-第8章-集合_第2頁](http://file4.renrendoc.com/view/8ea1b8d25f4211b4d3ff7bde16dc7f6a/8ea1b8d25f4211b4d3ff7bde16dc7f6a2.gif)
![《數(shù)據(jù)結(jié)構(gòu)與算法》PPT課堂課件-第8章-集合_第3頁](http://file4.renrendoc.com/view/8ea1b8d25f4211b4d3ff7bde16dc7f6a/8ea1b8d25f4211b4d3ff7bde16dc7f6a3.gif)
![《數(shù)據(jù)結(jié)構(gòu)與算法》PPT課堂課件-第8章-集合_第4頁](http://file4.renrendoc.com/view/8ea1b8d25f4211b4d3ff7bde16dc7f6a/8ea1b8d25f4211b4d3ff7bde16dc7f6a4.gif)
![《數(shù)據(jù)結(jié)構(gòu)與算法》PPT課堂課件-第8章-集合_第5頁](http://file4.renrendoc.com/view/8ea1b8d25f4211b4d3ff7bde16dc7f6a/8ea1b8d25f4211b4d3ff7bde16dc7f6a5.gif)
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、1第9章 集合 學(xué)習(xí)要點:9.1 以集合為基礎(chǔ)的抽象數(shù)據(jù)類型 理解集合的概念。 理解以集合為基礎(chǔ)的抽象數(shù)據(jù)類型。 掌握用位向量實現(xiàn)集合的方法。 掌握用鏈表實現(xiàn)集合的方法。29.2 符號表 理解抽象數(shù)據(jù)類型符號表的概念。 掌握數(shù)組實現(xiàn)符號表的方法。 理解開散列和閉散列的概念。 掌握用開散列表實現(xiàn)符號表的方法。 掌握除余法、數(shù)乘法、平方取中法、基數(shù)轉(zhuǎn)換法和隨機(jī)數(shù)法等散列函數(shù)構(gòu)造方法。 掌握采用線性重新散列技術(shù)的閉散列表實現(xiàn)符號表的方法。39.3 字典 理解以有序集為基礎(chǔ)的抽象數(shù)據(jù)類型字典。 理解用數(shù)組實現(xiàn)字典的方法。 理解二叉搜索樹的概念和實現(xiàn)方法。 掌握用二叉搜索樹實現(xiàn)字典的方法。 理解AVL樹
2、的定義和性質(zhì)。 掌握二叉搜索樹的結(jié)點旋轉(zhuǎn)變換及實現(xiàn)方法。 掌握AVL樹的插入重新平衡運算及實現(xiàn)方法。 掌握AVL樹的刪除重新平衡運算及實現(xiàn)方法。49.4 優(yōu)先隊列 理解以集合為基礎(chǔ)的抽象數(shù)據(jù)類型優(yōu)先隊列。 理解用有序字典實現(xiàn)優(yōu)先隊列的方法。 理解優(yōu)先級樹和堆的概念。 掌握用數(shù)組實現(xiàn)堆的方法。 理解以集合為基礎(chǔ)的抽象數(shù)據(jù)類型可并優(yōu)先隊列。 理解左偏樹的定義和概念。 掌握用左偏樹實現(xiàn)可并優(yōu)先隊列的方法。 掌握堆排序算法。59. 5 并查集 理解以不相交的集合為基礎(chǔ)的抽象數(shù)據(jù)類型并查集。 掌握用數(shù)組實現(xiàn)并查集的方法。 掌握用樹結(jié)構(gòu)實現(xiàn)并查集的方法。 理解將小樹合并到大樹的合并策略及其實現(xiàn)。 掌握路徑
3、壓縮技術(shù)及其實現(xiàn)方法。69.0 引言9.0.1 集合的概念的原形 銀行中所有儲戶帳號的集合;圖書館中 所有藏書的集合;一個程序中所有標(biāo)識 符的集合;2003級34班全體同學(xué)的集合等 79.0 引言9.0.2 集合的概念與術(shù)語 集合:集合是由元素(成員)組成的一個類。 原子:不可再分的元素。 多重集合:允許同一元素在集合中多次出 現(xiàn)的集合稱為多重集合。有序集:當(dāng)由原子組成的集合具有線性序關(guān) 系“”時,稱該集合為有序集?!啊笔羌系?一個線性序,它滿足: (1)若a、b是集合中任意2個原子,則ab,a=b和 ba三者必居其一;(2)a,b和c是集合中的原 子,且ab,bc則asetsize=siz
4、e; S-arraysize=(size+15)4; S-v=malloc(size*sizeof(unsigned short); for (i=0; ivi=0; return S; 15void SetAssign(Set A, Set B) int i; if (A-setsize !=B-setsize) Error(“Sets are not the same size”); for(i=0; iarraysize; i+) A-vi=B-vi; 16int SetMemeber(int x, Set S) if (x=S-setsize) Error(“Invalid membe
5、r reference”); return S-vArrayIndex() & BitMask(x); 17int ArrayIndex(int x) return x4; unsigned short BitMask(int x) return 1setsize !=B-setsize) Error(“.”); for(i=0; iarraysize; i+) if(A-vi !=B-vi) retval=0; break; return retval; 19Set SetUnion(Set A, Set B) int i; Set tmp=SetInit(A-setsize); for(i
6、=0; iarraysize; i+) tmp-vi=A-vi | B-vi; return tmp; 20Set SetIntersection(Set A, Set B) int i; Set tmp=SetInit(A-setsize); for(i=0; iarraysize; i+) tmp-vi=A-vi & B-vi; return tmp; 21Set SetDifference(Set A, Set B) int i; Set tmp=SetInit(A-setsize); for(i=0; iarraysize; i+) tmp-vi=A-vi (B-vi & A-vi);
7、 return tmp; 22void SetInsert(int x, Set S) if (x=S-setsize) Error(“.”); S-vArrayIndex(x) |=BitMask(x); 23void SetDelete(int x, Set S) if (x=S-setsize) Error(“.”); S-vArrayIndex(x) &=BitMask(x); 249.1 以集合為基礎(chǔ)的抽象數(shù)據(jù)類型9.1.3 ADT集合的簡單實現(xiàn)用有序鏈表實現(xiàn)9.1.3.0 LinkedSet的有序鏈表結(jié)點類型Node的定義Typedef struct node *linkstruc
8、t node ListItem element; link next; Node;259.1 以集合為基礎(chǔ)的抽象數(shù)據(jù)類型9.1.3 ADT集合的簡單實現(xiàn)用有序鏈表實現(xiàn) 9.1.3.1有序鏈表實現(xiàn)的集合Set的定義Typedef struct list *SetTypedef struct list link first;26Set SetInit( ) Set S=malloc(sizeof *S); S-first=0; return S; 27int SetEmpty(Set S) return S-first=0; 28int SetSize(Set S) int len; link c
9、urrent; current=S-first; len=0; while (current) len+; current=current-next; return len; 29void SetAssign(Set A, Set B) link a,b,c; b=B-first; A-first=0; if (b) A-first=NewNode( ); a=A-first; a-element=b-element; a-next=0; b=b-next; while(b) c=NewNode( ); c-element=b-element; c-next=0; b=b-next; a-ne
10、xt=c; a=c; 30Set SetIntersection(Set A, Set B) link a,b,p,q,r; Set tmp=SetInit( ); a=A-first; b=B-first; p=NewNode( ); q=p; while(a & & b) if(a-element =b-element) r=NewNode( ); r-element=a-element; r-next=0; p-next=r; p=r; a=a-next; b=b-next; else if(a-element element) a=a-next; else b=b-next; if(p
11、!=q) tmp-first=q-next; free(q); return tmp; 31void SetIntsert(ListItem x, Set S) link p,q,r; p = S-first; q = p; while ( p & p-element next; if (p & p-element = x) return; r = NewNode(); r -element =x; r-next = p; if (p = q) S-first = r; else q-next =r; 329.2 符號表9.2.0 引言 ADT符號表的概念 以集合為基礎(chǔ),并支持Member、I
12、nsert和Delete三種運算的抽象數(shù)據(jù)類型叫做符號表。 ADT符號表的應(yīng)用 公司的客戶字典 一個地區(qū)的固定/移動電話號碼字典 軟件開發(fā)中的數(shù)據(jù)字典 網(wǎng)上的在線字典 互聯(lián)網(wǎng)/企業(yè)網(wǎng)/局域網(wǎng)網(wǎng)管中的IP地址字典等等 339.2符號表9.2.1 實現(xiàn)符號表的簡單方法用固定數(shù)組typedef struct atab *Table;typedef struct atab int arraysize; int last; SetItem*data;Atab;34Table TableInit(int size) Table T=malloc(sizeof *T); T-arraysize=size;
13、T-last=0; T-data=malloc(size*sizeof(SetItem); return T;35int TableMember(SetItem x,Table T) int I; for(i=0;ilast;i+) if(T-datai=x) return 1;return 0;36void TableInsert(SetItem x,Table T) if(! TableMember(x,T) & T-lastarraysize) T-dataT-last+=x;37void TableDelete(SetItem x,Table T) int i=0; if (T-las
14、t0) while(Y-datai!=x & ilast) i+; if(ilast & T-datai=x) T-datai=T-data-T-last;389.2符號表9.2.1 實現(xiàn)符號表的簡單方法用固定數(shù)組9.2.1.3 優(yōu)缺點優(yōu)點:結(jié)構(gòu)簡單,實現(xiàn)操作的邏輯簡單。缺點: 所表示的集合的大小受到數(shù)組大小的限制。 三個基本操作在最壞情況下都需要O(n)。 通常集合元素并不占滿整個數(shù)組,因此, 空間沒有得到充分利用。399.2符號表9.2.2 實現(xiàn)符號表的簡單方法開散列9.2.2.1 基本設(shè)想 把符號表中的所有元素散列(hashing)即映射到一 個桶數(shù)組(散列表)的桶中。當(dāng)有多個不同元素被
15、 散列到同一個桶時,這些元素用鏈在一個表里。 期望散列能均勻,使得當(dāng)桶數(shù)組的規(guī)模與字典 的規(guī)模同階時,桶數(shù)組的每一個桶中大致有常 數(shù)個元素,從而對字典的三個基本操作都只需 要常數(shù)時間。 這里的問題是如何散列即如何構(gòu)造散列(映射)函 數(shù)去達(dá)到設(shè)想的期望?409.2符號表9.2.2 實現(xiàn)符號表的簡單方法開散列9.2.2.2 開散列的數(shù)據(jù)要素 按照設(shè)想,開散列首先需要擁有一個桶數(shù)組, 桶數(shù)組的規(guī)模與符號表的規(guī)模同階,桶數(shù)組中的 每一個桶有一個指針各指向一個鏈表。 其次需要擁有一個散列(映射)函數(shù),它把字典 中的元素分別散列(映射,分散)到各桶所對應(yīng) 的鏈表中。419.2符號表9.2.2 實現(xiàn)符號表的
16、簡單方法開散列9.2.2.3 散列函數(shù)的例子 假設(shè)符號表的元素是字符串x,桶數(shù)組的規(guī)模為 101,那么,下面是散列函數(shù)的一個具體例子int hash1(char* x) int len=strlen(x), hashval = 0; for(int i=0;isize=nbuckets; H-hf=hashf; H-ht=malloc(H-size*sizeof(List); for(i=0;isize;i+) H-hti=ListInit() return H;45int HTMember(SetItem x,OpenHashTable H) int i=(*h-HF)(x) % H-siz
17、e; return (ListLocate(x,H-hti)0);46void HTInsert(SetItem x,OpenHashTable H) int i; if (HTMember(x,H) Error(“Bad Input”); i=(*h-hf)(x) % H-size; ListInsert(0,x,H-hti);47void HTDelete(SetItem x,OpenHashTable H) int i; i=(*h-hf)(x) % H-size; if (k=ListLocate(x,H-hti) ListDelete(k,H-hti);489.2符號表9.2.3 實
18、現(xiàn)符號表的簡單方法閉散列9.2.3.1 與開散列的相同點和區(qū)別相同點:把字典中的所有元素散列(hashing)即 映射到一個桶數(shù)組(散列表)的桶中。區(qū)別:桶數(shù)組(散列表)的桶直接用來存放字典 元素,而且一個桶只存放一個元素。出現(xiàn)多個 元素散列到同一個桶時(這叫沖突),需要按照 確定的規(guī)則在桶數(shù)組中進(jìn)行探測,找還沒有存 放元素的桶(這叫空桶),然后將發(fā)生沖突的后 到元素放入空桶,解決沖突,實現(xiàn)散列。 499.2符號表9.2.3 實現(xiàn)符號表的簡單方法閉散列9.2.3.2 閉散列引發(fā)的問題(1)需要一個探測函數(shù)c(i),i=0,1,2,size-1: c(0)=0,而且對于任意的0jsize-1 (
19、j+c(0)mod size, (j+c(1)mod size, ,(j+c(size-1)mod size是 0,1,2,size-1 的重排,保證不會漏測。(2)需要對ht 的每一個桶的狀態(tài)加以標(biāo)記: statek=0表示htk桶存放著元素。 statek=1表示htk桶一直是空桶。 statek=2表示htk桶現(xiàn)在是空桶但曾經(jīng)存放過元素509.2符號表9.2.3 實現(xiàn)符號表的簡單方法閉散列9.2.3.3 閉散列的數(shù)據(jù)要素(1)桶數(shù)組的規(guī)模size;(2)桶數(shù)組ht ;(3)散列函數(shù)指針 int (*hf) (T x);(4)探測函數(shù)c(i),i=0,1,2,size-1;(5)桶狀態(tài)標(biāo)記
20、數(shù)組state ;519.2符號表9.2.3 實現(xiàn)符號表的簡單方法閉散列9.2.3.4 閉散列表實現(xiàn)的的定義typedef struct hashtable *HashTable;typedef struct hashtableint size;int (*hf)(SetItem x);SetItem *ht;int *state;Hashtable;52HashTable HTInit(int divisor, int (*hashf)(SetItem x)int i;HashTable H=malloc(sizeof *H);H-size=divisor;H-hf = hashf;H-ht
21、=malloc(H-size*sizeof(int);for (i=0;isize;i+)H-statei=1;return H;53int FindMatch(SetItem x,HashTable H)int I,j,k;j=(*H-hf)(x);for (i=0;isize;i+)k=(j+HashProb(i)%H-size;if (H-statek=1) break;if(!H-statek & H-htk=x) return k;return H-size;int HashProb(int i)return i;54int Unoccupied(SetItem x,HashTabl
22、e H)int I,j,k;j=(*H-hf)(x);for (i=0;isize;i+)k=(j+HashProb(i)%H-size;if (H-statek) return k;return H-size;55int HTMember(SetItem x,HashTable H)int i=FindMatch(x,H);if (isize & H-hti=x) return 1;return 0;56int HTInsert(SetItem x,HashTable H)int I;if(HTMember(x,H) Error(“Bad Input”);i=Unoccupied(x,H);
23、if(isize) H-statei=0; H-hti=x; else Error(“table full”);57int HTDelete(SetItem x,HashTable H)int i=FindMatch(x,H);if (isize & H-hti=x) H-statei=2;589.2符號表9.2.3 實現(xiàn)符號表的簡單方法閉散列9.2.3.5 HashTable的定義中未實現(xiàn)的函數(shù)(續(xù))函數(shù)HTDelete的缺點: 在執(zhí)行了大量元素刪除運算后,大量的桶的狀態(tài) 標(biāo)記為 2 即大量的桶的狀態(tài)標(biāo)記既非 1 也非 0 使 得運算FindMatch 中的循環(huán)次數(shù)大大增加,從而 使得運算F
24、indMatch的速度大大減慢。 因此人們提出HTDelete的一種改進(jìn)版本HTDelete1599.2符號表9.2.3 實現(xiàn)符號表的簡單方法閉散列9.2.3.5 HashTable的定義中未實現(xiàn)的函數(shù)(續(xù))改進(jìn)HTDelete的基本思想: 動機(jī)是希望騰出的空桶(記為hti)不僅僅可供新元素插入 ,而且能為提高還在桶數(shù)組中的元素(比如y= htj)的查 找速度作出貢獻(xiàn):減少查找y的探測次數(shù)。 容易理解,如果不作任何改進(jìn),查找y的探測次數(shù)會等于 插入y時的探測次數(shù)。如果插入y時x已在桶hti中且與x發(fā) 生沖突而增加了插入的探測次數(shù),那么,現(xiàn)在x不存在了, 只要將x騰出的桶hti讓y頂替,就可以使
25、得將來查找y時 減少探測次數(shù)。因此改進(jìn)HTDelete的途徑是在當(dāng)前的桶數(shù) 組中找能頂替x的y。如果找不到,就按HTDelete的原版處 理;如果找得到,在用y頂替x之后還可以引起連鎖反應(yīng)。 609.2符號表9.2.3 實現(xiàn)符號表的簡單方法閉散列9.2.3.5 HashTable的定義中未實現(xiàn)的函數(shù)(續(xù))改進(jìn)HTDelete的細(xì)節(jié)找能頂替x的y 假設(shè)被刪除元素x位于桶單元hti?,F(xiàn)考察一個非空單元htj 中的元素y,其散列函數(shù)值設(shè)為h=hf(y),則按從h出發(fā)的線性 探測,只要i比j離h近即可使得在頂替后找y的探測次數(shù)減少。 當(dāng)ij時,若ihj,則不可用元素htj頂替hti;若hij或ijh,
26、則可用元素htj頂替hti。如下圖(a)。 當(dāng)ji時,若jhI,則可用元素htj頂替hti,如下圖 (b);否則不可。 這里以線性探測為前題,以頂替后減少探測次數(shù)為目標(biāo)。619.2符號表9.2.3 實現(xiàn)符號表的簡單方法閉散列9.2.3.5 HashTable的定義中未實現(xiàn)的函數(shù)(續(xù))(8) 改進(jìn)HTDelete的函數(shù)HTDelete1Void HTDelete1SetItem x,HashTable H) int i=FindMatch(x); if (isize) / &H-hti=x可以去掉 for (;) /找hti的頂替元素 H-statei=2; /先按無頂替元素處理 int j;
27、/從(i+1)%size開始線性搜索可頂替元素 for (j=(i+1)%H-size; !statej; j=(j+1)%H-size) 629.2符號表 int h=(*H-hf) (H-htj);if (h=i&ij)|(ij&jh)|(jh&hstatej) break; /跳出外for循環(huán) H- hti=htj; H-statei=statej; /做頂替工作i=j; /為構(gòu)成循環(huán)找htj的頂替元素 639.2符號表9.2.4 開散列的效率若能選擇一個好的散列函數(shù),將集合中的N個元素均勻地散列到B個桶中,那么,每個桶中平均有N/B個元素,使得在開散列表中,Insert,Delete和
28、Member運算都只要O(N/B)的平均時間。進(jìn)而當(dāng)N/B為一常數(shù)時,字典的每一個運算都可在常數(shù)時間內(nèi)完成。因此:對于開散列表,關(guān)鍵在于選擇一個好的散列函數(shù)649.2符號表9.2.5 散列函數(shù)舉例(1)除余法:h(k)=k %m。(2)數(shù)乘法:h(k)= 。(3)平方取中法:h(k)= %B。(4)基數(shù)轉(zhuǎn)換法 :(5)隨機(jī)數(shù)法 :h(k)=random(k)。659.2符號表9.2.6 閉散列的重新散列技術(shù) (1)二次重新散列技術(shù) 它選取的探查桶序列為:h(x),h1(x) ,h2(x) ,h2i(x) ,h2i+1(x) , 其中, , 。 (2)隨機(jī)重新散列技術(shù) 它選取的探查桶序列為: ,
29、i=1,2,B-1。 其中, 是1,2,B-1的一個隨機(jī)排列。 (3)雙重散列技術(shù) 這種方法使用2個散列函數(shù)h和h來產(chǎn)生探索序列: 其中 i=1,2,B-1。要求h(x)的值和B互素 。669.3.1 字典的定義 字典是以有序集為基礎(chǔ)的抽象數(shù)據(jù)類型。 它支持以下運算: (1)Member(x),成員運算。 (2)Insert(x),插入運算:將元素x插入集合。 (3)Delete(x),刪除運算:將元素x從當(dāng)前集合中刪去。 (4)Predecessor(x),前驅(qū)運算:返回集合中小于x的最大元素。 (5)Successor(x),后繼運算:返回集合中大于x的最小元素。 (6)Range(x,y
30、),區(qū)間查詢運算:返回集合中界于x和y之間,即xzy的所有元素z組成的集合。 (7)Min( ),最小元運算:返回當(dāng)前集合中依線性序最小的元素。 9.3 字典 679.3 字典 9.3.2 用數(shù)組實現(xiàn)字典 用數(shù)組實現(xiàn)字典與用數(shù)組實現(xiàn)符號表的不同之處: 可以利用線性序?qū)⒆值渲械脑貜男〉酱笠佬虼鎯υ跀?shù)組中,通過數(shù)組下標(biāo)來反映有序字典元素之間的序關(guān)系。優(yōu)點:可用二分法高效地實現(xiàn)與線性序有關(guān)的一些運算。如:Member(x) ,Predecessor(x)和 Successor(x)可在時間O(logn)內(nèi)實現(xiàn)。缺點:插入和刪除運算的效率較低。每執(zhí)行一次Insert或Delete運算,需要移動部分?jǐn)?shù)
31、組元素,從而導(dǎo)致它們在最壞情況下的計算時間為O(n)??紤]:能否用鏈表來實現(xiàn)字典?Member運算需要O(n)時間,一旦找到元素在鏈表中插入或刪除的位置后,只要用O(1)時間就可完成插入或刪除操作。 兩種實現(xiàn)方式均不可取!689.3 字典 9.3.3 用二叉搜索樹實現(xiàn)字典9.3.3.1 基本思想: 用二叉樹來存儲有序集,每一個結(jié)點存儲一個元素。 滿足:存儲于每個結(jié)點中的元素x大于其左子樹中任一結(jié)點中所存儲的元素,小于其右子樹中任一結(jié)點中所存儲的元素。699.3 字典 9.3.3 用二叉搜索樹實現(xiàn)字典9.3.3.2 二叉搜索樹結(jié)點的定義及程序?qū)崿F(xiàn)709.3 字典 9.3.3 用二叉搜索樹實現(xiàn)字典
32、9.3.3.3 二叉搜索樹的定義及運算的實現(xiàn):71例 10, 18, 3, 8, 12, 2, 7, 41010181018310183810183812210183812710183812247101838122二叉搜索樹的建立過程:72刪除508060120110150557053刪除6080551201101505370805012060110150557053刪除43例80501206011015055705343運算Delete(const T& x)的實現(xiàn)73運算Delete(const T& x)的實現(xiàn)(續(xù))設(shè)要刪除二叉搜索樹中的結(jié)點p ,分三種情況:p為葉結(jié)點 直接刪除節(jié)點pp
33、只有左子樹或右子樹p只有左子樹 用p的左兒子代替p p只有右子樹 用p的右兒子代替p p左、右子樹均非空找p的左子樹的最大元素結(jié)點(即p的前驅(qū)結(jié)點),用該結(jié)點代替結(jié)點p,然后刪除該結(jié)點。74用二叉搜索樹實現(xiàn)字典時間復(fù)雜性分析 最壞情況分析member,insert,delete都需要O(n) 平均情況分析引入記號:記:p(n)為含有n個結(jié)點的二叉搜索樹的平均查找長度。顯然p(0)=0,p(1)=1; 若設(shè)某二叉搜索樹的左子樹有i個結(jié)點,則:p(i)+1為查找左子樹中每個結(jié)點的平均查找長度;p(n-i-1)+1為查找右子樹中每個結(jié)點的平均查找長度;由此構(gòu)造而得的二叉搜索樹在n個結(jié)點的查找概率相等
34、的情況下,其平均查找長度為:75對n用數(shù)學(xué)歸納法可以證明:又假設(shè)當(dāng)前的二叉搜索樹有n個結(jié)點,而它是從空樹開始反復(fù)調(diào)用n次的Insert運算得到的,且被插入的n個元素的所有可能的順序是等概率的。則:當(dāng)n=1時顯然成立。若設(shè)in時有 ,則76平均情況下的時間復(fù)雜度為:略去 -1/n 項77運算Predecessor(x)和Successor(x)的實現(xiàn):類似于Search(x)算法運算Range(y, z)的實現(xiàn):可借助于Search(y)和Successor(y)運算首先,用Search(y)檢測y是否在二叉搜索樹中,是則輸出y,否則不輸出y;然后,從y開始,不斷地用Successor找當(dāng)前元素
35、在二叉搜索樹中的后繼元素。當(dāng)找出的后繼元素x滿足x z時,就輸出x,并將x作為當(dāng)前元素。重復(fù)這個過程,直到找出的當(dāng)前元素的后繼元素大于z,或二叉搜索樹中已沒有后繼元素為止。時間復(fù)雜度:若二叉樹搜索樹中有r個元素x滿足y x z,則在最壞情況下用 時間,在平均情況下用 時間可實現(xiàn)Range運算。 78運算Range(y,z)的改進(jìn):考慮半無限查詢區(qū)域 , 即找出二叉搜索樹中滿足y x的所有元素x。 當(dāng)y不在二叉搜索樹中時,產(chǎn)生一條從根到葉的路徑。如下圖(a) 當(dāng)y在二叉搜索樹中時,產(chǎn)生一條從根到存儲元素y的結(jié)點的路徑。如下圖(b) 79在找到的搜索路徑上的所有結(jié)點可分為以下3種情況,如下圖 :8
36、0運算Range(y,z)的實現(xiàn):可用類似于Range(y,)算法 從二叉搜索樹的根結(jié)點開始,同時與y和z比較,此時,結(jié)點分類的情況可能有(見下圖) :81運算Range(y,z)的搜索路徑如下圖: 829.4 優(yōu)先隊列 9.4.0 優(yōu)先隊列的原型排隊上車,老弱病殘者優(yōu)先上車排隊候診,危急病人優(yōu)先就診洗相館為顧客洗照片,加錢加急者優(yōu)先洗分時操作系統(tǒng)運行程序,小程序優(yōu)先貪心算法對解分量的選擇,按元素的某種特征值,大(或小)的優(yōu)先在一個集合中搜索,按元素的某種特征值,大(或小)的優(yōu)先處理或服務(wù)時只關(guān)心對象中誰的優(yōu)先級最高通常的隊列是一種優(yōu)先隊列最先到者優(yōu)先級最高839.4 優(yōu)先隊列9.4.1 優(yōu)先
37、隊列的定義優(yōu)先隊列也是一個以集合為基礎(chǔ)的抽象數(shù)據(jù)類型。優(yōu)先隊列中的每一個元素都有一個優(yōu)先級值。優(yōu)先隊列中元素x的優(yōu)先級值記為p(x),它可以是一個實數(shù),也可以是一個一般的全序集中的元素。優(yōu)先級值用來表示該元素出列的優(yōu)先級。通常約定優(yōu)先級值小的優(yōu)先級高。也可以約定優(yōu)先級值大的優(yōu)先級高。優(yōu)先隊列支持的基本運算有:(1)Size( ):返回優(yōu)先隊列中元素個數(shù)。(2)Min( ):返回優(yōu)先隊列中具有最小優(yōu)先級值的元素。(3)Insert(x):將元素x插入優(yōu)先隊列。(4)DeleteMin(x):刪除優(yōu)先隊列中具有最小優(yōu)先級值的元素,并保存到x中。 849.4 優(yōu)先隊列9.4.2 用實現(xiàn)有序字典的方式
38、實現(xiàn)優(yōu)先隊列(1)優(yōu)先隊列與字典的相似性與區(qū)別:優(yōu)先隊列中元素的優(yōu)先級值可以看作是有序字典中元素的線性序值。在有序字典中,不同的元素具有不同的線性序值,其插入運算僅當(dāng)要插入元素x的線性序值與當(dāng)前字典中所有元素的線性序值都不同時才執(zhí)行。對于優(yōu)先隊列來說,不同的元素可以有相同的優(yōu)先級值。因此,優(yōu)先隊列的插入運算即使在當(dāng)前優(yōu)先隊列中存在與要插入元素x有相同的優(yōu)先級值的元素時,也要執(zhí)行元素x的插入。 859.4 優(yōu)先隊列9.4.2 用實現(xiàn)有序字典的方式實現(xiàn)優(yōu)先隊列(2)由于優(yōu)先隊列與字典的相似性,除了散列表之外,所有實現(xiàn)字典和有序字典的方法都可用于實現(xiàn)優(yōu)先隊列。 用有序鏈表實現(xiàn)優(yōu)先隊列;(Insert
39、低效) 用二叉搜索樹實現(xiàn)優(yōu)先隊列;(Insert,DeleteMin, Min 均低效) 用AVL樹實現(xiàn)優(yōu)先隊列;(邏輯復(fù)雜) 用無序鏈表實現(xiàn)優(yōu)先隊列;(DeleteMin, Min均低效) 都有缺點。原因在于沒有考慮到優(yōu)先隊列的特性。869.4 優(yōu)先隊列9.4.3 用優(yōu)先級樹實現(xiàn)優(yōu)先隊列 1.優(yōu)先隊列的特征:DeleteMin和Min只關(guān)心優(yōu)先級最高的元素Insert的元素不要求全局的序關(guān)系 因此實現(xiàn)優(yōu)先隊列的結(jié)構(gòu)只要求方便DeleteMin 和Min,而對Insert也只要求不給結(jié)構(gòu)的維護(hù)帶來 太大的麻煩。 根據(jù)這兩個特征,人們發(fā)明了優(yōu)先級樹。879.4 優(yōu)先隊列9.4.3 用優(yōu)先級樹實現(xiàn)
40、優(yōu)先隊列(續(xù))2.優(yōu)先級樹的概念 優(yōu)先級樹是滿足下面的優(yōu)先級性質(zhì)的二叉樹: (1)樹中每一結(jié)點存儲一個元素。 (2)任一結(jié)點中存儲的元素的優(yōu)先級值不大(小)于 其兒子結(jié)點中存儲的元素的優(yōu)先級值即父結(jié)點的 優(yōu)先級不低于其兒子結(jié)點的優(yōu)先級。 換句話說,越接近根的結(jié)點中的元素的優(yōu)先級越高,越方便被訪問,因為根最方便被訪問。 相應(yīng)的優(yōu)先級樹稱為極小(大)化優(yōu)先級樹。889.4 優(yōu)先隊列9.4.4用堆實現(xiàn)優(yōu)先隊列用優(yōu)先級樹實現(xiàn)優(yōu)先隊列仍有不足: Insert(x)和DeleteMin(x)后對結(jié)構(gòu)的維護(hù),在最壞情況下,仍需O(h)=O(n)。如果讓優(yōu)先級樹近似滿,從而h=log n,達(dá)到最小,那么,結(jié)果
41、將令人滿意:在最壞情況下, Min( )將只需O(1), Insert(x)和DeleteMin(x)后對結(jié)構(gòu)的維護(hù)只需O(log n)。因而引入堆的概念并用堆來實現(xiàn)優(yōu)先隊列。(1)堆的概念:如果一棵優(yōu)先級樹是一棵近似滿二叉樹,那么,這棵具有優(yōu)先級性質(zhì)的近似滿二叉樹(外形像堆)就叫做堆。(2)用堆實現(xiàn)優(yōu)先隊列: Min( )、Insert(x)和DeleteMin(x)運算的實現(xiàn)899.4 優(yōu)先隊列9.4.5 用數(shù)組表示堆從而實現(xiàn)優(yōu)先隊列(1) 用數(shù)組表示堆: 從1開始對堆的結(jié)點從根開始自上而下逐層、 每層從左到右進(jìn)行編號,然后讓結(jié)點中的元 素按編號在數(shù)組A中與下標(biāo)對號入座。(2) 用數(shù)組表示
42、堆的優(yōu)點: 存儲緊湊,空間利用率高 父子關(guān)系簡單清晰:存放在Ai的是結(jié)點i的元 素, A2i和A2i+1分別是結(jié)點i的左和右兒子 結(jié)點2i和2i+1的元素, Ai/2是結(jié)點i的父結(jié) 點的元素。909.4 優(yōu)先隊列9.4.5 用數(shù)組表示堆從而實現(xiàn)優(yōu)先隊列(續(xù))(3)數(shù)組實現(xiàn)優(yōu)先隊列極小化堆MinHeap919.4 優(yōu)先隊列9.4.6 優(yōu)先隊列的應(yīng)用Huffman編碼9.4.6.1 問題的提出 已知一個文本文件,要求把它轉(zhuǎn)換成一個電子文檔,以便存儲在磁介質(zhì)中或在網(wǎng)絡(luò)上傳輸。從存儲的角度看, 我們自然希望該電子文檔越短越好即存儲占用的空間越 少越好;從傳輸?shù)慕嵌瓤?,我們自然也希望該電子文檔 越短越好
43、即傳輸占用的時間越少越好。因此,我們要求 轉(zhuǎn)換成的電子文檔盡量地短,盡量地壓縮。 有許多名家說過,把一個問題表述清楚了,就已經(jīng)解決 了問題的一半。這說明問題的表述很重要,表述得越清 楚、越精確,對問題的解決越好。 上述問題還需要更精確的表述。929.4 優(yōu)先隊列9.4.6 優(yōu)先隊列的應(yīng)用Huffman編碼9.4.6.2 表述Huffman編碼問題的準(zhǔn)備 對涉及的有關(guān)對象、概念、術(shù)語、和記號的準(zhǔn)備 一個文本文件就是一個字符串,記為F。 文本文件中所用到的不同的字符組成的集合,記為C。 C中的字符c在文件中出現(xiàn)的頻率/次數(shù),記為f(c)或fc。 字符的編碼0/1串。如字符a的ASCII碼是0110
44、0001。 字符編碼的碼長0/1串的串長。記cC的碼長為l(c)。 文件F編碼的碼長原文本文件編碼后的0/1串的累計長。記為L(F)=cC f(c)* l(c) 。 字符的定長編碼。 ASCII碼是一種定長編碼。不可能壓縮。 字符的變長編碼字符的碼長隨字符而變。 939.4 優(yōu)先隊列9.4.6 優(yōu)先隊列的應(yīng)用Huffman編碼9.4.6.2 表述Huffman編碼問題的的準(zhǔn)備(續(xù)) 編碼與解碼既要編碼又要解碼,以便復(fù)原文件。 二義性:不能造成一串編碼有兩種理解。 前綴碼:為了解碼時不會出現(xiàn)二義性, 要求任意一個字符的編碼不能是另一個 字符的前綴。 字符集C的前綴碼的表示以C中的 字符為葉結(jié)點的
45、二叉樹,如a0,b101,c100,d111,e1101,f1100 可表示成右圖的二叉樹。 這棵樹叫字符集C的前綴編碼樹,記為T。acbfed0101010101949.4 優(yōu)先隊列9.4.6 優(yōu)先隊列的應(yīng)用Huffman編碼9.4.6.3 Huffman編碼問題的表述問題數(shù)學(xué)化。 經(jīng)上述準(zhǔn)備,我們看到,字符cC的碼長l (c) 正是c在字符集C的前綴編碼樹T中的深度,記 為dT(c)。這樣,我們的問題可更具體、更精 確地表述為:已知字符串F和出現(xiàn)在F中的字 符集C及C中每一字符c出現(xiàn)的頻率/次數(shù)f(c) , 要求C的一棵最優(yōu)的前綴編碼樹T, 使得F的編 碼長cC f(c)* dT(c) B
46、(T)達(dá)到最小。這棵 最優(yōu)的前綴編碼樹叫Huffman編碼樹。相應(yīng)的 前綴編碼叫Huffman編碼。959.4 優(yōu)先隊列9.4.6 優(yōu)先隊列的應(yīng)用Huffman編碼9.4.6.4 求解問題的設(shè)想與分析 (1) 問題的目標(biāo)是求C的最優(yōu)前綴編碼樹T,因此,我們應(yīng) 該先分析一下C的最優(yōu)的前綴編碼樹T的性質(zhì):它是一棵以C中 的字符為葉結(jié)點的健全二叉樹(這容易用反證法加以證明)。 因而一定有兩個最深的葉結(jié)點是兄弟結(jié)點。 (2) 按照大數(shù)學(xué)家、大教育家波利亞的觀點,“除數(shù)學(xué)和論 證邏輯外,我們所有的知識都是由一些猜想所構(gòu)成的。” 為了 得到有用的結(jié)論、方法,總是從猜想開始。而猜想的依據(jù)是 合情推理。 就擺
47、在面前的問題而言,可直觀地設(shè)想:最深的葉結(jié)點中 有兩個兄弟是C中頻 度最低的字符x和y ,因為編碼最長的字 符應(yīng)該是頻度最低的字符(這需要證明)。969.4 優(yōu)先隊列9.4.6 優(yōu)先隊列的應(yīng)用Huffman編碼9.4.6.4 求解問題的設(shè)想與分析(續(xù)) (3) 用字符z代替字符x和y ,讓f(x)+f(y)作為字符z 的頻度 f(z),相應(yīng)地,在T中刪去兄弟葉結(jié)點x和y ,而且用z 取代已經(jīng)成為葉結(jié)點的x和y的父結(jié)點,得到一棵新的健全二叉編碼樹T,那么,T應(yīng)該是C-x,yz的最優(yōu)前綴編碼樹(這需要證明) 。 若上述設(shè)想與分析正確,那么,問題就有了解法:把C中的字符以其頻度為優(yōu)先級值,且以小者優(yōu)
48、先組織成優(yōu)先隊列Q。然后反復(fù)地執(zhí)行下面兩個語句: 刪除Q中優(yōu)先級最高的兩個字符,設(shè)為x和y; 虛擬字符z(分別以x和y為左和右兒子),并賦予優(yōu)先 級值f(z)=f(x)+f(y),插入Q;直到Q為空,其結(jié)果就是C的最優(yōu)前綴編碼樹。979.4 優(yōu)先隊列9.4.6 優(yōu)先隊列的應(yīng)用Huffman編碼9.4.6.5 Huffman編碼問題的解決 從理論上看待Huffman編碼問題,在9.4.6.4 求 解問題的設(shè)想與分析中的(2)和(3)所猜想的分 別是問題的解的貪心選擇性質(zhì)和最優(yōu)子結(jié)構(gòu)性 質(zhì)。這兩個性質(zhì)保證了問題可以用基于優(yōu)先隊 列的前述算法正確地加以求解。所以問題的真 正解決有待對貪心選擇性質(zhì)和最
49、優(yōu)子結(jié)構(gòu)性質(zhì) 作理論上的證明。此外,還得給出Huffman編 碼和解碼的簡潔實現(xiàn)。989.4 優(yōu)先隊列9.4.6 優(yōu)先隊列的應(yīng)用Huffman編碼9.4.6.5 Huffman編碼問題的解決(續(xù)) (1) 問題解的貪心選擇性質(zhì):設(shè)x和y是C 中具有最小頻度的兩個字符,則存在C的 一個最優(yōu)前綴碼使x和y具有最長的相同碼 長且僅最后一位編碼不同,即x和y是編碼 樹中最深的一對葉結(jié)點兄弟。 證明:999.4 優(yōu)先隊列9.4.6 優(yōu)先隊列的應(yīng)用Huffman編碼9.4.6.5 Huffman編碼問題的解決(續(xù)) (2) 問題解的最優(yōu)子結(jié)構(gòu)性質(zhì):設(shè)x和y是C的最優(yōu)編碼樹T中的兩個葉子且為兄弟,z是它們的父親。若將z看作是具有頻率f(z)=f
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 企業(yè)公司融資合同范本
- 艙口蓋系統(tǒng)行業(yè)深度研究報告
- 化肥長期供貨合同范本
- 場地使用出租合同范本
- 事業(yè)單位聘用合同范本
- 共享叉車租賃合同范例
- 副食購買合同范本
- 充電樁維修合同范本
- 勞務(wù)法合同范本
- 加盟合同范本
- 戰(zhàn)略管理與倫理
- 如何構(gòu)建高效課堂課件
- 虛擬化與云計算技術(shù)應(yīng)用實踐項目化教程 教案全套 第1-14周 虛擬化與云計算導(dǎo)論-騰訊云服務(wù)
- 甲基丙烯酸甲酯生產(chǎn)工藝畢業(yè)設(shè)計設(shè)備選型與布置模板
- 徐金桂行政法與行政訴訟法新講義
- 瀝青拌合設(shè)備結(jié)構(gòu)認(rèn)知
- 2023年北京高考政治真題試題及答案
- 復(fù)旦中華傳統(tǒng)體育課程講義05木蘭拳基本技術(shù)
- 北師大版五年級上冊數(shù)學(xué)教學(xué)課件第5課時 人民幣兌換
- 工程回訪記錄單
- 住房公積金投訴申請書
評論
0/150
提交評論