版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)
文檔簡介
自考02331數(shù)據(jù)結(jié)構(gòu)重點總結(jié)(最終修訂)第一章概論1.瑞士計算機科學(xué)家沃思提出:算法+數(shù)據(jù)結(jié)構(gòu)=程序。算法是對數(shù)據(jù)運算的描述,而數(shù)據(jù)結(jié)構(gòu)涉及邏輯結(jié)構(gòu)和存儲結(jié)構(gòu)。由此可見,程序設(shè)計的實質(zhì)是針對實際問題選擇一種好的數(shù)據(jù)結(jié)構(gòu)和設(shè)計一個好的算法,而好的算法在很大限度上取決于描述實際問題的數(shù)據(jù)結(jié)構(gòu)。2.數(shù)據(jù)是信息的載體。數(shù)據(jù)元素是數(shù)據(jù)的基本單位。一個數(shù)據(jù)元素可以由若干個數(shù)據(jù)項組成,數(shù)據(jù)項是具有獨立含義的最小標(biāo)記單位。數(shù)據(jù)對象是具有相同性質(zhì)的數(shù)據(jù)元素的集合。3.數(shù)據(jù)結(jié)構(gòu)指的是數(shù)據(jù)元素之間的互相關(guān)系,即數(shù)據(jù)的組織形式。數(shù)據(jù)結(jié)構(gòu)一般涉及以下三方面內(nèi)容:數(shù)據(jù)的邏輯結(jié)構(gòu)、數(shù)據(jù)的存儲結(jié)構(gòu)、數(shù)據(jù)的運算①數(shù)據(jù)的邏輯結(jié)構(gòu)是從邏輯關(guān)系上描述數(shù)據(jù),與數(shù)據(jù)元素的存儲結(jié)構(gòu)無關(guān),是獨立于計算機的。數(shù)據(jù)的邏輯結(jié)構(gòu)分類:線性結(jié)構(gòu)和非線性結(jié)構(gòu)。線性表是一個典型的線性結(jié)構(gòu)。棧、隊列、串等都是線性結(jié)構(gòu)。數(shù)組、廣義表、樹和圖等數(shù)據(jù)結(jié)構(gòu)都是非線性結(jié)構(gòu)。②數(shù)據(jù)元素及其關(guān)系在計算機內(nèi)的存儲方式,稱為數(shù)據(jù)的存儲結(jié)構(gòu)(物理結(jié)構(gòu))。數(shù)據(jù)的存儲結(jié)構(gòu)是邏輯結(jié)構(gòu)用計算機語言的實現(xiàn),它依賴于計算機語言。③數(shù)據(jù)的運算。最常用的檢索、插入、刪除、更新、排序等。4.數(shù)據(jù)的四種基本存儲方法:順序存儲、鏈接存儲、索引存儲、散列存儲(1)順序存儲:通常借助程序設(shè)計語言的數(shù)組描述。(2)鏈接存儲:通常借助于程序語言的指針來描述。(3)索引存儲:索引表由若干索引項組成。關(guān)鍵字是能唯一標(biāo)記一個元素的一個或多個數(shù)據(jù)項的組合。(4)散列存儲:該方法的基本思想是:根據(jù)元素的關(guān)鍵字直接計算出該元素的存儲地址。5.算法必須滿足5個準(zhǔn)則:輸入,0個或多個數(shù)據(jù)作為輸入;輸出,產(chǎn)生一個或多個輸出;有窮性,算法執(zhí)行有限步后結(jié)束;擬定性,每一條指令的含義都明確;可行性,算法是可行的。算法與程序的區(qū)別:程序必須依賴于計算機程序語言,而一個算法可用自然語言、計算機程序語言、數(shù)學(xué)語言或約定的符號語言來描述。目前常用的描述算法語言有兩類:類Pascal和類C。6.評價算法的優(yōu)劣:算法的"對的性"是一方面要考慮的。此外,重要考慮如下三點:?①執(zhí)行算法所花費的時間,即時間復(fù)雜性;
②執(zhí)行算法所花費的存儲空間,重要是輔助空間,即空間復(fù)雜性;?③算法應(yīng)易于理解、易于編程,易于調(diào)試等,即可讀性和可操作性。以上幾點最重要的是時間復(fù)雜性,時間復(fù)雜度常用漸進時間復(fù)雜度表達。7.算法求解問題的輸入量稱為問題的規(guī)模,用一個正整數(shù)n表達。8.常見的時間復(fù)雜度按數(shù)量級遞增排列依次為:常數(shù)階0(1)、對數(shù)階0(log2n)、線性階0(n)、線性對數(shù)階0(nlog2n)、平方階0(n2)立方階0(n3)、…、k次方階0(nk)、指數(shù)階0(2n)和階乘階0(n!)。9.一個算法的空間復(fù)雜度S(n)定義為該算法所花費的存儲空間,它是問題規(guī)模n的函數(shù),它涉及存儲算法自身所占的存儲空間、算法的輸入輸出數(shù)據(jù)所占的存儲空間和算法在運營過程中臨時占用的存儲空間。第二章線性表1.數(shù)據(jù)的運算是定義在邏輯結(jié)構(gòu)上的,而運算的具體實現(xiàn)是在存儲結(jié)構(gòu)上進行的。
2.只要擬定了線性表存儲的起始位置,線性表中任意一個元素都可隨機存取,所以順序表是一種隨機存取結(jié)構(gòu)。3.常見的線性表的基本運算:(1)置空表InitList(L)構(gòu)造一個空的線性表L。?(2)求表長ListLength(L)求線性表L中的結(jié)點個數(shù),即求表長。
(3)GetNode(L,i)取線性表L中的第i個元素。?(4)LocateNode(L,x)在L中查找第一個值為x的元素,并返回該元素在L中的位置。若L中沒有元素的值為x,則返回0值。
(5)InsertList(L,i,x)在線性表L的第i個元素之前插入一個值為x的新元素,表L的長度加1。
(6)DeleteList(L,i)刪除線性表L的第i個元素,刪除后表L的長度減1。4.順序存儲方法:把線性表的數(shù)據(jù)元素按邏輯順序依次存放在一組地址連續(xù)的存儲單元里的方法。順序表(SequentialList):用順序存儲方法存儲的線性表稱為順序表。順序表是一種隨機存取結(jié)構(gòu),順序表的特點是邏輯上相鄰的結(jié)點其物理位置亦相鄰。順序表中結(jié)點ai的存儲地址:LOC(ai)=LOC(a1)+(i-1)*c
1≤i≤n,5.順序表上實現(xiàn)的基本運算:(1)插入:該算法的平均時間復(fù)雜度是O(n),即在順序表上進行插入運算,平均要移動一半結(jié)點(n/2)。在第i個位置插入一個結(jié)點的移動次數(shù)為n-i+1(2)刪除:順序表上做刪除運算,平均要移動表中約一半的結(jié)點(n-1)/2,平均時間復(fù)雜度也是O(n)。刪除第i個結(jié)點移動次數(shù)為n-i6.采用鏈?zhǔn)酱鎯Y(jié)構(gòu)可以避免頻繁移動大量元素。一個單鏈表可由頭指針唯一擬定,因此單鏈表可以用頭指針的名字來命名。①生成結(jié)點變量的標(biāo)準(zhǔn)函數(shù)p=(ListNode*)malloc(sizeof(ListNode));//函數(shù)malloc分派一個類型為ListNode的結(jié)點變量的空間,并將其首地址放入指針變量p中②釋放結(jié)點變量空間的標(biāo)準(zhǔn)函數(shù)free(p);//釋放p所指的結(jié)點變量空間③結(jié)點分量的訪問
方法二:p-﹥data和p-﹥next④指針變量p和結(jié)點變量*p的關(guān)系:指針變量p的值——結(jié)點地址,結(jié)點變量*p的值——結(jié)點內(nèi)容7.建立單鏈表:(1)頭插法建表:算法:p=(ListNode*)malloc(sizeof(ListNode));①//生成新結(jié)點
p->dat(yī)a=ch;②//將讀入的數(shù)據(jù)放入新結(jié)點的數(shù)據(jù)域中
p->next=head;③head=p;④
(2)尾插法建表:算法:p=(ListNode*)malloc(sizeof(ListNode));①//生成新結(jié)點?
p->data=ch;
②//將讀入的數(shù)據(jù)放入新結(jié)點的數(shù)據(jù)域中
if(head==NULL)head=p;//新結(jié)點插入空表
elserear->next=p;③//將新結(jié)點插到*r之后
rear=p;④//尾指針指向新表尾(3)尾插法建帶頭結(jié)點的單鏈表:頭結(jié)點及作用:頭結(jié)點是在鏈表的開始結(jié)點之前附加一個結(jié)點。它具有兩個優(yōu)點:?
⒈由于開始結(jié)點的位置被存放在頭結(jié)點的指針域中,所以在鏈表的第一個位置上的操作就和在表的其它位置上操作一致,無須進行特殊解決;
⒉無論鏈表是否為空,其頭指針都是指向頭結(jié)點的非空指針(空表中頭結(jié)點的指針域空),因此空表和非空表的解決也就統(tǒng)一了。頭結(jié)點數(shù)據(jù)域的陰影表達該部分不存儲信息。在有的應(yīng)用中可用于存放表長等附加信息。?具體算法:r=head;//
尾指針初值也指向頭結(jié)點
while((ch=getchar())!='\n'){?
s=(ListNode*)malloc(sizeof(ListNode));//生成新結(jié)點
s->data=ch;
//將讀入的數(shù)據(jù)放入新結(jié)點的數(shù)據(jù)域中?
r->next=s;
r=s;}?
r->next=NULL;//終端結(jié)點的指針域置空,或空表的頭結(jié)點指針域置空以上三個算法的時間復(fù)雜度均為O(n)。8.單鏈表上的查找:(帶頭結(jié)點)(1)按結(jié)點序號查找:序號為0的是頭結(jié)點。算法:p=head;j=0;//從頭結(jié)點開始掃描
while(p->next&&j<i){//順指針向后掃描,直到p->next為NULL或i=j為止?
p=p->next;?
j++;}?
if(i==j)returnp;//找到了第i個結(jié)點?
elsereturnNULL;//當(dāng)i<0或i>0時,找不到第i個結(jié)點
時間復(fù)雜度:在等概率假設(shè)下,平均時間復(fù)雜度為:為n/2=O(n)(2)按結(jié)點值查找:具體算法:ListNode*p=head->next;//從開始結(jié)點比較。表非空,p初始值指向開始結(jié)點?
while(p&&p->dat(yī)a!=key)//直到p為NULL或p->dat(yī)a為key為止
p=p->next;//掃描下一結(jié)點?
returnp;//若p=NULL,則查找失敗,否則p指向值為key的結(jié)點時間復(fù)雜度為:O(n)9.插入運算:插入運算是將值為x的新結(jié)點插入到表的第i個結(jié)點的位置上,即插入到ai-1與ai之間。
?s=(ListNode*)malloc(sizeof(ListNode));②s->data=x;③s->next=p->next;④p->next=s;⑤算法的時間重要花費在查找結(jié)點上,故時間復(fù)雜度亦為O(n)。?10.刪除運算
r=p->next;②//使r指向被刪除的結(jié)點aip->next=r->next③;//將ai從鏈上摘下free(r);④//釋放結(jié)點ai的空間給存儲池算法的時間復(fù)雜度也是O(n).p指向被刪除的前一個結(jié)點。鏈表上實現(xiàn)的插入和刪除運算,無須移動結(jié)點,僅需修改指針。11.單循環(huán)鏈表—在單鏈表中,將終端結(jié)點的指針域NULL改為指向表頭結(jié)點或開始結(jié)點即可。判斷空鏈表的條件是head==head->next;12.僅設(shè)尾指針的單循環(huán)鏈表:用尾指針rear表達的單循環(huán)鏈表對開始結(jié)點a1和終端結(jié)點an查找時間都是O(1)。而表的操作經(jīng)常是在表的首尾位置上進行,因此,實用中多采用尾指針表達單循環(huán)鏈表。判斷空鏈表的條件為rear==rear->next;13.循環(huán)鏈表:循環(huán)鏈表的特點是無須增長存儲量,僅對表的鏈接方式稍作改變,即可使得表解決更加方便靈活。若在尾指針表達的單循環(huán)鏈表上實現(xiàn),則只需修改指針,無須遍歷,其執(zhí)行時間是O(1)。具體算法:LinkListConnect(LinkListA,LinkListB)
{//假設(shè)A,B為非空循環(huán)鏈表的尾指針LinkListp=A->next;//①保存A表的頭結(jié)點位置
A->next=B->next->next;//②B表的開始結(jié)點鏈接到A表尾?
free(B->next);//③釋放B表的頭結(jié)點?
B->next=p;//④?
returnB;//返回新循環(huán)鏈表的尾指針循環(huán)鏈表中沒有NULL指針。涉及遍歷操作時,其終止條件就不再是像非循環(huán)鏈表那樣判別p或p->next是否為空,而是判別它們是否等于某一指定指針,如頭指針或尾指針等。在單鏈表中,從一已知結(jié)點出發(fā),只能訪問到該結(jié)點及其后續(xù)結(jié)點,無法找到該結(jié)點之前的其它結(jié)點。而在單循環(huán)鏈表中,從任一結(jié)點出發(fā)都可訪問到表中所有結(jié)點,這一優(yōu)點使某些運算在單循環(huán)鏈表上易于實現(xiàn)。14.雙向鏈表:雙(向)鏈表中有兩條方向不同的鏈,即每個結(jié)點中除next域存放后繼結(jié)點地址外,還增長一個指向其直接前趨的指針域prior。①雙鏈表由頭指針head惟一擬定的。
②帶頭結(jié)點的雙鏈表的某些運算變得方便。
③將頭結(jié)點和尾結(jié)點鏈接起來,為雙(向)循環(huán)鏈表。
15.雙向鏈表的前插和刪除本結(jié)點操作①雙鏈表的前插操作voidDInsertBefore(DListNode*p,DataTypex){//在帶頭結(jié)點的雙鏈表中,將值為x的新結(jié)點插入*p之前,設(shè)p≠NULL
DListNode*s=malloc(sizeof(DListNode));//①?
s->dat(yī)a=x;//②?
s->prior=p->prior;//③?
s->next=p;//④
p->prior->next=s;//⑤
p->prior=s;//⑥}?②雙鏈表上刪除結(jié)點*p自身的操作?voidDDeleteNode(DListNode*p)?
{//在帶頭結(jié)點的雙鏈表中,刪除結(jié)點*p,設(shè)*p為非終端結(jié)點?
p->prior->next=p->next;//①?
p->next->prior=p->prior;//②
free(p);}//③
與單鏈表上的插入和刪除操作不同的是,在雙鏈表中插入和刪除必須同時修改兩個方向上的指針。上述兩個算法的時間復(fù)雜度均為O(1)。順序表和鏈表比較時間性能:a、線性表:經(jīng)常性的查找;b、鏈?zhǔn)酱鎯Y(jié)構(gòu):經(jīng)常插入刪除操作;空間性能:a、對數(shù)據(jù)量大小事先可以知道的用線性表;b、數(shù)據(jù)量變化較大的用鏈?zhǔn)酱鎯Y(jié)構(gòu)。存儲密度越大,存儲空間的運用率越高。顯然,順序表的存儲密度是1,鏈表的存儲密度肯定小于1。第三章棧和隊列1.棧稱為后進先出(LastInFirstOut)的線性表,簡稱為LIFO表。?棧是運算受限的線性表,順序棧也是用數(shù)組表達的。?進棧操作:進棧時,需要將S->top加1,①S->top==StackSize-1表達棧滿②"上溢"現(xiàn)象--當(dāng)棧滿時,再做進棧運算產(chǎn)生空間溢出的現(xiàn)象。
退棧操作:退棧時,需將S->top減1,①S->top<0表達空棧②"下溢"現(xiàn)象--當(dāng)棧空時,做退棧運算產(chǎn)生的溢出現(xiàn)象。
下溢是正?,F(xiàn)象,常用作程序控制轉(zhuǎn)移的條件??諚r棧頂指針不能是0,只能是-1。兩個棧共享同一存儲空間:當(dāng)程序中同時使用兩個棧時,可以將兩個棧的棧底分別設(shè)在順序存儲空間的兩端,讓兩個棧頂各自向中間延伸。當(dāng)一個棧中的元素較多而棧使用的空間超過共享空間的一半時,只要另一個棧的元素不多,那么前者就可以占用后者的部分存儲空間。當(dāng)Top1=Top2-1時,棧滿
2.為了克服順序存儲分派固定空間所產(chǎn)生的溢出和空間浪費問題??刹捎面?zhǔn)酱鎯Y(jié)構(gòu)來存儲棧。鏈棧是沒有附加頭結(jié)點的運算受限的單鏈表。棧頂指針就是鏈表的頭指針。鏈棧中的結(jié)點是動態(tài)分派的,所以可以不考慮上溢,無須定義StackFull運算棧的一個重要應(yīng)用是實現(xiàn)遞歸,直接調(diào)用自己或間接調(diào)用自己的函數(shù)。3.隊列(Queue)是只允許在一端進行插入,而在另一端進行刪除的運算受限的線性表。允許刪除的一端稱為隊頭(Front),允許插入的一端稱為隊尾(Rear),當(dāng)隊列中沒有元素時稱為空隊列,隊列亦稱作先進先出(FirstInFirstOut)的線性表,簡稱為FIFO表。隊列的順序存儲結(jié)構(gòu)稱為順序隊列,順序隊列事實上是一個受限的線性表。
順序隊列的基本操作
①入隊時:將新元素插入rear所指的位置,然后將rear加1。
②出隊時:刪去front所指的元素,然后將front加1并返回被刪元素。當(dāng)頭尾指針相等時,隊列為空。
在非空隊列里,頭指針始終指向隊頭元素,而隊尾指針始終指向隊尾元素的下一位置。而棧頂指針指向棧頂元素。循環(huán)隊列:為充足運用數(shù)組空間,克服上溢,可將數(shù)組空間想象為一個環(huán)狀空間,并稱這種環(huán)狀數(shù)組表達的隊列為循環(huán)隊列。循環(huán)隊列中進行出隊、入隊操作時,頭尾指針仍要加1,朝前移動。只但是當(dāng)頭尾指針指向向量上界(QueueSize-1)時,其加1操作的結(jié)果是指向向量的下界0。這種循環(huán)意義下的加1操作可以描述為:①方法一:?
if(i+1==QueueSize)i=0;//i表達front或rear?
elsei++;?②方法二--運用"模運算"?
i=(i+1)%QueueSize;循環(huán)隊列中,由于入隊時尾指針向前追趕頭指針;出隊時頭指針向前追趕尾指針,導(dǎo)致隊空和隊滿時頭尾指針均相等。因此,無法通過條件Q.front==Q.rear來判別隊列是"空"還是"滿"。解決這個問題的方法至少有三種:?①另設(shè)一個標(biāo)志位以區(qū)別隊列是空還是滿;?②設(shè)立一個計數(shù)器記錄隊列中元素的總數(shù)(即隊列長度)。?③少用一個元素的空間。約定入隊前,測試尾指針在循環(huán)意義下加1后是否等于頭指針,若相等則認(rèn)為隊列滿即尾指針Q.rear所指的單元始終為空。 5.循環(huán)隊列的基本運算:①置隊空:Q->front=Q->rear=0;②判隊空:returnQ->rear==Q->front;③判隊滿:return(Q->rear+1)%QueueSize==Q->front;④入隊Q->data[Q->rear]=x;
//新元素插入隊尾?Q->rear=(Q->rear+1)%QueueSize;
⑤出隊temp=Q->data[Q->front];?Q->front=(Q->front+1)%QueueSize;
//循環(huán)意義下的頭指針加1
returntemp;⑥取隊頭元素returnQ->data[Q->front];隊列的鏈?zhǔn)酱鎯Y(jié)構(gòu)簡稱為鏈隊列。它是限制僅在表頭刪除和表尾插入的單鏈表。為了簡化解決,在隊頭結(jié)點之前附加一個頭結(jié)點,并設(shè)隊頭指針指向此結(jié)點。鏈隊列的基本運算:(帶頭結(jié)點)(1)構(gòu)造空隊:Q->rear=Q->front;Q->rear->next=NULL;(2)判隊空:returnQ->rear==Q->front;(3)入隊:QueueNode*p=(QueueNode*)malloc(sizeof(QueueNode));//申請新結(jié)點
p->dat(yī)a=x;
p->next=NULL;?
Q->rear->next=p;
//*p鏈到原隊尾結(jié)點后?
Q->rear=p;
//隊尾指針指向新的尾(4)出隊:當(dāng)隊列長度大于1時,只需修改頭結(jié)點指針,尾指針不變
s=Q->front->next;Q->front->next=s->next;x=s->data;free(s);returnx;當(dāng)隊列長度等于1時,不僅要修改頭結(jié)點指針,還要修改尾指針s=Q->front->next;Q->front->next=NULL;Q->rear==Q->front;x=s->data;free(s);returnx;(5)取隊頭元素:returnQ->front->next->data;由于有頭結(jié)點,所以用了next①和鏈棧類似,無須考慮判隊滿的運算及上溢。②在出隊算法中,一般只需修改隊頭指針。但當(dāng)原隊中只有一個結(jié)點時,該結(jié)點既是隊頭也是隊尾,故刪去此結(jié)點時亦需修改尾指針,且刪去此結(jié)點后隊列變空。7.用計算機來解決計算算術(shù)表達式問題,一方面要解決的問題是如何將人們習(xí)慣書寫的中綴表達式轉(zhuǎn)換成后綴表達式。第四章多維數(shù)組和廣義表1.數(shù)組的順序存儲方式:一般采用順序存儲方法表達數(shù)組。(1)行優(yōu)先順序
a11,a12,…,a1n,a21,a22,…,a2n,……,am1,am2,…,amn(2)列優(yōu)先順序
a11,a21,…,am1,a12,a22,…,am2,……,a1n,a2n,…,amnPascal和C語言是按行優(yōu)先順序存儲的,而Fortran語言是按列優(yōu)先順序存儲的。按行優(yōu)先順序存儲的二維數(shù)組Amn地址計算公式?LOC(aij)=LOC(a11)+[(i-1)×n+j-1]×d(注:此公式下界為1,如下界為0,則公式變?yōu)閇i×n+j])按列優(yōu)先順序存儲的二維數(shù)組Amn地址計算公式
LOC(aij)=LOC(a11)+[(j-1)×m+i-1]×d(注:此公式下界為1,如下界為0,則公式變?yōu)椋踛×m+i])按行優(yōu)先順序存儲的三維數(shù)組Amnp地址計算公式
LOC(aijk)=LOC(a111)+[(i-1)×n×p+(j-1)×p+k-1]×d(注:此公式下界為1,如下界為0,則公式變?yōu)閇i×n×p+j×p+k])2.為了節(jié)省存儲空間,可以對矩陣中有許多值相同或值為零的元素的矩陣,采用壓縮存儲。特殊矩陣是指相同值的元素或零元素在矩陣中的分布有一定的規(guī)律。常見的有對稱矩陣、三角矩陣。(1)對稱矩陣在一個n階方陣A中,若元素滿足下述性質(zhì):
aij=aji0≤i,j≤n-1稱為n階對稱矩陣,它的元素是關(guān)于主對角線對稱的,所以只需要存儲矩陣上三角或下三角元素即可,讓兩個對稱的元素共享一個存儲空間。矩陣元素aij和數(shù)組元素sa【k】之間的關(guān)系是k=i×(i+1)/2+ji≥j0≤k<n(n+1)/2-1k=j×(j+1)/2+ii<j0≤k<n(n+1)/2-1對稱矩陣的地址計算公式:LOC(aij)=LOC(sa[0])+[I×(I+1)/2+J]×d,其中I=max(i,j),J=min(i,j)(2)三角矩陣:以主對角線劃分,三角矩陣有上三角和下三角兩種。上三角矩陣是指它的下三角(不涉及主角線)中的元素均為常數(shù)c或零;下三角矩陣的主對角線上方均為常數(shù)c或零。一般情況,三角矩陣的常數(shù)c均為零。三角矩陣的壓縮存儲:三角矩陣中的反復(fù)元素c可共享一個存儲空間,其余的元素正好有n×(n+1)/2個,因此,三角矩陣可壓縮存儲在一維數(shù)組sa[n(n+1)/2+1]中,其中c存放在數(shù)組的最后一個元素中。①上三角矩陣中aij和sa[k]之間的相應(yīng)關(guān)系k=i×(2n-i+1)/2+j-i當(dāng)i≤jk=n×(n+1)/2當(dāng)i>j②下三角矩陣中aij和sa[k]之間的相應(yīng)關(guān)系k=i×(i+1)/2+j當(dāng)i≥jk=n×(n+1)/2當(dāng)i<j三角矩陣的壓縮存儲結(jié)構(gòu)是隨機存取結(jié)構(gòu)。3.稀疏矩陣:設(shè)矩陣Amn中有s個非零元素,若s遠(yuǎn)遠(yuǎn)小于矩陣元素的總數(shù),則稱A為稀疏矩陣。為了節(jié)省存儲單元,可用壓縮存儲方法只存儲非零元素。由于非零元素的分布一般是沒有規(guī)律的,因此在存儲非零元素的同時,還必須存儲非零元素所在的行、列位置,所以可用三元組(i,j,aij)來擬定非零元素。稀疏矩陣進行壓縮存儲通常有兩類方法:順序存儲(三元組表)和鏈?zhǔn)酱鎯?十字鏈表)。稀疏矩陣的壓縮存儲會失去隨機存取功能。4.廣義表是線性表的推廣,又稱列表。廣義表是n(n≥0)個元素a1,a2,…,ai,…,an的有限序列。其中ai或者是原子或者是一個廣義表。
①廣義表通常用圓括號括起來,用逗號分隔其中的元素。?
②為了區(qū)分原子和廣義表,書寫時用大寫字母表達廣義表,用小寫字母表達原子。
③若廣義表Ls非空(n≥1),則al是LS的表頭,其余元素組成的表(a1,a2,…,an)稱為Ls的表尾。?
④廣義表具有遞歸和共享的性質(zhì)廣義表的深度:一個表展開后所含括號的層數(shù)稱為廣義表的深度。19.廣義表是一種多層次的線性結(jié)構(gòu),事實上這就是一種樹形結(jié)構(gòu)。廣義表的兩個特殊的基本運算:取表頭head(Ls)和取表尾tail(Ls).任何一個非空廣義表的表頭可以是原子,也可以是子表,而其表尾必然是子表。?
head=(a,b)=a,tail(a,b)=(b)
對非空表A和(y),也可繼續(xù)分解。
注意:廣義表()和(())不同。前者是長度為0的空表,對其不能做求表頭和表尾的運算;而后者是長度為l的由空表作元素的廣義表,可以分解得到的表頭和表尾均是空表()。廣義表是一種有層次的非線性結(jié)構(gòu),通常采用鏈?zhǔn)酱鎯Y(jié)構(gòu),每個元素用一個結(jié)點表達,結(jié)點由3個域構(gòu)成,其中一個是tag標(biāo)志位,用來區(qū)分結(jié)點是原子還是子表,當(dāng)tag為零時結(jié)點是子表,第二個域為slink,用以存放子表的地址;當(dāng)tag為1時結(jié)點是原子,第二個域為data,用以存放元素值。第五章樹和二叉樹1.樹的表達法:最常用的是樹形圖表達法;尚有3種嵌套集合、凹形、廣義表。樹結(jié)構(gòu)的基本術(shù)語
(1)結(jié)點的度(Degree)
樹中的一個結(jié)點擁有的子樹數(shù)稱為該結(jié)點的度(Degree)。一棵樹的度是指該樹中結(jié)點的最大度數(shù)。?
度為零的結(jié)點稱為葉子(Leaf)或終端結(jié)點。度不為零的結(jié)點稱分支結(jié)點或非終端結(jié)點。?
除根結(jié)點之外的分支結(jié)點統(tǒng)稱為內(nèi)部結(jié)點。根結(jié)點又稱為開始結(jié)點。?(2)①途徑(path)若樹中存在一個結(jié)點序列k1,k2,…,ki,使得ki是ki+1的雙親(1≤i<j),則稱該結(jié)點序列是從kl到kj的一條途徑(Path)。?一個結(jié)點的祖先是從根結(jié)點到該結(jié)點途徑上所通過的所有結(jié)點,而一個結(jié)點的子孫則是以該結(jié)點為根的子樹中的所有結(jié)點。
結(jié)點的層數(shù)(Level)從根起算:根的層數(shù)為1,其余結(jié)點的層數(shù)等于其雙親結(jié)點的層數(shù)加1。?
雙親在同一層的結(jié)點互為堂兄弟。
樹中結(jié)點的最大層數(shù)稱為樹的高度(Height)或深度(Depth)。
若將樹中每個結(jié)點的各子樹當(dāng)作是從左到右有順序的(即不能互換),則稱該樹為有序樹(OrderedTree);否則稱為無序樹(UnoderedTree)。若不特別指明,一般討論的樹都是有序樹。
森林(Forest)是m(m≥0)棵互不相交的樹的集合。樹和森林的概念相近。刪去一棵樹的根,就得到一個森林;反之,加上一個結(jié)點作樹根,森林就變?yōu)橐豢脴?。?二叉樹與度數(shù)為2的有序樹不同:在有序樹中,雖然一個結(jié)點的孩子之間是有左右順序的,但是若該結(jié)點只有一個孩子,就無須區(qū)分其左右順序。而在二叉樹中,即使是一個孩子也有左右之分。二叉樹的性質(zhì):性質(zhì)1二叉樹第i層上的結(jié)點數(shù)目最多為2i-1(i≥1)。例如5層的二叉樹,第5層上的結(jié)點數(shù)目最多為24=16性質(zhì)2深度為k的二叉樹至多有2k-1個結(jié)點(k≥1)。例如深度為5的二叉樹,至多有25-1=31個結(jié)點性質(zhì)3在任意-棵二叉樹中,若終端結(jié)點的個數(shù)為n0,度為2的結(jié)點數(shù)為n2,則no=n2+1。例如一棵深度為4的二叉樹(a),其終端結(jié)點數(shù)n0為8,度為2的結(jié)點樹為7,則8=7+1,no=n2+1成立(b)其終端結(jié)點數(shù)n0為6,度為2的結(jié)點樹為5,則6=5+1,no=n2+1成立滿二叉樹:一棵深度為k且有2k-1個結(jié)點的二又樹稱為滿二叉樹。滿二叉樹的特點:(1)每一層上的結(jié)點數(shù)都達成最大值。即對給定的高度,它是具有最多結(jié)點數(shù)的二叉樹。(2)滿二叉樹中不存在度數(shù)為1的結(jié)點,每個分支結(jié)點均有兩棵高度相同的子樹,且樹葉都在最下一層上。完全二叉樹:若一棵深度為k的二叉樹,其前k-1層是一棵滿二叉樹,而最下面一層上的結(jié)點都集中在該層最左邊的若干位置上,則此二叉樹稱為完全二叉樹。特點:
(1)滿二叉樹是完全二叉樹,完全二叉樹不一定是滿二叉樹。
(2)在滿二叉樹的最下一層上,從最右邊開始連續(xù)刪去若干結(jié)點后得到的二叉樹仍然是一棵完全二叉樹。?
(3)在完全二叉樹中,若某個結(jié)點沒有左孩子,則它一定沒有右孩子,即該結(jié)點必是葉結(jié)點。性質(zhì)4
具有n個結(jié)點的完全二叉樹的深度為。?logn?+1或?log(n+1)?例,具有100個結(jié)點的完全二叉樹的深度為:?lg100?+1=7,26=6427=128所以?lg100?=6 ,?lg(100+1)?=7?4.完全二叉樹的編號特點:完全二叉樹中除最下面一層外,各層都充滿了結(jié)點。每一層的結(jié)點個數(shù)恰好是上一層結(jié)點個數(shù)的2倍。從一個結(jié)點的編號就可推得其雙親,左、右孩子等結(jié)點的編號。編號從0開始①若i=0,則qi為根結(jié)點,無雙親;否則,qi的雙親編號為?(i-1)/2?。②若2i+1<n,則qi的左孩子的編號是2i+1;否則,qi無左孩子,即qi必然是葉子。③若2i+2<n,則qi的右孩子的編號是2i+2;否則,qi無右孩子。對于完全二叉樹而言,使用順序存儲結(jié)構(gòu)既簡樸又節(jié)省存儲空間。但對于一般二叉樹來說,采用順序存儲時,為了使用結(jié)點在數(shù)組中的相對位置來表達結(jié)點之間的邏輯關(guān)系,就必須增長一些虛結(jié)點使其成為完全二叉樹的形式。5.鏈?zhǔn)酱鎯Y(jié)構(gòu):二叉樹的每個結(jié)點最多有兩個孩子。用鏈接方式存儲二叉樹時,每個結(jié)點除了存儲結(jié)點自身的數(shù)據(jù)外,還應(yīng)設(shè)立兩個指針域lchild和rchild,分別指向該結(jié)點的左孩子和右孩子。結(jié)點的結(jié)構(gòu)為:二叉鏈表是一種常用的二叉樹存儲結(jié)構(gòu)。建立二叉鏈表方法:a、按廣義表方法,靠近左括號的結(jié)點是在左子樹上,而逗號右邊結(jié)點是在右子樹上。b、按完全二叉樹的層次順序建立結(jié)點。具有n個結(jié)點的二叉鏈表中,共有2n個指針域。其中有n-1個用來指示結(jié)點的左、右孩子,其余的n+1個為空。二叉樹遍歷算法中的遞歸終止條件是二叉樹為空。中序遍歷的遞歸算法定義:(1)遍歷左子樹;(2)訪問根結(jié)點;(3)遍歷右子樹。先序遍歷的遞歸算法定義:(1)訪問根結(jié)點;(2)遍歷左子樹;(3)遍歷右子樹。后序遍歷得遞歸算法定義:(1)遍歷左子樹;(2)遍歷右子樹;(3)訪問根結(jié)點。遞歸工作棧中涉及兩項:一項是遞歸調(diào)用的語句編號,另一項則是指向根結(jié)點的指針。已知一棵二叉樹的前序和中序遍歷序列或中序和后序遍歷序列,可唯一擬定一棵二叉樹。具體方法如下:一方面根據(jù)前序或后序遍歷序列擬定二叉樹的各子樹的的根,然后根據(jù)中序遍歷序列擬定各子樹根的左右子樹。6.線索二叉樹:n個結(jié)點的二叉鏈表必然存在n+1個空指針域,可以運用這些空指針域,存放指向結(jié)點在某種遍歷順序下的前趨和后繼結(jié)點的指針,這種指向前驅(qū)和后繼結(jié)點的指針稱為"線索",這種加上線索的二叉鏈表稱為線索鏈表,相應(yīng)的二叉樹稱為線索二叉樹(Threaded
BinaryTree)。線索鏈表的結(jié)點結(jié)構(gòu):其中:ltag和rtag是增長的兩個標(biāo)志域,用來區(qū)分結(jié)點的左、右指針域是指向其左、右孩子的指針,還是指向其前趨或后繼的線索。
?
??
圖中的實線表達指針,虛線表達線索。線索二叉樹中,一個結(jié)點是葉結(jié)點的充要條件為:左、右標(biāo)志均是1。7.二叉樹的線索化:把對一棵二叉線索鏈表結(jié)構(gòu)中所有結(jié)點的空指針域按照某種遍歷順序加線索的過程稱為線索化。和中序遍歷算法同樣,遞歸過程中對每結(jié)點僅做一次訪問。因此對于n個結(jié)點的二叉樹,線索化的算法時間復(fù)雜度為O(n)。8.樹、森林到二叉樹的轉(zhuǎn)換:樹中每個結(jié)點最多只有一個最左邊的孩子(長子)和一個右鄰的兄弟。將樹轉(zhuǎn)換成二叉樹:①在所有兄弟結(jié)點之間加一道連線;②對每個結(jié)點,除了保存與其長子的連線外,去掉該結(jié)點與其它孩子的連線。由于樹根沒有兄弟,故樹轉(zhuǎn)化為二叉樹后,二叉樹的根結(jié)點的右子樹必為空。將一個森林轉(zhuǎn)換為二叉樹:將森林中的每棵樹轉(zhuǎn)化成二叉樹,然后再將二叉樹的根節(jié)點看做兄弟連在一起,形成一棵二叉樹
9.二叉樹到樹、森林的轉(zhuǎn)換:方式是:若二叉樹中結(jié)點x是雙親y的左孩子,則把x的右孩子,右孩子的右孩子,…,都與y用連線連起來,最后去掉所有雙親到右孩子的連線。10.樹的存儲結(jié)構(gòu):1.雙親表達法:雙親鏈表表達法運用樹中每個結(jié)點的雙親唯一性,在存儲結(jié)點信息的同時,為每個結(jié)點附設(shè)一個指向其雙親的指針parent,惟一地表達任何-棵樹。(1)雙親鏈表表達法的實現(xiàn)分析:E和F所在結(jié)點的雙親域是1,它們的雙親結(jié)點在向量中的位置是1,即B是它們的雙親。?
注意:①根無雙親,其parent域為-1。
②雙親鏈表表達法中指針parent向上鏈接,適合求指定結(jié)點的雙親或祖先(涉及根);求指定結(jié)點的孩子或其它后代時,也許要遍歷整個數(shù)組。2.孩子鏈表法:孩子鏈表表達法是為樹中每個結(jié)點設(shè)立一個孩子鏈表,并將這些結(jié)點及相應(yīng)的孩子鏈表的頭指針存放在一個向量中。注意:①孩子結(jié)點的數(shù)據(jù)域僅存放了它們在向量空間的序號。?
②與雙親鏈表表達法相反,孩子鏈表表達便于實現(xiàn)涉及孩子及其子孫的運算,但不便于實現(xiàn)與雙親有關(guān)的運算。
③將雙親鏈表表達法和孩子鏈表表達法結(jié)合起來,可形成雙親孩子鏈表表達法。3.孩子兄弟表達法:在存儲結(jié)點信息的同時,附加兩個分別指向該結(jié)點最左孩子和右鄰兄弟的指針域,即可得樹的孩子兄弟鏈表表達。注意:?
這種存儲結(jié)構(gòu)的最大優(yōu)點是:它和二叉樹的二叉鏈表表達完全同樣??蛇\用二叉樹的算法來實現(xiàn)對樹的操作。
11.樹的遍歷:一般都只給出兩種順序遍歷樹的方法:前序(先根順序)遍歷和后序(后根順序)遍歷。①前序遍歷一棵樹等價于前序遍歷該樹相應(yīng)的二叉樹
②后序遍歷一棵樹等價于中序遍歷該樹相應(yīng)的二叉樹。
對下面(a)圖中所示的森林進行前序遍歷和后序遍歷,則得到該森林的前序序列和后序序列分別為ABCDEFIGJH和BDCAIFJGHE。而(b)圖所示二叉樹的前序序列和中序序列也分別為ABCDEFIGJH和BDCAIFJGHE。前序遍歷森林等同于前序遍歷該森林相應(yīng)的二叉樹后序遍歷森林等同于中序遍歷該森林相應(yīng)的二叉樹12.從根結(jié)點到某結(jié)點之間的途徑長度與該結(jié)點上權(quán)的乘積稱為該結(jié)點的帶權(quán)途徑長度,樹種所有葉子結(jié)點的帶權(quán)途徑長度之和稱為樹的帶權(quán)途徑長度。帶權(quán)途徑長度WPL最小的二叉樹稱為哈夫曼樹或最優(yōu)二叉樹。哈夫曼樹不一定是二叉樹。哈夫曼樹又稱為最優(yōu)樹,是一類帶權(quán)途徑長度最短的樹。完全二叉樹就是這種途徑長度最短的二叉樹。①只有葉結(jié)點上的權(quán)值均相同時,完全二叉樹一定是最優(yōu)二叉樹,否則完全二叉樹不一定是最優(yōu)二叉樹。
②最優(yōu)二叉樹中,權(quán)越大的葉子離根越近。③最優(yōu)二叉樹的形態(tài)不唯一,WPL最小。13.哈夫曼算法:基本思想是:(1)根據(jù)給定的n個權(quán)值wl,w2,…,wn構(gòu)成n棵二叉樹的森林F={T1,T2,…,Tn},其中每棵二叉樹Ti中都只有一個權(quán)值為wi的根結(jié)點,其左右子樹均空。
(2)在森林F中選出兩棵根結(jié)點權(quán)值最小的樹(當(dāng)這樣的樹不止兩棵樹時,可以從中任選兩棵),將這兩棵樹合并成一棵新樹,為了保證新樹仍是二叉樹,需要增長一個新結(jié)點作為新樹的根,并將所選的兩棵樹的根分別作為新根的左右孩子(誰左,誰右無關(guān)緊要),將這兩個孩子的權(quán)值之和作為新樹根的權(quán)值。
(3)對新的森林F反復(fù)(2),直到森林F中只剩下一棵樹為止。這棵樹便是哈夫曼樹。
注意:①初始森林中的n棵二叉樹,每棵樹有一個孤立的結(jié)點,它們既是根,又是葉子?
②n個葉子的哈夫曼樹要通過n-1次合并,產(chǎn)生n-1個新結(jié)點。最終求得的哈夫曼樹中共有2n-1個結(jié)點。?
③哈夫曼樹是嚴(yán)格的二叉樹,沒有度數(shù)為1的分支結(jié)點。14.哈夫曼編碼:數(shù)據(jù)壓縮過程稱為編碼,反之,解壓縮的過程稱為解碼。設(shè)計一種長短不等的編碼,則必須保證任一字符的編碼都不是另一個字符編碼的前綴,這種編碼稱為前綴編碼??梢赃\用二叉樹來設(shè)計二進制的前綴編碼,其左分支表達字符0,右分支表達字符1,則以根結(jié)點到葉結(jié)點途徑上的分支字符組成的串作為該葉節(jié)點的字符編碼。因此設(shè)計電文總長最短的二進制前綴編碼,就是以n種字符出現(xiàn)的頻率作為權(quán)構(gòu)造一棵哈夫曼樹,由哈夫曼樹求得的編碼就是哈夫曼編碼。譯碼過程是從樹根結(jié)點出發(fā),逐個讀入電文中的二進制碼。第六章圖1.圖G由兩個集合構(gòu)成,頂點集合和邊集合,也可以圖G只有頂點而沒有邊。用尖括號表達圖的有向邊<vi,vj>,有向邊又稱為弧,起點稱為弧尾,終點稱為弧頭。無向圖的頂點對用圓括號表達(vi,vj)。在無向圖中,稱vi和vj相鄰接,在有向圖中稱頂點vi鄰接到vj,頂點vj鄰接于vi在無向圖中,n的取值范圍是0-n(n-1)/2,將具有n(n-1)/2條邊的無向圖稱為無向完全圖。在有向圖中,n的取值范圍是0-n(n-1),將具有n(n-1)條邊的有向圖稱為有向完全圖。無向圖中,頂點的度定義為以該頂點為一個端點的邊的數(shù)目,有向圖的度等于出度和入度之和。在無向圖中,任意兩頂點都有途徑,則稱兩頂點連通。若圖G中的任意兩個頂點都連通,稱G為連通圖。無向圖的極大連通子圖稱為連通分量,顯然,任何連通圖的連通分量只有一個,即其自身,而非連通的無向圖有多個連通分量。在有向圖中,圖G中任意兩頂點連通,稱為強連通圖,極大連通子圖稱為強連通分量。若在一個圖的每條邊上標(biāo)上某種數(shù)值,該數(shù)值稱為該邊的權(quán)。邊上帶權(quán)的圖稱為帶權(quán)圖,帶權(quán)的連通圖稱為網(wǎng)絡(luò)。2.圖的存儲結(jié)構(gòu):鄰接矩陣和鄰接表表達法。圖的頂點編號從0開始。鄰接矩陣表達法:<vi,vj>或(vi,vj)是邊,則值為1,不是邊則值為0。無向圖的鄰接矩陣是按主對角線對稱的。若G是帶權(quán)圖,只要把1換成相應(yīng)邊上的權(quán)值即可,0的位置上可以不動或?qū)⑵鋼Q成無窮大表達。無向圖的鄰接矩陣表達法可以僅存儲主對角線以下的元素,時間復(fù)雜度為O(n2)鄰接表表達法:鄰接表是圖的一種鏈?zhǔn)酱鎯Y(jié)構(gòu)。將無向圖的鄰接表稱為邊表,將有向圖的鄰接表稱為出邊表,將鄰接表的表頭向量稱為頂點表。若無向圖有n個頂點和e條邊,則它的鄰接表共有n個頭結(jié)點和2e個表結(jié)點。建立鄰接表的時間復(fù)雜度是O(n+e)。圖的鄰接表表達不是唯一的,這是由于在每個頂點的鄰接表中,各邊結(jié)點的鏈接順序可以是任意的,其具體鏈接順序與邊的輸入順序和生成算法有關(guān)。3.圖的遍歷:遍歷圖的算法是求解圖的連通性、圖的拓?fù)渑判虻人惴ǖ幕A(chǔ)。圖的遍歷常用的是深度優(yōu)先搜索遍歷和廣度優(yōu)先搜索遍歷兩種方法。深度優(yōu)先搜索遍歷(DFS)類似于前序(先根)遍歷。按訪問頂點的先后順序得到的頂點序列稱為圖的深度優(yōu)先遍歷序列,或簡稱為DFS序列。共需要搜索n2個矩陣元素,時間復(fù)雜度為鄰接矩陣O(n2)或鄰接表O(n+e)。廣度優(yōu)先搜索遍歷(BFS)類似于樹的按層次遍歷,先被訪問的頂點,其鄰接點也先被訪問,就是先進先出。時間復(fù)雜度為鄰接矩陣O(n2)或鄰接表O(n+e),空間復(fù)雜度都是O(n)。4.生成樹是連通圖的包含圖中所有頂點的一個極小連通子圖,一個圖的極小連通子圖恰為一個無回路的連通圖,也就是說,若圖中任意添加一條邊,就會出現(xiàn)回路,若去掉任意一條邊,都會使之成為非連通圖。因此,一個具有n個頂點的生成樹有且僅有n-1條邊,但有n-1條邊的圖不一定是生成樹,同一個圖可以有不同的生成樹。生成樹定義為:若從圖的某頂點出發(fā),可以系統(tǒng)的訪問到圖的所有頂點,則遍歷時通過的邊和圖的所有頂點所構(gòu)成的子圖,稱為該圖的生成樹。最小生成樹:圖的生成樹不唯一,把權(quán)值最小的生成樹稱為最小生成樹(MST)。構(gòu)造最小生成樹的算法:普里姆Prim算法的時間復(fù)雜度為O(n2)與網(wǎng)中邊數(shù)無關(guān)適于稠密圖。克魯斯卡爾Kruskal算法的時間復(fù)雜度為O(eloge),重要取決于邊數(shù),較適合于稀疏圖。5.最短途徑:Dijkstra迪杰斯特拉算法,提出了按途徑長度遞增的順序產(chǎn)生諸頂點的最短途徑算法。拓?fù)渑判?子工程稱為活動,頂點代表活動,有向邊代表活動的先后關(guān)系。這樣的有向無環(huán)圖DAG稱為頂點活動網(wǎng),簡稱為AOV網(wǎng)。將有向無環(huán)圖G中所有頂點排成一個線性序列,若<u,v>∈E(G),則在線性序列u在v之前,這種線性序列稱為拓?fù)湫蛄?。由AOV網(wǎng)構(gòu)造拓?fù)湫蛄械倪^程稱為拓?fù)渑判颉z測的方法是:對有向圖構(gòu)造其頂點的拓?fù)湫蛄?,若網(wǎng)中所有頂點都在他的拓?fù)湫蛄兄?則AOV網(wǎng)必然不存在環(huán)。AOV網(wǎng)的拓?fù)湫蛄胁皇俏ㄒ坏?。拓?fù)渑判虻拿枋鏊枷?a、在有向圖中選一個沒有前趨(入度為零)的頂點,且輸出之。b、從有向圖中刪除該頂點及其與該頂點有關(guān)的所有邊。c、反復(fù)上述環(huán)節(jié),直到所有頂點都已輸出或圖中剩余的頂點中沒有前趨頂點為止。d、輸出剩余的無前趨結(jié)點。拓?fù)渑判蚴聦嵣鲜菍︵徑颖肀磉_的圖G進行遍歷的過程。時間復(fù)雜度是O(n+e)。第七章排序1.假如待排序文獻中存在多個關(guān)鍵字相同的記錄,通過排序后,這些具有相同關(guān)鍵字的記錄之間的相對順序保持不變,該排序方法是穩(wěn)定的;反之,則是不穩(wěn)定的。排序在內(nèi)存中解決,不涉及數(shù)據(jù)的內(nèi)外存互換,稱為內(nèi)部排序,反之為外部排序。內(nèi)部排序又分為五類:插入、選擇、互換、歸并和分派排序。在排序過程中需進行兩種操作:比較兩個關(guān)鍵字的大小、改變指向記錄的指針或移動記錄自身,而待排序記錄的存儲形式一般有三種:順序結(jié)構(gòu)、鏈?zhǔn)浇Y(jié)構(gòu)和輔助表。評價排序算法的標(biāo)準(zhǔn):執(zhí)行算法需要的時間,以及算法所需要的附加空間。尚有算法自身的復(fù)雜度。排序的時間開銷,一般情況下可用算法中關(guān)鍵字的比較次數(shù)和記錄的移動次數(shù)來衡量。2.插入排序:每次將一個待排序記錄按其關(guān)鍵字大小插入到前面已排好序的文獻中的適當(dāng)位置。直接插入排序:每次從無序區(qū)取出第一個元素把它插入到有序區(qū)的適當(dāng)位置,使之成為新的有序區(qū),通過n-1次插入后完畢。算法中R[0]作用:保存R[i]副本,監(jiān)視數(shù)組下標(biāo)變量j是否越界。所以R[0]稱為哨兵。每次的比較是從后往前比較的。時間復(fù)雜度最佳是O(n),最壞是O(n2),所以是O(n2)。空間復(fù)雜度O(1),所以是就地排序。是穩(wěn)定的算法。初始情況是有序區(qū)中只有一個元素R[1],無序區(qū)中R[2..n]。希爾排序(縮小增量排序):算法不穩(wěn)定。記錄的總比較次數(shù)和總移動次數(shù)都要比直接插入排序少得多,特別是當(dāng)n越大越明顯。希爾排序的時間依賴于增量序列,最后一個增量必須是1,盡量避免增量互為倍數(shù)的情況。3.互換排序:兩兩比較待排序記錄的關(guān)鍵字,假如發(fā)現(xiàn)兩個記錄的順序相反時即進行互換,直到?jīng)]有反序位置。冒泡排序(起泡排序):通過相鄰元素之間比較和互換,使較小移向頂部,從后往前兩兩比較。時間復(fù)雜度最佳是O(n),最壞是O(n2),所以是O(n2)。是穩(wěn)定的排序算法。快速排序(劃分互換排序):是冒泡排序的改善。比較和互換從兩端向中間進行。一趟快速排序環(huán)節(jié):設(shè)兩個指針i和j,初值分別為low和high,基準(zhǔn)為x=R[i],一方面從j位置開始向前搜索第一個小于基準(zhǔn)x.key的記錄存入i所指位置上,i自增1,然后從i所指位置向后搜索找到第一個大于基準(zhǔn)x.key的記錄存入j所指位置上,j自減1,反復(fù)直至i=j為止??焖倥判蚴遣环€(wěn)定的。有非常好的時間復(fù)雜度,優(yōu)于其他各種排序算法,O(nlog2n),但是當(dāng)記錄關(guān)鍵字有序或基本有序時復(fù)雜度反而大了使之轉(zhuǎn)變成冒泡排序為O(n2)??焖倥判蚴沁f歸的,需要一個??臻g,空間復(fù)雜度O(log2n)。4.選擇排序:每一趟在待排序的記錄中選出關(guān)鍵字最小的記錄,依次存放在已排序好的記錄序列的最后。直接選擇排序:初始時,R[1..n]為無序區(qū),R[1]為空;第一趟是在R[1..n]中選出最小的記錄與R[1]互換,R[1]為有序區(qū);第二趟是在R[2..n]中選出最小的記錄與R[2]互換,R[1..2]為有序區(qū)。時間復(fù)雜度O(n2),是不穩(wěn)定的。初始情況是有序區(qū)為空,無序區(qū)中R[1..n],第一趟從R[1..n]選擇最小記錄與R[1]互換。堆排序:是對直接選擇排序的改善,是一種樹形選擇排序?;舅枷耄涸谂判蜻^程中,將記錄數(shù)組R[1..n]當(dāng)作是一棵完全二叉樹的順序存儲結(jié)構(gòu),運用完全二叉樹中雙親結(jié)點和孩子結(jié)點之間的內(nèi)在關(guān)系,在當(dāng)前無序區(qū)中選擇關(guān)鍵字最大或最小記錄。每一趟排序:將當(dāng)前無序區(qū)調(diào)整為一個大根堆,選取關(guān)鍵字最大的堆頂記錄,將他和無序區(qū)中最后一個記錄互換。堆排序是一個不斷建堆的過程。構(gòu)造堆的過程:R[1]作為二叉樹的根,R[2..n]依次逐層從左到右順序排列,構(gòu)成一棵完全二叉樹,任意結(jié)點R[i]的左孩子是R[2i],右孩子是R[2i+1],雙親是R?i/2?,此稱為篩選法。從?n/2?開始。每一趟的時間復(fù)雜度是O(log2n),整個堆排序的時間復(fù)雜度是O(nlog2n)。5.歸并排序:一方面將待排序文獻當(dāng)作n個長度為1的有序子文獻,把這些子文獻兩兩歸并,得到?n/2?個長度為2的有序子文獻,然后再將他們兩兩歸并,如此反復(fù),直到得到一個長度為n的有序文獻,此稱為二路歸并排序。每一趟歸并排序的時間復(fù)雜度是O(n),所以總的時間復(fù)雜度是O(nlog2n)。6.分派排序:前面方法都至少需要進行?nlogn?次比較,而分派排序?qū)r間復(fù)雜度降為O(n)。箱排序(桶排序):基數(shù)排序:是對箱排序的改善和推廣。箱排序只合用于關(guān)鍵字取值范圍較小的情況,否則所需箱子數(shù)目太多。每個分量也許取值的個數(shù)rd稱為基數(shù),基數(shù)的選擇和關(guān)鍵字的分解因關(guān)鍵字的類型而異。d趟箱排序?;鶖?shù)排序中,沒有進行關(guān)鍵字的比較和記錄的移動,而只是掃描鏈表和進行指針賦值,所以排序的時間重要用在修改指針上,初始化鏈表時間為O(n)。7.內(nèi)部排序方法分析比較:本章除基數(shù)排序外,都是在順序表上實現(xiàn)的。時間復(fù)雜度空間復(fù)雜度穩(wěn)定性插入直接插入O(n2)O(1)穩(wěn)定希爾排序O(nlog2n)或O(n1.25)O(1)不穩(wěn)定互換冒泡排序O(n2)O(1)穩(wěn)定快速排序O(nlog2n)O(log2n)不穩(wěn)定選擇直接選擇O(n2)O(1)不穩(wěn)定堆排序O(nlog2n)O(1)不穩(wěn)定歸并排序歸并排序O(nlog2n)O(n)穩(wěn)定分派排序基數(shù)排序O(d*(rd+n))rd是基數(shù),d是關(guān)鍵字位數(shù).n是元素個數(shù)O(rd+n)穩(wěn)定箱排序選取排序方法時需要考慮的重要因素:a、待排序的記錄個數(shù),b、記錄自身的大小和存儲結(jié)構(gòu),c、關(guān)鍵字的分布情況,d、對排序穩(wěn)定性的規(guī)定,e、時間和空間復(fù)雜度要等排序方法的選取:a、若待排序的一組記錄數(shù)目n較小(如n≤50)時,可采用插入排序或選擇排序;b、n較大時,則應(yīng)采用快速排序、堆排序或歸并排序;c、若待排序記錄按關(guān)鍵字基本有序時,則宜選用直接插入排序或冒泡排序;d、當(dāng)n很大,并且關(guān)鍵字位數(shù)較少時,采用鏈?zhǔn)交鶖?shù)排序較好;e、關(guān)鍵字比較次數(shù)與記錄的初始排列順序無關(guān)的排序方法是選擇排序。一般的排序方法都可以在順序結(jié)構(gòu)上實現(xiàn),當(dāng)記錄自身信息量較大時,可采用鏈?zhǔn)酱鎯Y(jié)構(gòu)。插入、歸并、基數(shù)排序易于在鏈表上實現(xiàn);快速排序和堆排序可以提取關(guān)鍵字建立索引表,然后對索引表進行排序。第八章:查找1.查找又稱檢索,是數(shù)據(jù)解決中經(jīng)常使用的一種重要運算。查找也分為內(nèi)查找和外查找。運算查找的重要操作是關(guān)鍵字的比較,因此把查找過程中的平均比較次數(shù)(也稱為平均查找長度)作為衡量算法效率優(yōu)劣的標(biāo)準(zhǔn)。2.順序表的查找:順序查找和二分查找順序查找又稱線性查找:查找成功的平均查找長度(n+1)/2,即約為表長的一半。假如查找成功和不成功機會相等,那么平均查找長度3(n+1)/4。優(yōu)點是簡樸,對表的結(jié)構(gòu)無任何規(guī)定,無論是順序存儲和鏈?zhǔn)酱鎯?、無論是否有序,都同樣合用,缺陷是效率低。對于有序表來說,該算法的平均查找長度是(n+1)/2。二分查找(折半查找):規(guī)定查找對象的線性表必須是順序存儲結(jié)構(gòu)的有序表。查找過程是遞歸的。樹中每個子樹的根節(jié)點相應(yīng)當(dāng)前查找區(qū)間的中位記錄R[mid],它的左子樹和右子樹分別相應(yīng)區(qū)間的左子表和右子表,通常將此樹稱為二叉鑒定樹。由于二分查找是在有序表上進行的,所以其相應(yīng)的鑒定樹必然是一棵二叉排序樹。二叉鑒定樹一定是二叉排序樹,二叉排序樹又稱為二叉查找樹。從鑒定樹上可見,關(guān)鍵字比較的次數(shù)恰好為該結(jié)點在樹中的層數(shù)。因此,二分查找算法在查找成功時進行關(guān)鍵字比較的次數(shù)最多不超過鑒定樹的深度。查找成功時的平均查找長度(n+1)/nlog2(n+1)-1,當(dāng)n很大時,可近似用log2(n+1)-1表達。由于鑒定樹度數(shù)小于2的結(jié)點只也許在最下面的兩層,所以n個結(jié)點的鑒定樹的深度和n個結(jié)點的完全二叉樹的深度相同,即為?log2(n+1)?。可見,二分查找的最壞性能和平均性能相稱接近。二叉鑒定樹的輸出:每次以?(low+high)/2?為根建樹。3.索引順序查找(分塊查找):是一種介于順序查找和二分查找之間的查找方法。規(guī)定分塊有序,前一塊的最大關(guān)鍵字小于后一塊的最小關(guān)鍵字,抽取各塊中的最大關(guān)鍵字及其起始位置構(gòu)成索引表。分塊查找的基本思想是:一方面查找索引表,可用二分查找或順序查找,然后在擬定的塊中進行順序查找。平均查找長度:二分查找lo
溫馨提示
- 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年度投標(biāo)擔(dān)保合同風(fēng)險管理與處理合同3篇
- 內(nèi)蒙古交通職業(yè)技術(shù)學(xué)院《光纖通信技術(shù)》2023-2024學(xué)年第一學(xué)期期末試卷
- 2024年公共交通廣告安裝與廣告資源共享合同2篇
- 2024年度企業(yè)間個人股東股權(quán)轉(zhuǎn)讓及股權(quán)結(jié)構(gòu)調(diào)整協(xié)議3篇
- 2024年度凈身出戶離婚協(xié)議書編寫規(guī)范解讀3篇
- 2024年度文化演出收益分成協(xié)議書模板3篇
- 2024年有限責(zé)任公司股東權(quán)益分配合同版
- 2024年度新能源項目三方收款委托及監(jiān)管協(xié)議3篇
- 2024年度消防泵站設(shè)計與建造合同14篇
- 2024版公共停車場設(shè)施維修與日常養(yǎng)護合同3篇
- 腰穿術(shù)護理常規(guī)
- 2021-2022學(xué)年統(tǒng)編版道德與法治五年級上冊全冊單元測試題及答案(每單元1套共6套)
- 2024政府采購評審專家知識題庫(含答案)
- 中國文化概論智慧樹知到答案2024年紹興文理學(xué)院
- 人力資源外包投標(biāo)方案
- GB/T 3863-2008工業(yè)氧
- CRH2型動車組一級檢修作業(yè)辦法081222
- 淺談失業(yè)保險的擴面征繳
- (完整版)西南財經(jīng)大學(xué)計量經(jīng)濟學(xué)期末考試試題
- 研究生英語議論文范文模板
- 酒店建筑BIM實施方案
評論
0/150
提交評論