數(shù)據(jù)結(jié)構(gòu)課件教材_第1頁
數(shù)據(jù)結(jié)構(gòu)課件教材_第2頁
數(shù)據(jù)結(jié)構(gòu)課件教材_第3頁
數(shù)據(jù)結(jié)構(gòu)課件教材_第4頁
數(shù)據(jù)結(jié)構(gòu)課件教材_第5頁
已閱讀5頁,還剩102頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、第二章 線性表2.1 線性表及其基本運(yùn)算2.2 線性表的順序存儲(chǔ)結(jié)構(gòu)2.3 線性表的鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)線性表的邏輯結(jié)構(gòu)、物理結(jié)構(gòu),以及它們之間的相互關(guān)系;定義與之相適應(yīng)的運(yùn)算;設(shè)計(jì)相應(yīng)的算法;分析算法的效率。線性結(jié)構(gòu)特點(diǎn):在數(shù)據(jù)元素的非空有限集中n存在存在唯一唯一的一個(gè)被稱作的一個(gè)被稱作“第一個(gè)第一個(gè)”的數(shù)據(jù)元的數(shù)據(jù)元素素n存在存在唯一唯一的一個(gè)被稱作的一個(gè)被稱作“最后一個(gè)最后一個(gè)”的數(shù)據(jù)的數(shù)據(jù)元素元素n除第一個(gè)外,集合中的每個(gè)數(shù)據(jù)元素均除第一個(gè)外,集合中的每個(gè)數(shù)據(jù)元素均只有只有一個(gè)前驅(qū)一個(gè)前驅(qū)n除最后一個(gè)外,集合中的每個(gè)數(shù)據(jù)元素均除最后一個(gè)外,集合中的每個(gè)數(shù)據(jù)元素均只只有一個(gè)后繼有一個(gè)后繼2.1

2、線性表及其基本運(yùn)算例 英文字母表(A,B,C,.Z)是一個(gè)線性表例學(xué)號姓名年齡001張三18002李四19數(shù)據(jù)元素一、線性表(linear_list) 線性表是n個(gè)數(shù)據(jù)元素的有限序列,記為: L=(a1, a2,an)線性表的特點(diǎn) 同一性:同一性:線性表由線性表由同類同類數(shù)據(jù)元素組成,每一個(gè)數(shù)據(jù)元素組成,每一個(gè)ai必必須屬于須屬于同一同一數(shù)據(jù)對象數(shù)據(jù)對象,且不能出現(xiàn)缺項(xiàng)。且不能出現(xiàn)缺項(xiàng)。 有窮性:有窮性:線性表由線性表由有限個(gè)有限個(gè)數(shù)據(jù)元素組成,表長度數(shù)據(jù)元素組成,表長度就是表中數(shù)據(jù)元素的個(gè)數(shù)就是表中數(shù)據(jù)元素的個(gè)數(shù)n,當(dāng)當(dāng)n=0時(shí)為時(shí)為空表空表。 有序性:有序性:線性表中相鄰數(shù)據(jù)元素之間存在線

3、性表中相鄰數(shù)據(jù)元素之間存在著序偶關(guān)系著序偶關(guān)系。1in時(shí)時(shí)ai的直接前驅(qū)是的直接前驅(qū)是ai-1,a1無直接前驅(qū)無直接前驅(qū)ai的直接后繼是的直接后繼是ai+1,an無直接后繼無直接后繼二、線性表的抽象數(shù)據(jù)類型定義抽象數(shù)據(jù)類型定義抽象數(shù)據(jù)類型定義 :ADT LinearList數(shù)據(jù)元素?cái)?shù)據(jù)元素:D=ai| aiD0, i=1,2,,n n0 ,D0為某一數(shù)據(jù)對象 關(guān)系關(guān)系: | ai, ai+1D0,i=1,2, ,n-1 基本操作基本操作: (1)InitList(L) 操作前提:L為未初始化線性表。 操作結(jié)果:將L初始化為空表。 (2)DestroyList(L) 操作前提:線性表L已存在。

4、操作結(jié)果:將L銷毀。 (3)ClearList(L) 操作前提:線性表L已存在 。 操作結(jié)果:將表L置為空表。 ADT LinearList2.2 線性表的順序存儲(chǔ)結(jié)構(gòu)2.2.1 線性表的順序存儲(chǔ)結(jié)構(gòu) 2.2.2 線性表順序存儲(chǔ)結(jié)構(gòu)上的基本運(yùn)算 n順序表:n定義:是指用一組地址連續(xù)的存儲(chǔ)單元依次存儲(chǔ)線性表中的各個(gè)元素,使得線性表中在邏輯結(jié)構(gòu)上相鄰的數(shù)據(jù)元素存儲(chǔ)在相鄰的物理存儲(chǔ)單元中。n元素地址計(jì)算方法:nLoc(ai)=Loc(a1)+(i-1)*knLoc(ai+1)=Loc(ai)+ kn其中:nk一個(gè)元素占用的存儲(chǔ)單元個(gè)數(shù)nLoc(ai)線性表第i個(gè)元素的地址2.2.1 線性表的順序存儲(chǔ)

5、結(jié)構(gòu)n特點(diǎn):n實(shí)現(xiàn)邏輯上相鄰物理地址相鄰n實(shí)現(xiàn)隨機(jī)存取n實(shí)現(xiàn):可用C語言的一維數(shù)組實(shí)現(xiàn)a1a2an01n-112n內(nèi)存V數(shù)組下標(biāo)元素序號M-1typedef int DATATYPE; #define M 1000DATATYPE dataM;例 typedef struct card int num; char name20; char author10; char publisher30; float price;DATATYPE;DATATYPE libraryM; 備用空間數(shù)據(jù)元素不是簡單類型時(shí),可定義結(jié)構(gòu)體數(shù)組或動(dòng)態(tài)申請和釋放內(nèi)存DATATYPE *pData = (DATATYPE

