![數(shù)據(jù)結(jié)構(gòu)C語言版復(fù)習(xí)攻略_第1頁](http://file4.renrendoc.com/view5/M01/31/0A/wKhkGGaFk-6ASHTjAAGqrqbkFKc124.jpg)
![數(shù)據(jù)結(jié)構(gòu)C語言版復(fù)習(xí)攻略_第2頁](http://file4.renrendoc.com/view5/M01/31/0A/wKhkGGaFk-6ASHTjAAGqrqbkFKc1242.jpg)
![數(shù)據(jù)結(jié)構(gòu)C語言版復(fù)習(xí)攻略_第3頁](http://file4.renrendoc.com/view5/M01/31/0A/wKhkGGaFk-6ASHTjAAGqrqbkFKc1243.jpg)
![數(shù)據(jù)結(jié)構(gòu)C語言版復(fù)習(xí)攻略_第4頁](http://file4.renrendoc.com/view5/M01/31/0A/wKhkGGaFk-6ASHTjAAGqrqbkFKc1244.jpg)
![數(shù)據(jù)結(jié)構(gòu)C語言版復(fù)習(xí)攻略_第5頁](http://file4.renrendoc.com/view5/M01/31/0A/wKhkGGaFk-6ASHTjAAGqrqbkFKc1245.jpg)
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
第一章:緒論
一、基礎(chǔ)知識(shí)
概念和術(shù)語(黑體字部分)。
另外,注意:
1、數(shù)據(jù)元素是數(shù)據(jù)的基本單位。P4
2、數(shù)據(jù)項(xiàng)是數(shù)據(jù)不可分割的最小單位。P5
3、數(shù)據(jù)結(jié)構(gòu)及其形式定義。P5
四種基本結(jié)構(gòu):①集合②線性結(jié)構(gòu)③樹形結(jié)構(gòu)④圖(網(wǎng))狀結(jié)構(gòu)
4、數(shù)據(jù)結(jié)構(gòu)的
邏輯結(jié)構(gòu)(抽象的,與實(shí)現(xiàn)無關(guān))
物理結(jié)構(gòu)(存儲(chǔ)結(jié)構(gòu))順序映像(順序存儲(chǔ)結(jié)構(gòu))位置“相鄰”
非順序映像(鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu))指針表示關(guān)系P6
5、數(shù)據(jù)類型P7
抽象數(shù)據(jù)類型(ADT)P7
ADT=(數(shù)據(jù)對象,數(shù)據(jù)關(guān)系,基本操作)
ADT細(xì)分為原子類型,固定聚合,可變聚合類型。P8
6、算法的概念P13
7、算法的五個(gè)特征
①有窮性②確定性③可行性④輸入(0個(gè)或多個(gè))⑤輸出(1個(gè)或多個(gè))
8、算法設(shè)計(jì)的要求:①正確性②可讀性③健壯性④效率與低存儲(chǔ)量
其中正確性的四個(gè)層次(通常要求達(dá)到C層)。
9、算法的時(shí)間復(fù)雜度P15
常見有:0(1),0(n),O(n'),0(log2n)),0(nlog2n),0(2")
語句頻度,用歸納法計(jì)算。
10、算法的空間復(fù)雜度P17
二、算法
起泡排序。P16
另一種形式
voidBubbleSort(DataTypea[],intn)
(
for(i=0;i<n-l;i++)
for(j=0;j<n-i-l;j++)
if(a[j]>a[j+l])
a[j]<—>a[j+l];
)
或
voidBubbleSort(DataTypea[],intn)
(
for(i=l;i<n;i++)
for(j=0;j<n-i;j++)
if(a[j]>a[j+l])
a[j]<—>a[j+l];
)
或
1分析算法的時(shí)間復(fù)雜度時(shí),logzn常簡單記作logn.
voidBubbleSort(DataTypea[],intn)
(
for(i=0;i<n-l;i++){
change=fasle;
for(j=0;j<n-i-l;j++)
if(a[j]>a[j+l]){
a[j]<—>a[j+l];
change=true;
)
if(!change)break;
說明:
a)考試中要求寫算法時(shí),可用類C,也可用C程序。
b)盡量書寫算法說明,言簡意賅。
c)技巧:用“邊界值驗(yàn)證法”檢查下標(biāo)越界錯(cuò)誤。
如上第一個(gè):第二個(gè)循環(huán)條件若寫作j<n-i,則當(dāng)i=0時(shí)a[j+l]會(huì)越界。
d)時(shí)間復(fù)雜度為0(r),第3個(gè)在最好情況下(待排記錄有序),時(shí)間復(fù)雜度為0(n)。
第二章、線性表
一、基礎(chǔ)知識(shí)和算法
1、線性表及其特點(diǎn)
線性表是n個(gè)數(shù)據(jù)元素的有限序列。
線性結(jié)構(gòu)的特點(diǎn):①“第一個(gè)”②“最后一個(gè)”③前驅(qū)④后繼。z
2、順序表一線性表的順序存儲(chǔ)結(jié)構(gòu)
(1)特點(diǎn):a)邏輯上相鄰的元素在物理位置上相鄰。b)隨機(jī)訪問。
(2)類型定義
簡而言之,“數(shù)組+長度”)
constintMAXSIZE=線性表最大長度;
typedefstruct{
DataTypeelem[MAXSIZE];
intlength;
}SqList;
注:a)SqList為類型名,可換用其他寫法。
b)DataType是數(shù)據(jù)元素的類型,根據(jù)需要確定。
c)MAXSIZE根據(jù)需要確定。如
constintMAXSIZE=64;
d)課本上的SqList類型可在需要時(shí)增加存儲(chǔ)空間,在上面這種定義下不可以
e)課本上的SqList類型定義中l(wèi)istsize表示已經(jīng)分配的空間大?。ㄈ菁{數(shù)據(jù)元素的個(gè)
數(shù))。當(dāng)插入元素而遇到L.length==L.listsize時(shí),用realloc(L.elem,L.listsize+增
2這里太簡煉了,只是為了便于記憶。
3不準(zhǔn)確的說法,只為便于理解和記憶,不要在正式場合引用。凡此情形,都加引號(hào)以示提醒。
量)重新分配內(nèi)存,而reallocO函數(shù)在必要的時(shí)候自動(dòng)復(fù)制原來的元素到新分配的空間
中。
(3)基本形態(tài)
1。.順序表空
條件L.length==001...MAXSIZE-1
不允許刪除操作.el
LemlL.length==0
2°.順序表滿
條件L.length==MAXSIZEL.elem[L.length==MAXSIZ
不允許插入操作L.ele
m[0<L.length<MAXSI
3°.不空也不滿
可以插入,刪除
(4)基本算法一一遍歷
4°.順序訪問所有元素for(i=0;i<L.length;i++)visit(L.elem[i]);
5查找元素x
for(i=0;i<L.length;i++)
if(L.elem[i]==x)break;
if(i<L.length)
找到;
else
未找到;
(2)插入算法Listinsert(&L,i,x)
1°.前提:表不滿
2°.合理的插入范圍:IWiWL.length+1
注:位序i在C/C++中對應(yīng)于下標(biāo)i-K
3°.步驟
第i至最后所有元素后移一個(gè)元素
在第i個(gè)位置插入元素x
表長增1
4°.算法
bool1Listinsert(SqList&L,inti,DataTypex)
(
if(L.length==MAXSIZEIi<l||i>L.length+1)returnfalse;//失敗
//元素后移
for(j=L.length-1;j>=i-l;j—)//這里j為下標(biāo),從L.lengthT至UiT
L.elem[j+l]=L.elem[j]://若作為位序,有如何修改?
//插入x
L.elem[i-l]=x;
//表長增1
L.length++;
"這里返回true表示正確插入,返回false表示插入失敗。以下常用來區(qū)分操作是否正確執(zhí)行。
returntrue;//插入成功
(3)刪除算法ListDelete(&L,i,&x)
1。.前提:表非空
2。.合理的刪除范圍:length
3°.步驟
取出第i個(gè)元素
第i個(gè)元素之后的元素向前移動(dòng)一個(gè)位置
表長減1
4°.算法
boolListDelete(SqList&L,inti,DataTypefex)
(
if(L.length==0|Ii<l||i>L.length)returnfalse;//失敗
x=L.elem[i-l];
for(j=i;j<L.length;j++)
L.elem[j-l]=L.;
L.length—;
returntrue;//刪除成功
(4)算法分析
表錯(cuò)誤!文檔中沒有指定樣式的文字。.1順序表插入和刪除算法的分析
插入刪除
基本操作移動(dòng)元素移動(dòng)元素
平均移動(dòng)次1"[(〃-/)=4
〃乙,=i\2
時(shí)間復(fù)雜度0(n)0(n)
尾端操作插入第n+1個(gè)元素,不移動(dòng)刪除第n個(gè)元素,不移動(dòng)
插入、刪除需移動(dòng)大量元素0(n);但在尾端插入、刪除效率高0(1)。
(5)其他算法
1°.InitList(&L),ClearList(&L)
L.length=0;
2°.ListEmpty(L)
returnL.length==0;
3°.ListLength(L)
returnL.length;
4°.GetElem(L,i,&e)
e=L.elem[i-l];
單鏈表一一線性表的鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)之一
(6)概念
線性鏈表,單鏈表,結(jié)點(diǎn);數(shù)據(jù)域,指針域;頭指針,頭結(jié)點(diǎn)。
(7)特點(diǎn)
用指針表示數(shù)據(jù)之間的邏輯關(guān)系(邏輯相鄰的元素物理位置不一定相鄰)。
(8)類型定義
簡而言之,“數(shù)據(jù)+指針”5。
typedefstructLNode{
DataTypedata;datanext
structLNode*next;
}LNode,*LinkList;
(9)基本形態(tài)
帶頭結(jié)點(diǎn)的單鏈表的基本形態(tài)有:
1°.單鏈表空
條件:L->next==0L—>A
2°.單鏈表不空
條件:L->next!=0L—>c-->a?c-->…c—>UnA
(10)基本算法(遍歷)
1°.順序訪問所有元素
借助指針,“順膜模4”(沿著鏈表訪問結(jié)點(diǎn))。
p=L->next;//注意起始位置的考慮
while(p!=NULL){//判表尾,另外(p!=0)或(p)均可
visit(p->data);//訪問:可以換成各種操作
p=p->next;〃指針沿著鏈表向后移動(dòng)
)
例:打印單鏈表中的數(shù)據(jù)。
voidPrintLinkList(LinkListL)
(
p=L->next;
while(p!=NULL){
print(p->data);//訪問:打印數(shù)據(jù)域
p=p->next;
}
)
2°.查找元素x
//在單鏈表L中查找元素x
不準(zhǔn)確的說法,只為便于理解和記憶,不要在正式場合引用。
//若找到,返回指向該結(jié)點(diǎn)的指針;否則返回空指針
LinkListFind(LinkListL,DataTypex)
(
p=L->next;
while(p!=NULL){
if(p->data=二x)returnp;//找到x
p=p->next;
)
returnNULL;//未找到
)
//在單鏈表L中查找元素x
//若找到,返回該元素的位序;否則返回0
intFind(LinkListL,DataTypex)
(
p=L->next;j=1;
while(p!=NULL){
if(p->data==x)returnj;//找到x
p=p->next;j++;//計(jì)數(shù)器隨指針改變
)
return0;//未找到
前一個(gè)算法的另一種寫法:
p=L->next;
while(p&&p->data!=x)
p=p->next;
if(p&&p->data==x)returnp;
elsereturn0;
或者
p=L->next;
while(p&&p->data!=x)p=p->next;
returnp;//為什么
3°.查找第i個(gè)元素
LinkListGet(LinkListL,inti)
(
p=L->next;j=1;
while(p&&j<i){
P=p->next;j++;
)
if(p&&j==i)returnp;
elsereturn0;
4°.查找第i-1個(gè)元素
P=L;j=0;
while(p&&j<i-l){
P=p->next;j++;
)
if(p&&j==i-l)returnp;
elsereturn0;
(11)插入算法Listinsert(&L,i,x)
技巧:畫圖輔助分析。
思路:
先查找第iT個(gè)元素
若找到,在其后插入新結(jié)點(diǎn)
bool"Listinsert(LinkList&L,inti,DataTypex)
//查找第iT個(gè)元素P
P=L;j=0;
while(p&&j<i-l){插入前
p=p->next;j++;
)
//若找到,在p后插入x
if(p&&j-i-l){
s=(LinkList)malloc(sizeof(LNode));執(zhí)行①之后
s->data=x;
s->next=p->next;〃①
p->next=s;//②
returntrue;//插入成功
)
else
returnfalse;//插入失敗
)
注意:
a)要讓p指向第iT個(gè)而不是第i個(gè)元素(否則,不容易找到前驅(qū)以便插入)。
b)能夠插入的條件:p&&j==i-l?即使第i個(gè)元素不存在,只要存在第iT個(gè)元素,
仍然可以插入第i個(gè)元素。
c)新建結(jié)點(diǎn)時(shí)需要?jiǎng)討B(tài)分配內(nèi)存。
s=(LinkList)malloc(sizeof(LNode));
若檢查是否分配成功,可用
if(s==NULL)exit(l);〃分配失敗則終止程序
d)完成插入的步驟:①②。技巧:先修改新結(jié)點(diǎn)的指針域。
6這里返回true表示正確插入,返回false表示插入失敗。
(12)刪除算法ListDelete(&L,i,&x)
思路:
先查找第iT個(gè)元素
若找到且其后存在第i個(gè)元素,則用x返回?cái)?shù)據(jù),并刪除之
boolListDelete(LinkList&L,inti,int&x)
(刪除前
//查找第iT個(gè)元素p
p=L;j=0;
while(p&&j<i-l){
p=p->next;j++;執(zhí)行①之后
}
〃若存在第i個(gè)元素,則用x返回?cái)?shù)據(jù),并刪除之
if(p&&j==iT&&p->next){//可以刪除
s=p->next;//①
p->next=s->next;//②
x=s->data;
free(s);
returntrue;
)
else
returnfalse;
)
注意:
a)要求p找到第iT個(gè)而非第i個(gè)元素。為什么?
b)能夠進(jìn)行刪除的條件:p&&j=i-l&&p->next?條件中的p->next就是要保證第
i個(gè)元素存在,否則無法刪除。若寫成p->next&&j==i-l也不妥,因?yàn)榇藭r(shí)(循環(huán)結(jié)束時(shí))
可能有P==NULL,所以必須先確定p不空。技巧:將條件中的“大前提”放在前面。該條件
也不可以寫成p->next&&p&&j==iT,因?yàn)橄扔衟!=0才有p->next,上式顛倒了這一關(guān)
系。
c)釋放結(jié)點(diǎn)的方法。free(s);
d)完成刪除的步驟:①②。
(13)建立鏈表的兩種方法
思路:
建立空表(頭結(jié)點(diǎn));
依次插入數(shù)據(jù)結(jié)點(diǎn)(每次插入表尾得⑶,a?,…,a”),每次插入表頭得(a?,…,a2,aj)。
1°.順序建表
voidCreateLinkList(LinkList&L,intn)
//建立空表
L=(LinkList)malloc(sizeof(LNode));
L->next=NULL;//空表
p=L;〃用p指向表尾
//插入元素
for(i=0;i<n;i++){
scanf(x);
s=(LinkList)malloc(sizeof(LNode)):
s->data=x;
//插入表尾
s->next=p->next;
p->next=s;
p=s;//新的表尾
)
}
2°.逆序建表
voidCreateLinkList(LinkList&L,intn)
(
//建立空表
L=(LinkList)malloc(sizeof(LNode));
L->next=NULL;//空表
//插入元素
for(i=0;i<n;i++){
scanf(x);
s=(LinkList)malloc(sizeof(LNode));
s->data=x;
//插入表頭
s->next=L->next;
L->next=s;
)
)
循環(huán)鏈表
(14)特點(diǎn)
最后一個(gè)結(jié)點(diǎn)的指針指向頭結(jié)點(diǎn)。
(15)類型定義
同單鏈表。
(16)基本形態(tài)
空表:L->next==Lo"----巴
非空表。工--------------------------------------------
L>c->a]c->?...c>3|)
(17)與單鏈表的聯(lián)系一
判斷表尾的方法不同:單鏈表用p==NULL;循環(huán)鏈表用p==L。
其余操作相同。
雙向循環(huán)鏈表
(18)特點(diǎn)
一個(gè)結(jié)點(diǎn)包含指向后繼(next)和指向前驅(qū)(prior)兩個(gè)指針,兩個(gè)方向又分別構(gòu)成循環(huán)鏈
表。
(19)類型定義
typedefstructDuLNode{
DataTypedata;
structDuLNode*prior,*next;〃兩個(gè)priddata指針
}DuLNode,*DuLinkList;
(20)基本形態(tài)
空表:用后向指針判斷L->next==L,或者用前向指針判斷L->prior==L。
非空表。
I
(21)與單鏈表和循環(huán)鏈表的聯(lián)系
最大不同:前驅(qū)容易求得,可以向前遍歷。
判斷表尾的方法與循環(huán)鏈表相同:P==L。
插入和刪除時(shí)需要修改兩個(gè)方向的指針。
(22)插入和刪除
需要修改兩個(gè)方向的指針。例如:(見下表)
表錯(cuò)誤!文檔中沒有指定樣式的文字。.2雙向循環(huán)鏈表的插入和刪除
P之后插入SP之前插入S刪除P之后繼s刪除p
s->next=s->prior=s=p->next;p->prior->next=
p->next;p->prior;p->next=p->next;
p->next=s;p->prior=s;s->next;p->next->prior=
s->prior=p;s->next=p;p->next->prior=p->prior;
s->next->priors->prior->next=P;
=s;s;
順序表與單鏈表的比較
表錯(cuò)誤!文檔中沒有指定樣式的文字。.3順序表和單鏈表的比較
順序表單鏈表
以地址相鄰表示關(guān)系用指針表示關(guān)系
隨機(jī)訪問,取元素0(1)順序訪問,取元素0(n)
插入、刪除需要移動(dòng)元素0(n)插入、刪除不用移動(dòng)元素0(n)(用于查找
位置)
總結(jié):需要反復(fù)插入、刪除,宜采用鏈表;反復(fù)提取,很少插入、刪除,宜采用順序表。
第三章、棧和隊(duì)列
棧
棧,棧頂,棧底,空棧,后進(jìn)先出(LIFO),入棧(Push),出棧(Pop)。
順序棧:棧的順序存儲(chǔ)結(jié)構(gòu);鏈棧:棧的鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)。
鏈棧
存儲(chǔ)結(jié)構(gòu)
用不帶頭結(jié)點(diǎn)的單鏈表實(shí)現(xiàn)。
S<----->3n---->an-1>'...>aiA
類型定義
同單鏈表。
基本形態(tài)
1°.???/p>
條件:S==NULL
S<-----?A
2°.棧非空
>…>
3°.棧滿(一般不出現(xiàn))S<----->anan-iai/\
基本算法
4°.入棧Push(&s,x)
boolPush(LinkList&s,DataTypex)
(
//新建結(jié)點(diǎn)
p=(LinkList)inalloc(sizeof(LNode));
if(!p)returnfalse;//失敗
p->data=x;
//插入棧頂
p->next=s;
s=p;
returntrue;
)
5°.出棧Pop(&s,&x)
前提:棧非空。
boolPop(LinkList&s,DataType&x)
(
if(s==NULL)returnfalse;//???/p>
//刪除棧頂元素
P=s;
s=s->next;
x=p->data;
free(p);
returntrue;
)
6°.棧頂元素
前提:棧非空。
boolTop(LinkList&s,DataType&x)
(
if(s==NULL)returnfalse;//???/p>
x=s->data;
returntrue;
)
順序棧
存儲(chǔ)結(jié)構(gòu)
類似于順序表,插入和刪除操作固定于表尾。
類型定義
簡單說,“數(shù)組+長度”7。
constintMAXSIZE=棧的最大容量;
typedefstruct{
DataTypeelem[MAXSIZE];
inttop;
}SqStack;
基本形態(tài)
7°.???/p>
條件s.top—0;
8°.棧滿
條件s.top==MAXSIZE
9°.棧不空、不滿
基本算法
10°.入棧Push(&s,x)
前提:棧不滿
boolPush(SqStack&s,DataTypex)
(
if(s.top==MAXSIZE)returnfalse;//棧滿
s.elem[top]=x;//或者s.elem[top++]=x;
top++;//代替這兩行
returntrue;
)
11°.出棧Pop(&s,&x)
前提:棧非空
boolPop(SqStack&s,DataType&x)
(
if(s.top==0)returnfalse;
top一;//可用x=s.elem[—top];
x=s.elem[top];//代替這兩行
returntrue;
)
7不準(zhǔn)確的說法,只為便于理解和記憶,不要在正式場合引用。
12°.棧頂元素
前提:棧非空
s.elem[top-l]即是。
隊(duì)列
隊(duì)列,隊(duì)頭,隊(duì)尾,空隊(duì)列,先進(jìn)先出(FIFO)。
鏈隊(duì)列:隊(duì)列的鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)。
循環(huán)隊(duì)列:隊(duì)列的順序存儲(chǔ)結(jié)構(gòu)之一。
鏈隊(duì)列
存儲(chǔ)結(jié)構(gòu)
簡而言之,”單鏈表+尾指針”%
類型定義
課本P61.
typedefstruct{Q.front
LinkListfront;
Q.rear
LinkListrear;
}LinkQueue;Q.frontaia?-*anA
Q.rear-------------------------------------------—f
基本形態(tài)
隊(duì)列空:Q.front==Q.rear。
非空隊(duì)列。
基本算法
13°.入隊(duì)列
課本P62。插入隊(duì)尾,注意保持Q.rear指向隊(duì)尾。
14°.出隊(duì)列
課本P62。刪除隊(duì)頭元素,
特別注意:如果隊(duì)列中只有一個(gè)元素,則隊(duì)頭也同時(shí)是隊(duì)尾,刪除隊(duì)頭元素后也需要修改
隊(duì)尾指針。
循環(huán)隊(duì)列
存儲(chǔ)結(jié)構(gòu)
簡單說,“數(shù)組+頭、尾位置”工
類型定義
constintMAXSIZE=隊(duì)列最大容量;
typedefstruct{
DataTypeelem[MAXSIZE];
intfront,rear;//隊(duì)頭、隊(duì)尾位置
}SqQueue;
8不準(zhǔn)確的說法,只為便于理解和記憶,不要在正式場合引用。
9不準(zhǔn)確的說法,只為便于理解和記憶,不要在正式場合引用。
基本形態(tài)
通常少用一個(gè)元素區(qū)分隊(duì)列空和隊(duì)列滿,也可以加一標(biāo)志。約定front指向隊(duì)頭元素的位
置,rear指向隊(duì)尾的下一個(gè)位置,隊(duì)列內(nèi)容為[front,rear)?
15°.隊(duì)列空
條件:Q.front==Q.rear。
不能出隊(duì)列。
16°.隊(duì)列滿
條件:(Q.rear+l)%MAXSIZE==Q.front(少用一個(gè)元素時(shí))。
不能入隊(duì)列。
17°.隊(duì)列不空也不滿
18°.加一標(biāo)志區(qū)分隊(duì)列空和隊(duì)列滿的情況
可以用滿所有空間。隊(duì)列空和隊(duì)列滿時(shí)都有Q.front==Q.rear,再用標(biāo)志區(qū)分。
隊(duì)列空:Q.front==Q.rearandQ.tag==0;隊(duì)列滿:Q.front==Q.rearandQ.tag==l?
基本算法
19°.入隊(duì)列
前提:隊(duì)列不滿。
boolEnQueue(SqQueue&Q,DataTypex)
{
if((Q.rear+l)%MAXSIZE==Q.front)returnfalse;//隊(duì)列滿
//入隊(duì)列
Q.elem[Q.rear]=x;
Q.rear=(Q.rear+l)%MAXSIZE;
returntrue;
)
20°.出隊(duì)列
前提:隊(duì)列非空。
boolDeQueue(SqQueue&Q,DataType&x)
(
if(Q.front==Q.rear)returnfalse;//隊(duì)列空
//出隊(duì)列
x=Q.elem[Q.front];
Q.front=(Q.front+l)%MAXSIZE;
returntrue;
)
21°.隊(duì)列中元素個(gè)數(shù)
結(jié)論:(Q.rear-Q.front+MAXSIZE)%MAXSIZE(.
注:Q.rear-Q.front可能小于0,需要加上MAXSIZE。
intQueueLength(SqQueueQ)
(
return(Q.rear-Q.front+MAXSIZE)%MAXSIZE;
)
22°.用標(biāo)志區(qū)分隊(duì)列空和滿
用標(biāo)志區(qū)分隊(duì)列空和滿時(shí),隊(duì)列初始化、入隊(duì)列、出隊(duì)列和隊(duì)列長度的算法如下:
voidInitQueue(SqQueue&Q){
Q.front=Q.rear=0;Q.tag=0;
)
boolEnQueue(SqQueue&Q,DataTypex){
if(Q.front==Q.rearandQ.tag==l)returnfalse;
Q.elem[Q.rear]=x;
Q.rear=(Q.rear+l)%MAXSIZE;
if(Q.tag==0)Q.tag=1;//隊(duì)列非空
returntrue;
)
boolDeQueue(SqQueue&Q,DataType&x){
if(Q.front==Q.rearandQ.tag==0)returnfalse;
x=Q.elem[Q.front];
Q.front=(Q.front+l)%MAXSIZE;
if(Q.front==Q.rear)Q.tag=0;//隊(duì)列空
returntrue;
)
intQueueLength(SqQueueQ)
(
if(Q.front-Q.rearandQ.tag==l)
returnMAXSIZE;//隊(duì)列滿
else
return(Q.rear-Q.front+MAXSIZE)%MAXSIZE;//隊(duì)列不滿(包含隊(duì)列空的情況)
)
棧和隊(duì)列比較
都是線形結(jié)構(gòu),棧的操作LIFO(后進(jìn)先出),隊(duì)列操作FIFO(先進(jìn)先出)。
簡化的棧和隊(duì)列結(jié)構(gòu)
在算法中使用棧和隊(duì)列時(shí)可以采用簡化的形式。
表錯(cuò)誤!文檔中沒有指定樣式的文字。"簡化的棧和隊(duì)列結(jié)構(gòu)
簡化棧簡化隊(duì)列
結(jié)構(gòu)“S口+top”結(jié)構(gòu)“q口+front+rearff
初始化top=0;初始化front=rear=0;
入棧s[top++]=X;入隊(duì)列q[rear]=x;
rear=(rear+l)%MAXSIZE;
出棧X=s[--top];出隊(duì)列x=q[front];
front二(front+l)%MAXSIZE;
棧頂s[top-1]隊(duì)列頭q[front]
??誸op==0隊(duì)列空front==rear
說明:只要棧(隊(duì)列)的容量足夠大,算法中可以省去檢查棧(隊(duì)列)滿的情況。
棧和隊(duì)列的應(yīng)用
23°.表達(dá)式求值
參見課本P53o
24°.括號(hào)匹配
例:檢查表達(dá)式中的括號(hào)是否正確匹配。如{()[]}正確,([)]}則錯(cuò)誤。
分析:每個(gè)左括號(hào)都“期待”對應(yīng)的右括號(hào),匹配成功則可以消去。
思路:遇到左括號(hào)則入棧,遇到右括號(hào)則與棧頂括號(hào)相比較,如果匹配則消去,否則匹配
失敗。當(dāng)然,如果棧中沒有括號(hào)可以匹配,或者最后棧中還有未匹配的左括號(hào),也都是匹
配錯(cuò)誤。
//檢查輸入的表達(dá)式中括號(hào)是否匹配
boolMatchBrackets()
constintMAXSIZE=1024;//棧的最大容量
chars[MAXSIZE];//簡化的棧結(jié)構(gòu)
inttop;//棧頂
//棧初始化
top=0;
//檢查括號(hào)是否匹配
ch=getchar();
while(ch!=E0F){
switch(ch){
case'(,['
s[top++]=ch//所有左括號(hào)入棧
break;
case')':
if(top==0ors[-top]!=,(')returnfalse;//??栈蛴依ㄌ?hào)與棧頂
左括號(hào)失配
case:
if(top==0ors[--top]!二')returnfalse;
case:
if(top==0ors[―top]!='{')returnfalse;
)
ch二getchar();//取下一個(gè)字符
)
if(top=0)returntrue;//正好匹配
elsereturnfalse;//棧中尚有未匹配的左括號(hào)
}
25°.遞歸程序的非遞歸化
將遞歸程序轉(zhuǎn)化為非遞歸程序時(shí)常使用棧來實(shí)現(xiàn)。
26。.作業(yè)排隊(duì)
如操作系統(tǒng)中的作業(yè)調(diào)度中的作業(yè)排隊(duì),打印機(jī)的打印作業(yè)也排成隊(duì)列。
27°.按層次遍歷二叉樹
voidLevelOrder(BinTreebt,VisitFuncvisit)
{
constintMAXSIZE=1024;//隊(duì)列容量(足夠大即可)
BinTreeq[MAXSIZE];//簡化的隊(duì)列結(jié)構(gòu)
intfront,rear;//隊(duì)頭、隊(duì)尾
if(!bt)return;
//初始化隊(duì)列,根結(jié)點(diǎn)入隊(duì)列
front=rear=0;
q[rear]二bt;
rear=(rear+l)%MAXSIZE;
//隊(duì)列不空,則取出隊(duì)頭訪問并將其左右孩子入隊(duì)列
while(front!=rear){
p=q[front];
front=(front+l)%MAXSIZE;
if(P){
visit(p->data);//訪問結(jié)點(diǎn)
q[rear]=p->lchild;
rear=(rear+1)%MAXSIZE;
q[rear]=p->rchild;
rear=(rear+1)%MAXSIZE;
第四章串
基礎(chǔ)知識(shí)和算法
概念
串,空串,空格串,串的長度;子串,子串在主串中的位置,主串;串相等。
串的基本操作
表錯(cuò)誤!文檔中沒有指定樣式的文字。.5串的基本操作
Assign(s,t),CreateAssign(s,t)將變量t賦值給s,Create(s,cs)根據(jù)字串創(chuàng)
(s,cs)建變量So
Equal(s,t),Length判斷串相等,求串長度。如Length()=0。
(s)
Concat(s,t)串連接。如Concat(“ab","cd")="abed”。
Substr(s,pos,len)取子串,pos為開始位置,len為子串長度。
Index(s,t)求子串t在主串s中的位置。如Index(“abc",“ab”)=1,
Index(aabe“,“be")二3。
Replace(s,t,v)把串s中的字串t替換成Vo如Replace("aaa","aa","
a")="aa”。
Delete(s,pos,len)刪除串s的一部分。____________________________________
注:完成習(xí)題集4.廣4.6。
串的存儲(chǔ)結(jié)構(gòu)
表錯(cuò)誤!文檔中沒有指定樣式的文字。.6串的存儲(chǔ)結(jié)構(gòu)__________________________
定長順序串最大長度固定,超過最大長度則作截?cái)嗵幚?/p>
堆分配存儲(chǔ)表示串的長度幾乎沒有限制
塊鏈存儲(chǔ)表示塊內(nèi)存儲(chǔ)空間連續(xù),塊間不連續(xù)______________________________
樹和二叉樹
基礎(chǔ)知識(shí)和算法
樹及有關(guān)概念
樹,根,子樹;結(jié)點(diǎn),結(jié)點(diǎn)的度,葉子(終端結(jié)點(diǎn)),分支結(jié)點(diǎn)(非終端結(jié)點(diǎn)),內(nèi)部結(jié)點(diǎn),
樹的度;孩子,雙親,兄弟,祖先,子孫,堂兄弟;層次(根所在層為第1層),深度,高
度;有序樹,無序樹,二叉樹是有序樹;森林。
二叉樹
二叉樹(二叉樹與度為2的樹不同,二叉樹的度可能是0,1,2);左孩子,右孩子。
二叉樹的五種基本形態(tài)。
二叉樹的性質(zhì)
28°.二叉樹的第i層"上至多有‘個(gè)結(jié)點(diǎn)。
29°.深度為k的二叉樹至多有2k-l個(gè)結(jié)點(diǎn)。
滿二叉樹:深度為k,有2匚1個(gè)結(jié)點(diǎn)。
完全二叉樹:給滿二叉樹的結(jié)點(diǎn)編號(hào),從上至下,從左至右,n個(gè)結(jié)點(diǎn)的完全二叉樹中結(jié)
點(diǎn)在對應(yīng)滿二叉樹中的編號(hào)正好是從1到no
30°.葉子結(jié)點(diǎn)n0,度為2的結(jié)點(diǎn)為n2,則n0=m+l。
考慮結(jié)點(diǎn)個(gè)數(shù):n=no+m+我
考慮分支個(gè)數(shù):n-1=2n2+n1
可得n0=n2+l
例:1)二叉樹有n個(gè)葉子,沒有度為1的結(jié)點(diǎn),共有一個(gè)結(jié)點(diǎn)。2)完全二叉樹的第3
層有2個(gè)葉子,則共有一個(gè)結(jié)點(diǎn)。
分析:1)度為2的結(jié)點(diǎn)有n-1個(gè),所以共2n-l個(gè)結(jié)點(diǎn)。2)注意考慮到符合條件的二叉
樹的深度可能是3或4,所以有5、10或11個(gè)結(jié)點(diǎn)。
31°.n個(gè)結(jié)點(diǎn)的完全二叉樹深度為[log〃」+1。
32°.n個(gè)結(jié)點(diǎn)的完全二叉樹,結(jié)點(diǎn)按層次編號(hào)
有:i的雙親是如果i=1時(shí)為根(無雙親);
i的左孩子是2i,如果2i>n,則無左孩子;
i的右孩子是2i+1,如果2i+l>n則無右孩子。
二叉樹的存儲(chǔ)結(jié)構(gòu)
33°.順序存儲(chǔ)結(jié)構(gòu)
用數(shù)組、編號(hào)i的結(jié)點(diǎn)存放在[i-1]處。適合于存儲(chǔ)完全二叉樹。
i0本書中約定根結(jié)點(diǎn)在第1層,也有約定根在第o層的,則計(jì)算公式會(huì)有所不同.
34°.鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)
二叉鏈表:
typedefstructBTNode{
DataTypedata;
structBTNode*lchild,*rchild;
}BTNode,*BinTree;
三叉鏈表:
typedefstructBTNode{
DataTypedata;
structBTNode*lchild,*rchild,"parent;
}BTNode,*BinTree;
例:用二叉鏈表存儲(chǔ)n個(gè)結(jié)點(diǎn)的二叉樹(n>0),共有(3)個(gè)空指針域;采用三叉鏈表存儲(chǔ),
共有(也)個(gè)空指針域。"
二叉樹的五種基本形態(tài)
①②③④⑤
①空樹:bt==NULL②左右子樹均空:bt->lchild==NULLandbt->rchild==NULL
③右子樹為空:bt->rchild==NULL④左子樹為空:bt->lchild==NULL
⑤左右子樹均非空。
前兩種常作為遞歸結(jié)束條件,后三者常需要遞歸。
遍歷二叉樹
35°.常見有四種遍歷方式
按層次遍歷,先序遍歷,中序遍歷,后序遍歷。
按層次遍歷:“從上至下,從左至右”,利用隊(duì)列。
先序遍歷:DLR;中序遍歷:LDR;后序遍歷LRD。
例:寫出a+b*(c-d)-e/f的前綴、中綴和后綴表達(dá)式。
畫出二叉樹,分別進(jìn)行前序、中序、后序遍歷即可得到。
前綴表達(dá)式:-+a*b-cd/ef
中綴表達(dá)式:a+b*c-d-e/f
后綴表達(dá)式:abcd-*+ef/-
36°.先序遍歷算法
voidPreorder(BinTreebt)
{
if(bt){
visit(bt->data);
11答案:(a)n+1(b)n+2,提示:只有根結(jié)點(diǎn)沒有雙親。
Preorder(bt->lchild);
Preorder(bt->rchild);
)
)
37°.中序遍歷算法
voidInorder(BinTreebt)
(
if(bt){
Inorder(bt->lchild);
visit(bt->data);
Inorder(bt->rchild);
38°.后序遍歷
voidPostorder(BinTreebt)
(
if(bt){
Postorder(bt->lchild);
Postorder(bt->rchild);
visit(bt->data);
)
)
39°.按層次遍歷
思路:利用一個(gè)隊(duì)列,首先將根(頭指針)入隊(duì)列,以后若隊(duì)列不空則取隊(duì)頭元素P,如果
P不空,則訪問之,然后將其左右子樹入隊(duì)列,如此循環(huán)直到隊(duì)列為空。
voidLevelOrder(BinTreebt)
(
//隊(duì)列初始化為空
InitQueue(Q);
//根入隊(duì)列
EnQueue(Q,bt);
//隊(duì)列不空則繼續(xù)遍歷
while(!QueueEmpty(Q)){
DeQueue(Q,p);
if(p!=NULL){
visit(p->data);
//左、右子樹入隊(duì)列
EnQueue(Q,p->lchild);
EnQueue(Q,p->rchild);
)
)
)
若隊(duì)列表示為“數(shù)組q[]+頭尾front,rear"有:
voidLevelOrder(BinTreebt)
(
constintMAXSIZE=1024;
BinTreeq[MAXSIZE];
intfront,rear;
//隊(duì)列初始化為空
front=rear=0;
//根入隊(duì)列
q[rear]=bt;rear=(rear+1)%MAXSIZE;
//隊(duì)列不空則循環(huán)
while(front!=rear){
p=q[front];front=(front+1)%MAXSIZE;
if(P){
visit(p->data);
//左、右子樹入隊(duì)列
q[rear]=p->lchild;rear=(rear+1)%MAXSIZE;
q[rear]=p->rchild;rear二(rear+1)%MAXSIZE;
}
)
)
40°,非遞歸遍歷二叉樹
一般借助棧實(shí)現(xiàn)。設(shè)想一指針沿二叉樹中序順序移動(dòng),每當(dāng)向上層移動(dòng)時(shí)就要出棧。
(a)中序非遞歸遍歷
指針P從根開始,首先沿著左子樹向下移動(dòng),同時(shí)入棧保存;當(dāng)?shù)竭_(dá)空子樹后需要退棧訪
問結(jié)點(diǎn),然后移動(dòng)到右子樹上去。
voidInOrder(BinTreebt,VisitFuncvisit)
(
InitStack(S);
P=bt;
while(pII!StackEmpty(S)){
if(P){
Push(S,p);
p=p->lchild;
}else(
Pop(S,p);
visit(p);//中序訪問結(jié)點(diǎn)的位置
p=p->rchild;
)
)
)
⑹先序非遞歸遍歷
按照中序遍歷的順序,將訪問結(jié)點(diǎn)的位置放在第一次指向該結(jié)點(diǎn)時(shí)。
voidPreorder(BinTreebt,VisitFuncvisit)
InitStack(S);
P=bt;
while(pII!StackEmpty(S)){
if(P){
visit(p);//先序訪問結(jié)點(diǎn)的位置
Push(S,p);
p=p->lchild;
}else{
Pop(S,p);
p=p->rchild;
)
)
}
或者,由于訪問過的結(jié)點(diǎn)便可以棄之不用,只要能訪問其左右子樹即可,寫出如下算法。
voidPreorder(BinTreebt,VisitFuncvisit)
(
InitStack(S);
Push(S,bt);
while(!StackEmpty(S)){
Pop(S,p);
if(P){
visit(p);
Push(S,p->rchild);//先進(jìn)棧,后訪問,所以
Push(S,p->lchild);//這里先讓右子樹進(jìn)棧
)
)
)
(c)后序非遞歸遍歷
后序遍歷時(shí),分別從左子樹和右子樹共兩次返回根結(jié)點(diǎn),只有從右子樹返回時(shí)才訪問根結(jié)
點(diǎn),所以增加一個(gè)棧標(biāo)記到達(dá)結(jié)點(diǎn)的次序。
voidPostOrder(BinTreebt,VisitFuncvisit)
(
InitStack(S),InitStack(tag);
P=bt;
while(pH!StackEmpty(S)){
if(P){
Push(S,p),Push(tag,1);//第一次入棧
p=p->lchild;
}else{
Pop(S,p),Pop(tag,f);
if(f==l){
//從左子樹返回,二次入棧,然后p轉(zhuǎn)右子樹
Push(S,p),Push(tag,2);
p=p->rchild;
}else{
//從右子樹返回(二次出棧),訪問根結(jié)點(diǎn),p轉(zhuǎn)上層
visit(p);
p=NULL;//必須的,使下一步繼續(xù)退棧
)
}
)
注:后序非遞歸遍歷的過程中,棧中保留的是當(dāng)前結(jié)點(diǎn)的所有祖先。這是和先序及中序遍
歷不同的。在某些和祖先有關(guān)的算法中,此算法很有價(jià)值。
41°.三叉鏈表的遍歷算法
下面以中序遍歷為例。
//中序遍歷三叉鏈表存儲(chǔ)的二叉樹
voidInorder(BinTreebt,VisitFuncvisit)
(
if(bt==NULL)return;//空樹,以下考慮非空樹
//找到遍歷的起點(diǎn)
p=bt;//Note:p!=nullhere
while(p->lchild)p=p->lchild;
//開始遍歷
while(p){
//訪問結(jié)點(diǎn)
visit(p);
//p轉(zhuǎn)下一個(gè)結(jié)點(diǎn)
if(p->rchild){//右子樹不空,下一個(gè)在右子樹
p=p->rchild;
while(p->lchild)p=p->lchild;//轉(zhuǎn)右子樹的最左下結(jié)點(diǎn)
}else{//右子樹為空,下一個(gè)在上層
f=p->parent;
while(p==f->rchild){//若p是右子樹則一直上溯
P=f;f=f->parent;
)
)
)
)
遍歷二叉樹的應(yīng)用
42°.寫出遍歷序列(前、中、后序)
43°.根據(jù)遍歷序列畫出二叉樹
(a)已知前序和中序序列,唯一確定二叉樹。
例:前序:ABDEGCFH,中序:DBGEAFHC,畫出二叉樹。
分析:前序序列的第一個(gè)是根,這是解題的突破口。
步驟:①前序序列的第一個(gè)是根②在中序序列中標(biāo)出根,分成左右子樹③在前序序列中
標(biāo)出左右子樹(根據(jù)結(jié)點(diǎn)個(gè)數(shù)即可)④分別對左右子樹的前序和中序序列重復(fù)以上步驟直
至完成。
(b)已知后序和中序序列,唯一確定二叉樹。
例:后序:DGEBHFCA,中序:DBGEAFHC,畫出二叉樹。
分析:后序序列的最后一個(gè)是根,這是解題的突破口。
步驟:①后序序列的最后一個(gè)是根②在中序序列中標(biāo)出根,分成左右子樹③在后序序列
中標(biāo)出左右子樹(根據(jù)結(jié)點(diǎn)個(gè)數(shù)即可)④分別對左右子樹的后序和中序序列重復(fù)以上步驟
直至完成。
(c)已知前序和后序序列,不存在度為1的結(jié)點(diǎn)時(shí)能唯一確定二叉樹。
例:前序:ABDEC,后序:DEBCA,畫出二叉樹。又前序AB,后序BA則不能唯一確定二叉樹。
注:對于不存在度為1的結(jié)點(diǎn)的二叉樹,首先確定根結(jié)點(diǎn),然后總可以將其余結(jié)點(diǎn)序列劃
分成左右子樹,以此類推即可確定二叉樹。
說明:畫出二叉樹后可以進(jìn)行遍歷以便驗(yàn)證。
44°.編寫算法
思路:按五種形態(tài)(①一⑤)分析,適度簡化。
例:求二叉樹結(jié)點(diǎn)的個(gè)數(shù)。
分析:①0;②1;③L+1;④1+R;⑤1+L+R。
簡化:②l+Lo+Rs③1+L+R-o④1+U+R⑤1+L+R可合并成⑤一種情況。
intNodeCount(BinTreebt)
(
if(bt==O)return0;
elsereturn1+NodeCount(bt->lchild)+NodeCount(bt->rchiId);
)
例:求二叉樹葉子結(jié)點(diǎn)的個(gè)數(shù)。
分析:①0;②1;③L;④R;⑤L+Ro簡化:③④⑤可合并成⑤。
intLeafCount(BinTreebt)
(
if(bt-0)return0;
elseif(bt->lchild—0andbt->rchild-0)return1;
elsereturnLeafCount(bt->lchild)+LeafCount(bt->rchiId);
)
例:求二叉樹的深度。
分析:①0;②1;③1+L;④1+R;⑤l+max(L,R)。簡化:②③④⑤可合并成⑤。
intDepth(BinTreebt)
(
if(bt—0)return0;
elsereturn1+max(Depth(bt->lchiId),Depth(bt->rchiId));
)
線索二叉樹
45°.線索
n個(gè)結(jié)點(diǎn)的二叉鏈表中有n+1個(gè)空指針,可以利用其指向前驅(qū)或后繼結(jié)點(diǎn),叫線索,同時(shí)需
附加一個(gè)標(biāo)志,區(qū)分是子樹還是線索。
Ichild?tagdatartagrchild
*0/10/1
Ichild有左子樹,則指向左子樹,標(biāo)志Itag==0;
沒有左子樹,可作為前驅(qū)線索,標(biāo)志Itag==1。
rchild有右子樹,則指向右子樹,標(biāo)志rtag==0:
沒有右子樹,可作為后繼線索,標(biāo)志rtag==lo
46°.線索化二叉樹
利用空指針作為線索指向前驅(qū)或后繼。左邊空指針可以作為前驅(qū)線索,右邊空指針可以作
為后繼線索,可以全線索化或部分線索化。
表錯(cuò)誤!文檔中沒有指定樣式的文字。.7線索化二叉樹的類型
前驅(qū)、后繼線索
溫馨提示
- 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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 施工質(zhì)量交底內(nèi)容范本
- 施工現(xiàn)場施工防化學(xué)事故制度
- 高效班級(jí)管理行為規(guī)范與文化塑造
- DB6103T 85-2025露地線辣椒栽培技術(shù)規(guī)范
- 兩人合伙投資合同范本
- 中外能源開發(fā)合作合同
- 三人合資辦廠合同模板大全
- 臨時(shí)用工合同范本及解析
- 個(gè)人住房補(bǔ)貼貸款合同范文
- 產(chǎn)品經(jīng)銷合同
- (部編)五年級(jí)語文下冊小練筆(21篇)
- 安全閥拆除與回裝方案
- 《企業(yè)人力資源管理師考試用書考試通過必備一級(jí)》
- 2023年高考英語考前必練-非謂語動(dòng)詞(含近三年真題及解析)
- 高??萍汲晒D(zhuǎn)化政策與案例分享
- 全國職工拔河比賽執(zhí)行方案
- 冶金廠、軋鋼廠工藝流程圖
- 《民航服務(wù)溝通技巧》教案第15課民航服務(wù)人員下行溝通的技巧
- 中國人婚戀狀況調(diào)查報(bào)告公布
- 早產(chǎn)兒視網(wǎng)膜病變
- GB 10665-1997碳化鈣(電石)
評論
0/150
提交評論