6、 *)malloc(M*sizeof(DATATYPE);free(pData); . .loc(aloc(a1 1)+(maxlen-1)k )+(maxlen-1)k n n a an n loc(aloc(a1 1)+(n-1)k )+(n-1)k i ia ai i loc(aloc(a1 1)+(i-1)k )+(i-1)k 2 2a a2 2 Loc(aLoc(a1 1)+(2-1)k )+(2-1)k 1 1 a a1 1Loc(aLoc(a1 1) ) 邏輯地址邏輯地址 內(nèi)存空間狀態(tài)內(nèi)存空間狀態(tài) 存儲(chǔ)地址存儲(chǔ)地址 順序存儲(chǔ)結(jié)構(gòu)示意圖順序存儲(chǔ)結(jié)構(gòu)示意圖空閑空閑順序存儲(chǔ)結(jié)構(gòu)示意圖順

7、序存儲(chǔ)結(jié)構(gòu)的C語言定義#definemaxsize=線性表可能達(dá)到的最大長度;typedef struct ElemType elemmaxsize; /* 線性表占用的數(shù)組空間*/ int last; /*記錄線性表中最后一個(gè)元素在數(shù)組elem 中的位置(下標(biāo)值),空表置為-1*/ SeqList;注意區(qū)分元素的序號和數(shù)組的下標(biāo),如a1的序號為1,而其對應(yīng)的數(shù)組下標(biāo)為0。 2.2.2 線性表順序存儲(chǔ)結(jié)構(gòu)的基本運(yùn)算n線性表的基本運(yùn)算:1.查找操作 2.插入操作 3.刪除操作4.順序表合并算法n線性表順序存儲(chǔ)結(jié)構(gòu)的優(yōu)缺點(diǎn)分析1.查找操作線性表的兩種基本查找運(yùn)算u按序號查找按序號查找GetData

8、(L,i):要求查找線性表L中第i個(gè)數(shù)據(jù)元素,其結(jié)果是L.elemi-1或L-elemi-1。u按內(nèi)容查找按內(nèi)容查找Locate(L,e): : 要求查找線性表L中與給定值e相等的數(shù)據(jù)元素,其結(jié)果是:若在表L中找到與e相等的元素,則返回該元素在表中的序號;若找不到,則返回一個(gè)“空序號”,如-1。 線性表的查找運(yùn)算算法描述為:線性表的查找運(yùn)算 int Locate(SeqList L,ElemType e) i=0 ; /*i為掃描計(jì)數(shù)器,初值為0,即從第一個(gè)元素開始比較*/ while (i=L.last)&(L.elemi!=e) ) i+; /*順序掃描表,直到找到值為key的元素,或掃描

9、到表尾而沒找到*/ if (i=L.last) return(i); /*若找到值為e的元素,則返回其序號*/ else return(-1); /*若沒找到,則返回空序號*/2.插入操作 線性表的插入運(yùn)算是指在表的第i (1in+1)個(gè)位置,插入一個(gè)新元素e,使長度為n的線性表 (e1,ei-1,ei,en) 變成長度為n+1的線性表(e1,,ei-1,e e,ei,en)。 線性表的插入運(yùn)算算法插入算法示意圖已知:已知:線性表 (4,9,15,28,30,30,42,51,62),需在第4個(gè)元素之前插入一個(gè)元素“21”。則需要將第9個(gè)位置到第4個(gè)位置的元素依次后移一個(gè)位置,然后將“21”插

10、入到第4個(gè)位置,序號移動(dòng)元素插入元素1234567810949152830304251624915283030426251491521283030426251內(nèi)存a1a2aiai+1an01i-1V數(shù)組下標(biāo)n-1in12i元素序號i+1nn+1內(nèi)存a1a2aiai+1an01i-1V數(shù)組下標(biāo)n-1in12i元素序號i+1nn+1an-1x插入運(yùn)算int InsList(SeqList *L,int i,ElemType e) int k; if( (iL-last+2) ) /*首先判斷插入位置是否合法*/ printf(“插入位置i值不合法”);return(ERROR); if(L-las

11、t=maxsize-1) printf(“表已滿無法插入”); return(ERROR); for(k=L-last;k=i-1;k-) /*為插入元素而移動(dòng)位置*/ L-elemk+1=L-elemk; L-elemi-1=e; /*在C語言中數(shù)組第i個(gè)元素的下標(biāo)為i-1*/ L-last+; return(OK); 設(shè)Pi是在第i個(gè)元素之前插入一個(gè)元素的概率,則在長度為n的線性表中插入一個(gè)元素時(shí),所需移動(dòng)的元素次數(shù)的平均次數(shù)為:11)1(niiinPEis nOnTninnEisnPnii112)1(1111則若認(rèn)為插入運(yùn)算算法時(shí)間復(fù)雜度T(n)3.刪除操作線性表的刪除運(yùn)算是指將表的第i

12、(1in)個(gè)元素刪去,使長度為n的線性表 (e1,,ei-1,ei,ei+1,en),變成長度為n-1的線性表(e1,,ei-1, ei+1,en)。 算法思路示意 算法實(shí)現(xiàn)刪除算法示意將線性表(4,9,15,21,28,30,30,42,51,62)中的第5個(gè)元素刪除。 序號123456781094915212830304262514915213030425162刪除28后內(nèi)存a1a2aiai+1an01i-1V數(shù)組下標(biāo)n-1in12i元素序號i+1nn+1內(nèi)存a1a2ai+1V數(shù)組下標(biāo)01i-1n-2in-112i元素序號i+1n-1nanai+2刪除算法 int DelList(SeqL

13、ist *L,int i,ElemType *e)/*在順序表L中刪除第i個(gè)數(shù)據(jù)元素,并用指針參數(shù)e返回其值*/ int k; if(iL-last+1) printf(“刪除位置不合法!”); return(ERROR); *e= L-elemi-1; /* 將刪除的元素存放到e所指向的變量中*/ for(k=i;ilast;k+) L-elemk-1= L-elemk; /*將后面的元素依次前移*/ L-last-; return(OK); 設(shè)Qi是刪除第i個(gè)元素的概率,則在長度為n的線性表中刪除一個(gè)元素所需移動(dòng)的元素次數(shù)的平均次數(shù)為:niideinQE1)( nOnTninnEnQnid

14、ei121)(11則若認(rèn)為故在順序表中插入或刪除一個(gè)元素時(shí),平均移動(dòng)表的一半元素,當(dāng)n很大時(shí),效率很低。刪除運(yùn)算算法時(shí)間復(fù)雜度T(n)4.合并算法n已知 :有兩個(gè)順序表LA和LB,其元素均為非遞減有序排列,編寫一個(gè)算法,將它們合并成一個(gè)順序表LC,要求LC也是非遞減有序排列。 n算法思想算法思想 :設(shè)表LC是一個(gè)空表,為使LC也是非遞減有序排列,可設(shè)兩個(gè)指針i、j分別指向表LA和LB中的元素,若LA.elemiLB.elemj,則當(dāng)前先將LB.elemj插入到表LC中,若LA.elemiLB.elemj ,當(dāng)前先將LA.elemi插入到表LC中,如此進(jìn)行下去,直到其中一個(gè)表被掃描完畢,然后再將

15、未掃描完的表中剩余的所有元素放到表LC中。n算法實(shí)現(xiàn)順序表合并算法實(shí)現(xiàn)void merge(SeqList *LA, SeqList *LB, SeqList *LC) i=0;j=0;k=0; while(ilast&jlast) if(LA-elemielemj) LC-elemk= LA-elemi; i+; k+; else LC-elemk=LB-elemj; j+; k+; while(ilast)/*當(dāng)表LA長則將表LA余下的元素賦給表LC*/ LC-elemk= LA-elemi; i+; k+; while(jlast) /*當(dāng)表LB長則將表LB余下的元素賦給表LC*/ LC

16、-elemk= LB-elemj; j+; k+; LC-last=LA-last+LB-last; 順序存儲(chǔ)結(jié)構(gòu)的優(yōu)點(diǎn)和缺點(diǎn)優(yōu)點(diǎn):1.無需為表示結(jié)點(diǎn)間的邏輯關(guān)系而增加額外的存儲(chǔ)空間; 2.可方便地隨機(jī)存取表中的任一元素。 缺點(diǎn):1.插入或刪除運(yùn)算不方便,除表尾的位置外,在表的其它位置上進(jìn)行插入或刪除操作都必須移動(dòng)大量的結(jié)點(diǎn),其效率較低; 2.由于順序表要求占用連續(xù)的存儲(chǔ)空間,存儲(chǔ)分配只能預(yù)先進(jìn)行靜態(tài)分配。因此當(dāng)表長變化較大時(shí),難以確定合適的存儲(chǔ)規(guī)模。定義:采用鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)的線性表稱為鏈表 。特點(diǎn): 用一組任意的存儲(chǔ)單元存儲(chǔ)線性表的數(shù)據(jù)元素 利用指針實(shí)現(xiàn)了用不相鄰的存儲(chǔ)單元存放邏輯上相鄰的元素

17、 每個(gè)數(shù)據(jù)元素ai,除存儲(chǔ)本身信息外,還需存儲(chǔ)其直接后繼的信息數(shù)據(jù)域 指針域結(jié)點(diǎn)2.3 線性表的鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)結(jié)點(diǎn)(node) 數(shù)據(jù)域:元素本身信息指針域:指示直接后繼的存儲(chǔ)位置ZHAOQIANSUNLIZHOUWUZHENGWANGH例 線性表 (ZHAO,QIAN,SUN,LI,ZHOU,WU,ZHENG,WANG)43131NULL3771925數(shù)據(jù)域指針域LIQIANSUNWANGWUZHAOZHENGZHOU存儲(chǔ)地址1713192531374331H頭指針我們從兩個(gè)角度來討論鏈表:1.從實(shí)現(xiàn)角度看,鏈表可分為動(dòng)態(tài)鏈表和靜態(tài)鏈表;2.從鏈接方式的角度看,鏈表可分為單鏈表、循環(huán)鏈表和雙鏈表

18、。2.3.1 單鏈表 2.3.2 單鏈表上的基本運(yùn)算 2.3.3 循環(huán)鏈表 2.3.4 雙向鏈表 *2.3.5 靜態(tài)鏈表 2.3.6 順序表和鏈表的比較鏈表鏈表n單鏈表n定義:每個(gè)結(jié)點(diǎn)中只含一個(gè)指針域的鏈表,也叫線性鏈表。n單鏈表包括兩個(gè)域:數(shù)據(jù)域用來存儲(chǔ)結(jié)點(diǎn)的值;指針域用來存儲(chǔ)數(shù)據(jù)元素的直接后繼的地址(或位置)。n頭指針頭指針 :指向鏈表頭結(jié)點(diǎn)的指針。2.3.1 單鏈表單鏈表的示例圖頭指針H存儲(chǔ)地址數(shù)據(jù)域指針域1 D 437 B 1313 C 119 H NULL25 F 3731 A 737 G 1943 E 2531單鏈表的存儲(chǔ)結(jié)構(gòu)描述typedef struct node / * 結(jié)點(diǎn)

19、類型定義 * / elemtype data; struct node * next;node, *linklist; /* linklist為結(jié)構(gòu)指針類型*/ 生成一個(gè)linklist型新結(jié)點(diǎn):p=(linklist *)malloc(sizeof(node); 系統(tǒng)回收p結(jié)點(diǎn):free(p);單鏈表結(jié)點(diǎn)關(guān)系data nextdata nextdata next指針域數(shù)據(jù)域前驅(qū)后繼P-nextP P PP-pre(*p)表示p所指向的結(jié)點(diǎn)(*p).datap-data表示p指向結(jié)點(diǎn)的數(shù)據(jù)域(*p).nextp-next表示p指向結(jié)點(diǎn)的指針域帶頭結(jié)點(diǎn)的單鏈表示意圖有時(shí)為了操作的方便,還可以在單

20、鏈表的第一個(gè)結(jié)點(diǎn)之前附設(shè)一個(gè)頭結(jié)點(diǎn)。n帶頭結(jié)點(diǎn)的空單鏈表 n帶頭結(jié)點(diǎn)的單鏈表 Ha1a2Han 2.3.2 單鏈表上的基本運(yùn)算n線性表的基本運(yùn)算:1.建立單鏈表 2.單鏈表查找 3.單鏈表插入 4.單鏈表刪除 n算法應(yīng)用示例:1.求單鏈表的長度 2.求兩個(gè)集合的差 建立單鏈表n頭插法建表算法描述:算法描述:從一個(gè)空表開始,重復(fù)讀入數(shù)據(jù),生成新結(jié)點(diǎn),將讀入數(shù)據(jù)存放到新結(jié)點(diǎn)的數(shù)據(jù)域中,然后將新結(jié)點(diǎn)插入到當(dāng)前鏈表的表頭結(jié)點(diǎn)之后,直至讀入結(jié)束標(biāo)志為止。c1 sLL ci-1 c2 c1 ci sc1 建立單鏈表 c1 H S指向新申請的結(jié)點(diǎn)指向新申請的結(jié)點(diǎn)S-data=c1H-next=ss c1 H

21、 s頭插法建表 H c2s H-next=SH-next c1 頭插法建表 H c2s S -next =H-nextH-next c1 H-next=S H c2 c1 頭插法建表H c2c1 H cici-1c1 注:頭插法得到的單鏈表的邏輯順序與輸入元素順序相反,即為逆序建表。頭插法建表算法Linklist CreateFromHead() LinkList L; Node *s; int flag=1; /* 設(shè)置一個(gè)標(biāo)志,初值為1,當(dāng)輸入“$”時(shí),flag為0,建表結(jié)束*/ L=(Linklist)malloc(sizeof(Node);/*為頭結(jié)點(diǎn)分配存儲(chǔ)空間*/ L-next=N

22、ULL; while(flag) c=getchar(); if(c!=$) /*為讀入的字符分配存儲(chǔ)空間*/ s=(Node*)malloc(sizeof(Node); s-data=c; s-next=L-next; L-next=s; elseflag=0; 尾插法建表(建表及插入第一個(gè)結(jié)點(diǎn)) H r-next=S c1r r=SS指向新申請的結(jié)點(diǎn)指向新申請的結(jié)點(diǎn)S-data=c1s尾插法建表(插入第二個(gè)結(jié)點(diǎn)) H c2 r-next=S c1r r=Ss尾插法建表H c2c1r s注:尾插法得到的單鏈表的邏輯順序與輸入元素順序相同,即為順序建表。 H c1c2ci r s尾插法建表算法

23、Linklist CreateFromTail() /*將新增的字符追加到鏈表的末尾*/ LinkList L; Node *r, *s; int flag =1; L=(Node * )malloc(sizeof(Node);/*為頭結(jié)點(diǎn)分配存儲(chǔ)空間*/ L-next=NULL; r=L; /*r指針始終動(dòng)態(tài)指向鏈表的當(dāng)前表尾*/ while(flag)/*標(biāo)志,初值為1。輸入“$”時(shí)flag為0,建表結(jié)束*/ c=getchar(); if(c!=$) s=(Node*)malloc(sizeof(Node); s-data=c; r-next=s; r=s else flag=0; r-

24、next=NULL; 單鏈表查找n按序號查找 算法描述:算法描述:設(shè)帶頭結(jié)點(diǎn)的單鏈表的長度為n,要查找表中第i個(gè)結(jié)點(diǎn),則需要從單鏈表的頭指針L出發(fā),從頭結(jié)點(diǎn)(L-next)開始順著鏈域掃描,用指針p指向當(dāng)前掃描到的結(jié)點(diǎn),初值指向頭結(jié)點(diǎn)(pL-next),用j做記數(shù)器,累計(jì)當(dāng)前掃描過的結(jié)點(diǎn)數(shù)(初值為0),當(dāng)j = i 時(shí),指針p所指的結(jié)點(diǎn)就是要找的第i個(gè)結(jié)點(diǎn) 。算法實(shí)現(xiàn),算法演示。按序號查找算法實(shí)現(xiàn)/ * 在帶頭結(jié)點(diǎn)的單鏈表L中查找第i個(gè)結(jié)點(diǎn),若找到(1in),則返回該結(jié)點(diǎn)的存儲(chǔ)位置; 否則返回NULL * /Node * Get(LinkList L, int i) Node *p; p=L;

25、j=0; / * 從頭結(jié)點(diǎn)開始掃描 * / while (p-next!=NULL)&(jnext; j+; / * 掃描下一結(jié)點(diǎn) * / / * 已掃描結(jié)點(diǎn)計(jì)數(shù)器 * / if(i= =j)return p; / * 找到了第i個(gè)結(jié)點(diǎn) * / else return NULL; / * 找不到,i0或in * /n 按值查找算法描述:算法描述:按值查找是指在單鏈表中查找是否有結(jié)點(diǎn)值等于e的結(jié)點(diǎn),若有的話,則返回首次找到的其值為e的結(jié)點(diǎn)的存儲(chǔ)位置,否則返回NULL。查找過程從單鏈表的頭指針指向的頭結(jié)點(diǎn)出發(fā),順著鏈逐個(gè)將結(jié)點(diǎn)的值和給定值e作比較。算法實(shí)現(xiàn),算法演示。單鏈表查找按值查找算法實(shí)現(xiàn)/

26、* 在帶頭結(jié)點(diǎn)的單鏈表L中查找其結(jié)點(diǎn)值等于key的結(jié)點(diǎn),若找到則返回該結(jié)點(diǎn)的位置p,否則返回NULL * /Node *Locate( LinkList L,ElemType key) Node *p; p=L-next; / * 從表中第一個(gè)結(jié)點(diǎn)比較 * / while (p!=NULL) if (p-data!=key) p=p-next; else break; / * 找到結(jié)點(diǎn)key,退出循環(huán) * / return p;單鏈表插入操作n算法描述: 要在帶頭結(jié)點(diǎn)的單鏈表L中第i個(gè)數(shù)據(jù)元素之前插入一個(gè)數(shù)據(jù)元素e,需要首先在單鏈表中找到第i-1個(gè)結(jié)點(diǎn)并由指針pre指示,然后申請一個(gè)新的結(jié)點(diǎn)并

27、由指針s指示,其數(shù)據(jù)域的值為e,并修改第i-1個(gè)結(jié)點(diǎn)的指針使其指向s,然后使s結(jié)點(diǎn)的指針域指向第i個(gè)結(jié)點(diǎn)。esa1an ai-1aiespreLa1an preai-1ai單鏈表插入 H a1aian sai-1 epre與ai鏈接S-next=pre-next ai-1與ai斷鏈插入epre-next=s單鏈表插入操作算法實(shí)現(xiàn)void InsList(LinkList L,int i,ElemType e) /*在帶頭結(jié)點(diǎn)的單鏈表L中第i個(gè)結(jié)點(diǎn)之前插入值為e的新結(jié)點(diǎn)。 */ Node *pre,*s; pre=L; int k=0; while(pre!=NULL&knext;k=k+1;

28、if(k!=i-1) printf(“插入位置不合理!”); return; s=(Node*)malloc(sizeof(Node); /*為e申請一個(gè)新的結(jié)點(diǎn)*/ s-data=e; /*將待插入結(jié)點(diǎn)的值e賦給s的數(shù)據(jù)域*/ s-next=pre-next; pre-next=s; 單鏈表最后一個(gè)元素怎么查找? H a1aian ai-1preWhile( ? ) pre=pre-next; pre!=null插入位置1im+1單鏈表刪除n算法描述:欲在帶頭結(jié)點(diǎn)的單鏈表L中刪除第i個(gè)結(jié)點(diǎn),則首先要通過計(jì)數(shù)方式找到第i-1個(gè)結(jié)點(diǎn)并使p指向第i-1個(gè)結(jié)點(diǎn),而后刪除第i個(gè)結(jié)點(diǎn)并釋放結(jié)點(diǎn)空間。 p

29、a1ai-1aian pa1Lan ai-1aiai+1rL單鏈表刪除 H ai+1aian rai-1p r=p-next p-next= p-next-next free(r)這個(gè)節(jié)點(diǎn)用指針p怎么表示?p-next-next單鏈表刪除 H an-1aian ai-1pWhile( ? ) pre=pre-next; P- next!=null刪除位置1impp單鏈表刪除算法實(shí)現(xiàn)void DelList(LinkList L,int i,ElemType *e)/*在帶頭結(jié)點(diǎn)的單鏈表L中刪除第i個(gè)元素,并保存其值到變量*e中*/ Node *p,*r; p=L; int k =0;while

30、(p-next!=NULL&knext; k=k+1; if(k!=i-1) /* 即while循環(huán)是因?yàn)閜-next=NULL而跳出的*/ printf(“刪除結(jié)點(diǎn)的位置i不合理!”); return ERROR; r=p-next; p-next=p-next-next /*刪除結(jié)點(diǎn)r*/free(r); /*釋放被刪除的結(jié)點(diǎn)所占的內(nèi)存空間*/求單鏈表的長度算法描述:算法描述:可以采用“數(shù)”結(jié)點(diǎn)的方法來求出單鏈表的長度,用指針p依次指向各個(gè)結(jié)點(diǎn),從第一個(gè)元素開始“數(shù)”,一直“數(shù)”到最后一個(gè)結(jié)點(diǎn)(p-next=NULL)。intListLength(LinkList L) /*L為帶頭結(jié)點(diǎn)的

31、單鏈表*/ Node *p; p=L-next; j=0; /*用來存放單鏈表的長度*/ while(p!=NULL) p=p-next; j +; return j; 求兩個(gè)集合的差n已知:已知:以單鏈表表示集合,假設(shè)集合A用單鏈表LA表示,集合B用單鏈表LB表示,設(shè)計(jì)算法求兩個(gè)集合的差,即A-B。n算法思想:算法思想:由集合運(yùn)算的規(guī)則可知,集合的差A(yù)-B中包含所有屬于集合A而不屬于集合B的元素。具體做法是,對于集合A中的每個(gè)元素e,在集合B的鏈表LB中進(jìn)行查找,若存在與e相同的元素,則從LA中將其刪除。n算法實(shí)現(xiàn)n算法演示鏈接求兩個(gè)集合的差算法實(shí)現(xiàn)void Difference (Link

32、List LA,LinkList LB) /*此算法求兩個(gè)集合的差集*/ Node *pre;*p, *r; pre=LA; p=LA-next; /*p向表中的某一結(jié)點(diǎn),pre始終指向p的前驅(qū)*/ while(p!=NULL) q=LB-next; /*掃描LB中的結(jié)點(diǎn),尋找與LA中*P結(jié)點(diǎn)相同的結(jié)點(diǎn)*/ while (q!=NULL&q-data!=p-data) q=q-next; if (q!=NULL) r=p; pre-next=p-next; p=p-next; free(r); else pre=p; p=p-next; 2.3.3 循環(huán)鏈表循環(huán)鏈表循環(huán)鏈表(Circular

33、Linked List) 是一個(gè)首尾相接的鏈表。 特點(diǎn)特點(diǎn):將單鏈表最后一個(gè)結(jié)點(diǎn)的指針域由NULL改為指向頭結(jié)點(diǎn)或線性表中的第一個(gè)結(jié)點(diǎn),就得到了單鏈形式的循環(huán)鏈表,并稱為循環(huán)單鏈表。在循環(huán)單鏈表中,表中所有結(jié)點(diǎn)被鏈在一個(gè)環(huán)上。 帶頭結(jié)點(diǎn)循環(huán)單鏈表示意圖。循環(huán)鏈表 L aianai-1帶頭結(jié)點(diǎn)的循環(huán)單鏈表示意圖 L(a) 空鏈表 a1ai-1aian L(b)帶頭結(jié)點(diǎn)的循環(huán)單鏈表的一般形式 帶頭結(jié)點(diǎn)的循環(huán)單鏈表示意圖a1ai-1aian *(rear-next)*rear(c)采用尾指針的循環(huán)單鏈表尾指針的循環(huán)單鏈表的一般形式 rear循環(huán)單鏈表合并為一個(gè)循環(huán)單鏈表已知已知:有兩個(gè)帶頭結(jié)點(diǎn)的循環(huán)

34、單鏈表LA、LB,編寫一個(gè)算法,將兩個(gè)循環(huán)單鏈表合并為一個(gè)循環(huán)單鏈表,其頭指針為LA。算法思想算法思想:先找到兩個(gè)鏈表的尾,并分別由指針p、q指向它們,然后將第一個(gè)鏈表的尾與第二個(gè)表的第一個(gè)結(jié)點(diǎn)鏈接起來,并修改第二個(gè)表的尾Q,使它的鏈域指向第一個(gè)表的頭結(jié)點(diǎn)。循環(huán)單鏈表合并為一個(gè)循環(huán)單鏈表a1ai-1aian b1bi-1bibn pqLALB循環(huán)單鏈表合并算法實(shí)現(xiàn)LinkList merge_1(LinkList LA,LinkList LB)/*此算法將兩個(gè)鏈表的首尾連接起來*/ Node *p, *q; p=LA; q=LB; while (p-next!=LA) p=p-next;/*找

35、到表LA的表尾*/ while (q-next!=LB) q=q-next;/*找到表LB的表尾*/ q-next=LA;/*修改表LB 的尾指針,使之指向表LA 的頭結(jié)點(diǎn)*/ p-next=LB-next;/*修改表LA的尾指針,使之指向表LB 中的第一個(gè)結(jié)點(diǎn)*/free(LB); return(LA);2.3.4 雙向鏈表 雙向鏈表:雙向鏈表:在單鏈表的每個(gè)結(jié)點(diǎn)里再增加一個(gè)指向其前趨的指針域prior。這樣形成的鏈表中就有兩條方向不同的鏈,我們稱之為雙雙 ( 向向) 鏈表鏈表 (Double Linked List)。雙向鏈表的結(jié)構(gòu)定義:typedef struct Dnode ElemT

36、ype data; struct DNode *prior,*next; DNode,* DoubleList;雙鏈表的結(jié)構(gòu)定義n雙鏈表的結(jié)點(diǎn)結(jié)構(gòu) 后繼指針域prior data next前驅(qū)指針域數(shù)據(jù)域雙向循環(huán)鏈表示意圖 a1 a2 a3LL空的雙向循環(huán)鏈表 非空的雙向循環(huán)鏈表 雙向鏈表的前插操作n算法描述:欲在雙向鏈表第i個(gè)結(jié)點(diǎn)之前插入一個(gè)的新的結(jié)點(diǎn),則指針的變化情況如圖所示。 es bp a p-priors-prior = p-priorp-prior -next = ss -next = pp-prior = s雙向鏈表的前插操作算法實(shí)現(xiàn)void DlinkIns(DoubleLis

37、t L,int i,ElemType e) DNode *s,*p; /*首先檢查待插入的位置i是否合法*/ /*若位置i合法,則讓指針p指向它*/ s=(DNode*)malloc(sizeof(DNode); if (s) s-data=e; s-prior=p-prior; p-prior-next=s; s-next=p; p-prior=s; return TRUE; else return FALSE; 雙向鏈表的刪除操作n算法描述:欲刪除雙向鏈表中的第i個(gè)結(jié)點(diǎn),則指針的變化情況如圖所示。 a b cp c a p-prior-next = p next p- next -prio

38、r = p prior p nextp priorp prior-nextp next-prior雙向鏈表的刪除操作算法實(shí)現(xiàn)intDlinkDel(DoubleList L,int i,ElemType *e)DNode *p; /*首先檢查待插入的位置i是否合法*/ /*若位置i合法,則讓指針p指向它*/ *e=p-data; p-prior-next=p-next; p-next-prior=p-prior; free(p); return TRUE; 雙向鏈表應(yīng)用舉例已知已知:設(shè)一個(gè)循環(huán)雙鏈表L=(a,b,c,d)編寫一個(gè)算法將鏈表轉(zhuǎn)換為L=(b,a,c,d)。算法思想:算法思想:實(shí)際上

39、是交換表中前兩個(gè)元素的次序。算法實(shí)現(xiàn)算法實(shí)現(xiàn):voidswap(DLinkList L) DNode * p,*q,*h; h=L-next; /* h指向表中的第一個(gè)結(jié)點(diǎn),即a */ p=h-next; /* p指向b結(jié)點(diǎn) */ q=h-prior; /* 保存a 結(jié)點(diǎn)的前驅(qū) */ h-next=p-next; p-next-prior=h; /*變換指針指向*/ p-prior=q; p-next=h; L-next=p; h-prior=p; *2.3.5 靜態(tài)鏈表靜態(tài)鏈表n基本概念:游標(biāo)實(shí)現(xiàn)鏈表的方法游標(biāo)實(shí)現(xiàn)鏈表的方法:定義一個(gè)較大的結(jié)構(gòu)數(shù)組作為備用結(jié)點(diǎn)空間(即存儲(chǔ)池)。當(dāng)申請結(jié)點(diǎn)時(shí),

40、每個(gè)結(jié)點(diǎn)應(yīng)含有兩個(gè)域:data域和next域。data域存放結(jié)點(diǎn)的數(shù)據(jù)信息,next域?yàn)橛螛?biāo)指示器,指示后繼結(jié)點(diǎn)在結(jié)構(gòu)數(shù)組中的相對位置(即數(shù)組下標(biāo))。數(shù)組的第0個(gè)分量可以設(shè)計(jì)成表的頭結(jié)點(diǎn),頭結(jié)點(diǎn)的next域指示了表中第一個(gè)結(jié)點(diǎn)的位置,為0表示靜態(tài)單鏈表的結(jié)束。我們把這種用游標(biāo)指示器實(shí)現(xiàn)的單鏈表叫做靜態(tài)單鏈表靜態(tài)單鏈表(Static Linked List)。靜態(tài)鏈表的結(jié)構(gòu)定義,靜態(tài)鏈表的插入和刪除操作示例。 n基本操作:初始化、分配結(jié)點(diǎn)與結(jié)點(diǎn)回收、前插操作、刪除。 靜態(tài)鏈表的結(jié)構(gòu)定義#define Maxsize= 鏈表可能達(dá)到的最大長度typedef struct ElemType data

41、; int cursor; Component, StaticListMaxsize; 靜態(tài)鏈表的插入和刪除操作示例已知已知:線性表 a,b,c,d,f,g,h,i),Maxsize=11 0123456789100123456789101a 2b 3c 4d 9f 6g 8h 8i 0e 51a 2b 3c 4d 9f 6g 7h 8i 0e 51a 2b 3c 4d 5f 6g 7h 8i 0012345678910(a)初始化(b)插入e后 (c)刪除h后 靜態(tài)鏈表初始化算法描述算法描述:初始化操作是指將這個(gè)靜態(tài)單鏈表初始化為一個(gè)備用靜態(tài)單鏈表。設(shè)space為靜態(tài)單鏈表的名字,av為備用

42、單鏈表的頭指針,其算法如下:void initial(StaticList space,int *av) int k; space0-cursor=0;/*設(shè)置靜態(tài)單鏈表的頭指針指向位置0*/ for(k=0;kcursor=k+1; /*連鏈*/ spaceMaxsize-1=0; /*標(biāo)記鏈尾*/ *av=1; /*設(shè)置備用鏈表頭指針初值*/ 靜態(tài)鏈表分配結(jié)點(diǎn)與結(jié)點(diǎn)回收n分配結(jié)點(diǎn)分配結(jié)點(diǎn)int getnode(int *av)/*從備用鏈表摘下一個(gè)結(jié)點(diǎn)空間,分配給待插入靜態(tài)鏈表中的元素*/ int i=*av; *av=space*av.cur; return i; n結(jié)點(diǎn)回收結(jié)點(diǎn)回收 v

43、oid freenode(int *av,int k) /*將下標(biāo)為 k的空閑結(jié)點(diǎn)插入到備用鏈表*/ spacek.cursor=*av; *av=k; 靜態(tài)鏈表前插操作算法描述算法描述:1、先從備用單鏈表上取一個(gè)可用的結(jié)點(diǎn);2、將其插入到已用靜態(tài)單鏈表第i個(gè)元素之前。void insbefore(StaticList space,int i,int *av) j=*av ;/*j為從備用表中取到的可用結(jié)點(diǎn)空間的下標(biāo)*/ av=spaceav-cursor;/*修改備用表的頭指針*/ spacej-data=x; k=space0-cursor;/*k為已用靜態(tài)單鏈表的第一個(gè)元素的下標(biāo)值*/

44、for(m=1;mcursor; spacej-cursor=spacek-cursor; /*修改游標(biāo)域*/ spacek-cursor=j; 靜態(tài)鏈表刪除算法描述:算法描述:首先尋找第i -1個(gè)元素的位置,之后通過修改相應(yīng)的游標(biāo)域進(jìn)行刪除;在將被刪除的結(jié)點(diǎn)空間鏈到可用靜態(tài)單鏈表中,實(shí)現(xiàn)回收。void delete(StaticList space;int i;int *av ) k=space0-cursor; for(m=1,mcursor ; j=spacek-cursor ; spacek-cursor=spacej-cursor;/*從刪除第i個(gè)元素*/ spacej-cursor

45、=*av;/*將第i 個(gè)元素占據(jù)的空間回收*/ av=j ; /*置備用表頭指針以新值*/2.3.6 順序表和鏈表的比較順序表和鏈表的比較 1基于空間的考慮 2基于時(shí)間的考慮 l 順序表的特點(diǎn)是邏輯位置相鄰的數(shù)據(jù)元素其物理位順序表的特點(diǎn)是邏輯位置相鄰的數(shù)據(jù)元素其物理位置也相鄰,因此可以進(jìn)行隨機(jī)存儲(chǔ),是一種隨機(jī)存儲(chǔ)置也相鄰,因此可以進(jìn)行隨機(jī)存儲(chǔ),是一種隨機(jī)存儲(chǔ)結(jié)構(gòu)。其插入和刪除操作的時(shí)間復(fù)雜度均為結(jié)構(gòu)。其插入和刪除操作的時(shí)間復(fù)雜度均為O(n)。l 鏈表中的數(shù)據(jù)元素使用一組任意的存儲(chǔ)單元存儲(chǔ),鏈表中的數(shù)據(jù)元素使用一組任意的存儲(chǔ)單元存儲(chǔ),不要求邏輯位置相鄰的數(shù)據(jù)元素物理位置也相鄰,而不要求邏輯位置相

46、鄰的數(shù)據(jù)元素物理位置也相鄰,而是采用附加的指針表示元素之間的邏輯關(guān)系。鏈表的是采用附加的指針表示元素之間的邏輯關(guān)系。鏈表的插入和刪除結(jié)點(diǎn)均不需要移動(dòng)其他結(jié)點(diǎn),但是,其查插入和刪除結(jié)點(diǎn)均不需要移動(dòng)其他結(jié)點(diǎn),但是,其查找運(yùn)算必須從頭指針開始順序查找,其時(shí)間復(fù)雜度為找運(yùn)算必須從頭指針開始順序查找,其時(shí)間復(fù)雜度為O(n)。2.4 一元多項(xiàng)式的表示及相加 一個(gè)一元多項(xiàng)式Pn(x)可按升冪的形式寫成:Pn(x)=p0+p1x+p2x2+p3x3+ +pnxn 在計(jì)算機(jī)內(nèi),可以用一個(gè)線性表P來表示: P=(p0,p1,p2, ,pn) 用單鏈表存儲(chǔ)多項(xiàng)式的結(jié)點(diǎn)結(jié)構(gòu)如下: typedef struct Pol

47、ynode int coef; int exp; Polynode *next; Polynode , * Polylist; coefexpnext建立多項(xiàng)式鏈表l算法描述算法描述:輸入多項(xiàng)式的系數(shù)和指數(shù),用尾插法建立一元多項(xiàng)式的鏈表。Polylist polycreate() Polynode *head, *rear, *s; int c,e; rear=head =(Polynode *)malloc(sizeof(Polynode); /*建立多項(xiàng)式的頭結(jié)點(diǎn), rear 始終指向單鏈表的尾*/ scanf(“%d,%d”,&c,&e);/*鍵入多項(xiàng)式的系數(shù)和指數(shù)項(xiàng)*/ while(c

48、!=0)/*若c=0,則代表多項(xiàng)式的輸入結(jié)束*/ s=(Polynode*)malloc(sizeof(Polynode);/*申請新的結(jié)點(diǎn)*/ s-coef=c ; s-exp=e ;rear-next=s ;/*在當(dāng)前表尾做插入*/ rear=s; scanf(“%d,%d”,&c,&e); rear-next=NULL;/*將表的最后一個(gè)結(jié)點(diǎn)的next置NULL,以示表結(jié)束*/ return(head);多項(xiàng)式的單鏈表表示示意圖說明:圖示分別為多項(xiàng)式A(x)=7+3x+9x8+5x17B(x)=8x+22x7-9x8 -17 03 15 17 9 88 1 -122 7 -9 8 設(shè)p,

49、q分別指向A,B中某一結(jié)點(diǎn),p,q初值是第一結(jié)點(diǎn)比較p-exp與q-expp-exp exp: p結(jié)點(diǎn)是和多項(xiàng)式中的一項(xiàng) p后移,q不動(dòng)p-exp q-exp: q結(jié)點(diǎn)是和多項(xiàng)式中的一項(xiàng) 將q插在p之前,q后移,p不動(dòng)p-exp = q-exp: 系數(shù)相加0:從A表中刪去p, 釋放p,q,p,q后移0:修改p系數(shù)域, 釋放q,p,q后移直到p或q為NULL 若q=NULL,結(jié)束 若p=NULL,將B中剩余部分連到A上即可n運(yùn)算規(guī)則兩個(gè)多項(xiàng)式中所有指數(shù)相同的項(xiàng)的對應(yīng)系數(shù)相加,若和不為零,則構(gòu)成“和多項(xiàng)式”中的一項(xiàng);所有指數(shù)不相同的項(xiàng)均復(fù)抄到“和多項(xiàng)式”中。兩個(gè)多項(xiàng)式相加兩個(gè)多項(xiàng)式相加算法實(shí)現(xiàn)vo

50、id polyadd(Polylist polya;Polylist polyb) /* p和q分別指向polya和polyb鏈表中的當(dāng)前計(jì)算結(jié)點(diǎn)*/ /* pre指向和多項(xiàng)式鏈表中的尾結(jié)點(diǎn)*/ while p!=NULL & q!=NULL) if (p-expexp) /*將p結(jié)點(diǎn)加入到和多項(xiàng)式中*/ else if ( p-exp= =q-exp) /*若指數(shù)相等,則相應(yīng)的系數(shù)相加。若系數(shù)為0則刪除p,q節(jié)點(diǎn)*/ else /*將q結(jié)點(diǎn)加入到和多項(xiàng)式中*/ ./*將多項(xiàng)式polya或polyb中剩余的結(jié)點(diǎn)加入到和多項(xiàng)式中*/q-1pa7 0 3 1 9 8 5 17 -1pb8 1 22

51、 7 -9 8 ppreq-1pa7 0 3 1 9 8 5 17 -1pb8 1 22 7 -9 8 ppreq-1pa7 0 11 1 9 8 5 17 -1pb8 1 22 7 -9 8 ppre q-1pa7 0 11 1 9 8 5 17 -1pb8 1 22 7 -9 8 ppreq=NULL-1pa7 0 11 1 9 8 5 17 -1pb8 1 22 7 -9 8 ppreq=NULL-1pa7 0 11 1 9 8 5 17 -1pb8 1 22 7 -9 8 ppre-1pa7 0 11 1 22 7 5 17 復(fù)習(xí)1、順序表的插入2、順序表的刪除3、單鏈表的插入4、單鏈表的刪除5、循環(huán)鏈表的合并6、雙向鏈表的插入7、雙向鏈表的刪除 . .loc(aloc(a1 1)+(maxlen-1)k )+(maxlen-1)k n n a an n loc(aloc(a1 1)+(n-1)k )+(n-1)

溫馨提示

  • 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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論