日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

第2章线性表的基本使用及其cpp示例(第二章汇总,线性表都在这里)

發(fā)布時間:2025/3/8 编程问答 13 豆豆
生活随笔 收集整理的這篇文章主要介紹了 第2章线性表的基本使用及其cpp示例(第二章汇总,线性表都在这里) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

2.1線性表的定義和特點

【類型定義:
*是n個元素的有限序列
*除了第一個元素沒有直接前驅(qū)和最后一個沒有直接后驅(qū)之外,其余的每個元素只有一個直接前驅(qū)和直接后驅(qū);
(a1,a2…an)

【特征:
*有窮性:由有限個元素組成,元素個數(shù)表長度 n=0空表
(a1,a2…an),稱下標i為線性表的位序

*有序性: 線性表元素之間存在嚴格次序關(guān)系(序偶關(guān)系)

*同一性:線性表屬于同類數(shù)據(jù)元素組成,每一個元素都屬于同一數(shù)據(jù)對象
eg:(A,12,b)不是線性表,不遵守同一性

2.1.2線性表抽象數(shù)據(jù)類型定義

ADT List{

//數(shù)據(jù)對象
D={ai|ai∈ElemSet,i=1,2…n, n>0}

//數(shù)據(jù)關(guān)系
R1={<ai-1,ai>|ai-1,ai∈D,i=2,…n}

//基本操作
1)InitList(&L)
將:初數(shù)化為空表
2)

}ADT list

【引用在什么情況下使用】

所用到的元素,哪個元素變化(帶入數(shù)據(jù)或者 ),就在此元素前加 &
【eg】
1)InitList(&L)
將:初數(shù)化為空表
//表L初始化帶入值,發(fā)生變化,故早L前加&

2.1.5 示例 *有序集合的合并

有序表:LA和LB,求合并遞減有序LC

基本思路:
{若ai<=bi,則ci=bi
{
{若bi<ai,則ci=ai
//誰小就先吧他賦給c

算法時間復雜度:O(ListLength(LA))+O(ListLength(LB))

2.2.1線性表的順序表示和實現(xiàn)------順序映像

【順序存儲】在【查找時】的時間復雜度為【O(1)】,因為它的地址是連續(xù)的,只要知道首元素的地址,根據(jù)下標可以很快找到指定位置的元素
【插入和刪除】操作由于可能要在插入前或刪除后對元素進行移動,所以順序存儲的時間復雜度為【O(n)】。

1)初始化操作
思想:構(gòu)造一個空表
設(shè)置表起始位置、表長及可用空間

#define LIST_INIT_SIZE 100 #define LISTINCREAMENT 10 typedef struct { ElemType *elem; //定義個地址變量,使其后面能指向線性表占用的數(shù)組空間 int length; // 線性表的長度 int listsize; // 當前分配的存儲容量 }SqList;//初始化操作 Status InitList_Sq(SqList &L) //初始化 { //構(gòu)造一個空表 L.elem=(ElemType)malloc(LIST_INIT_SIZE*size of(ElemType)); if(!L.elem) exit(OVERFLOW); //存儲分配失敗 L.length=0; //空表長度為0 L.listsize=LIST_INIT_SIZE; //初始存儲容量 return OK;}

2.2.3順序表的插入

2)順序插入操作

目的:在線性表L第i個元素前插入一個元素e

【基本思想
1)判斷i是否在允許范圍
2)存儲空間是否已滿
3)將第i個元素和后面的所有元素向后移動
4)新元素寫在空出的第i個位置
5)線性表長度加1

【注意】
長度為n的順序表第i個位置插入移動n-i+1個元素

Status ListInsert_Sq(SqList&L,int i,ElemType e){if(i<1||i>1.lenth+1) return ERROR; //插入位置不合法if(L.length>=L.listsize) { newbase=(ElemType*)realloc(L.elem,(LIST_INIT_SIZE+LISTINCREMENT)*sizeof(ElemType)); If(!newbase) exit(OVERFLOW);// 當前存儲空間已滿L.elem=newbase; //新基址L.listsize+=LISTINCREMENT; // 增加存儲容量 } //判斷空間足夠q=&(L.elem[i-1]); //q指向插入位置for(p=&(L.elem[L.elem-1]);p>-q;--q) *(p+1)=*p; *q=e; ++L.length; return OK; }

2.2.4順序表的刪除和插入

【基本思路
1)判斷i是否在允許范圍
2)將線性表的第i個元素給e
3)將第i個元素和后面的所有元素向前移動一個位置
4)線性表長度減1

Status ListDelete_Sq(SqList&L,int i,ElemType e){//刪除第i個元素并用e返回值if(i<1||i>1.lenth+1) return ERROR; //刪除位置不合法p=&(L.elem[i-1]); //q指向插入位置 e=*p; q=L.elem+L.length-1; //表尾元素位置 for(++p;p<=q;++p) *(p-1)=*p; //p-1指向p--L.length; return OK; }

【圖】:平均移動次數(shù)

【查找操作】11:42

int LocateElem_Sq(SqList,ElseType e) { //查詢第一個 滿足條件的元素,若存在,返回位序,否則返回0; int i; i=1; while (i<=L.length&&L.elem[i-1]!=e) ++i; if(i<=L.length) return i; else return 0; }// locateElem_Sqi<=L.length&&L.elem[i-1]!=e i>L.length

【順序結(jié)構(gòu)優(yōu)缺點14:15
【優(yōu)點:
邏輯相鄰,物理相鄰
可隨機存取一元素
存儲空間使用緊湊
【缺點:
插入,刪除需要移動大量元素
預(yù)先分配空間需按最大空間分配,利用不充分表難以擴充

【】線性表的合并問題
【圖:例1】
基本思路:
1)初始化Lc為空表
2)分別從La和Lb取得當前元素ai和bi
3)若ai<bj,則將ai插入到Lc中,否則
bj插入到Lc中

代碼:

Viod MergeList(SqList La.SqList ,lb.SqList &Lc) { Pa=La.elem; Pb=Lb.elem; Lc.listsize=Lc.length=La.elem+Lb.elem; Pc=Lc.elem=(ElemType*)malloc(Lc.listsize* sizeof(ElemType)); if(!Lc.elem) exit(overflow); Pa_last=La.elem+La.length-1; Pb_last=Lb.elem+Lb.length-1; while(pa<=pa_last&&pb<=pb_last) { if(*pa<= *pb) *pc++= *pa++; else *pc++= *pb++; } while(pa<=pa_last) *pc++= *pa++; while (pb<=pb_last) *pc++= *pb++; }

2.3線性表的鏈式表現(xiàn)與實現(xiàn)

2.3.1.1單鏈表
【特點:
*用一組任意的存儲單元存儲線性表的數(shù)據(jù)元素
*利用指針實現(xiàn)用不同相鄰的存儲單元存放邏輯上相鄰的元素
*每個元素ai,除存儲本身信息外,還存儲其直接后繼的元素(后一個元素的地址)
*結(jié)點:數(shù)據(jù)元素ai的存儲映像
{數(shù)據(jù)域:數(shù)據(jù)元素本身
指針域:指示直接后繼的存儲位置

【頭指針、頭結(jié)點、第一個元素結(jié)點
*頭指針:以線性表的第一個數(shù)據(jù)元素a1的存數(shù)地址作為線性表的地址,稱為線性表的頭指針

*頭結(jié)點:為了操作方便,在第一個結(jié)點前虛加一個“頭結(jié)點”,指向頭結(jié)點的指針為鏈表的頭指針(相當于第一個呀元素的結(jié)點)

代碼:

typedef struct LNode{ElemType data;struct LNode*next; }LNode,*LinkList //LNode是結(jié)構(gòu)體的別名,LinkList為指針變量 //相當于:typedef LNode *LinkList

2.3.1.2 單鏈表存儲結(jié)構(gòu)實現(xiàn)

格式: data | next

【p指向數(shù)據(jù)域
(*p).data=10;
或:p->data=10; //表示p指向結(jié)點的數(shù)據(jù)域

(*p).next=10
或 p->next //表示p指向結(jié)點的指針域

*生成一個LNode型新結(jié)點:
p=(LinkList)malloc(sizeof(LNode));

*系統(tǒng)回收p的結(jié)點
free(p)

*單鏈表特點:
1)是它是一種動態(tài)結(jié)構(gòu),整個存儲空間為多個鏈表共用
2)不需預(yù)先分配空間
3)指針占用額外存儲空間
4)不能隨機存取,查找速度慢

【基本操作:
1)GetElem(L,i,&e) //第i個元素用e帶回結(jié)果
2)ListInsert(&L,i,e) //插入
3)ListDelete(&L,i,e) //刪除
4)CreateList_L(&L,n) //創(chuàng)建線性表

2.3.1.3單鏈表的查找

【操作:
1)GetElem(L,i,&e)

【基本思想:
1)令p為指針變量,首先指向第一個結(jié)點,變量 j為計數(shù)器
2)依次向后查找,循環(huán)結(jié)束條件:p為空或j>=i;
3)找到用e返回第i個值

【代碼:

Status GetElem_L(LinkList L,int i,ElemType&e) { //L是鏈表的頭指針(對帶頭結(jié)點的鏈表),以e返回dii個值 p=L->next; j=1;while (p&&j<i) {p=p->next; ++j;if(!p||j>i)return ERROR;e=p->data; //取第i個值 return OK; }

2.3.1.4單鏈表的插入操作

2)ListInsert(&L,i,e)
在線性表第i個元素之前插入一個元素e,元素e存在結(jié)點s中

【思路:在第i項的前加一個接結(jié)點,i-1項的地址域和e的數(shù)據(jù)域連接

int ListInsert_L(LinkList&L,int i,int e) { LNode*p,*s;int j; //或:LinkList p,s; 等同 p=L;j=0; //計數(shù)器 while(p&&j<i-1) {p=p->next;++j;} if(!p||j>i-1) return ERROR; s=LinkList()malloc(sizeof(LNode)); //新結(jié)點 s->data=e; s->next=p->next; p->next=s; return OK; }

2.3.1.5 單鏈表的刪除

【思路:刪除第i個元素,并保存到元素e中

【代碼:

int ListDelete_L(LinkList&L,int i,ElemType&e) { LNode*p,*q;int j; p=L;j=0; while(p->next||j<i-1) //????我覺得應(yīng)該是(!p||j>i-1) {p=p->next;++j} if(p->next==NULL||j>i-1) return ERROR; //刪除位置不合理 q=p->next; //q指向被刪除結(jié)點 p->next=q->next; // e=q->data; //取出第i個結(jié)點的數(shù)據(jù)域 free(q); // 釋放dii個結(jié)點的內(nèi)存 return OK; }

2.3.1.6單鏈表的建立

【頭插法建立有頭結(jié)點的單鏈表
可理解為:每次插一個新的頭
【圖】
L=(Linklist)malloc(sizeof(LNode)) //sizeof后面跟數(shù)據(jù)類型(LNode)
L->next=NULL

【圖】
p=(LinkList)malloc(sizeof(LNode))
scanf("%f",&(p->data)); //

【整個代碼:

void CreateList_L(LinkList &L,int n) { LNode*p;int i; L=(LinkList)malloc(sizeof(Lnode)); L->next=NULL; for(i=n;i>0;--i) { p=(Listlink)malloc(sizeof(LNode)); scanf("%d",&p->data); p->next=L->next; l->next=p //這里的=都可以理解為“給了,到,指向” } }

2.3.1.7有序單鏈表的合并

例:線性表LA和LB中數(shù)據(jù)元素按照廢帝劍有序排列,將LA和LB合并為一個新的LC,且LC中的數(shù)據(jù)元素仍按照遞減有序排列


【代碼:

void MergeList_L(LinkList&La,LinkList&Lb,LinkList&Lc) {// 歸并La和Lb得到Lc,Lc也按照降序排列 LinkList pa,pb,pc; pa=La->next;pb=Lb->next; Lc=pc=La; //用La的頭結(jié)點作為Lc的頭結(jié)點 while(pa&&pb) { if(pa->data<=pb->data) { pc->next=pa; pc=pa;pa=pa->next; } else { pc->next=pb;pc=pb;pb=pb->next; } pc->next=pa?pa:pb; //若a不為空則指向pa,否則指向pb free(Lb); }

2.3.1.8靜態(tài)鏈表

定義:用數(shù)組描述的鏈表叫靜態(tài)鏈表

目的:為在不設(shè)指針類型的高級程序語言中使用鏈表結(jié)構(gòu)

存儲結(jié)構(gòu):

#define MAXSIZE 100 //靜態(tài)鏈表最大長度 typedef struct{ ElemType data; int cur; //游標,代替指針的結(jié)點,表示數(shù)組中的位置 }component,SLinkList[MAXSIZE]

2.3.2循環(huán)鏈表

循環(huán)鏈表是單鏈表的變形

循環(huán)鏈表最后一個結(jié)點link指針部位NULL,而是指向表的前端

為簡化操作,在循環(huán)鏈表往往插入頭結(jié)點

特點:
只要知道表中一結(jié)點的地址,就可以搜索到所有其他結(jié)點的地址

操作的時間復雜度:
表尾插入,時間復雜度:O(1)
表尾刪除:O(n)
表頭插入,同表尾
表頭刪除:O(1)

2.3.3雙向鏈表 插入、刪除

指在前驅(qū)和后驅(qū)方向都能游歷(遍歷)的線性鏈表

雙向鏈表的每個結(jié)點有兩個指針域
【結(jié)構(gòu)】:prior data next

雙鏈表通常采用帶頭結(jié)點的循環(huán)鏈表形式

可理解為首位相接的數(shù)據(jù)“圈”,每個結(jié)點都可以向前或向后走

【結(jié)點指向】

【插入操作】:

1.分配空間
2.斷開與連接


【操作算法

status ListInsert_DuL(DuLinkList &L,int i,ElemType e) {if(!p=GetElem_Dul(L,i)) return ERROR; //相當于嵌套第i個結(jié)點的指針if(!(s=(DuLinkList)malloc(sizeof(DuLNode)))) return ERROR //空間分配失敗 s-data=e; //將數(shù)據(jù)放入新結(jié)點的數(shù)據(jù)圖 s-prior=p-prior; //將p的前驅(qū)結(jié)點指針放入新結(jié)點的前向指針域 s-next=p; //將p放入新結(jié)點的反向指針域 p-prior-next=s; //修改p的前驅(qū)結(jié)點的反向指針 p-prior=s; // 修改p的前驅(qū)指針 return OK; } ListInsert_DuL
【刪除操作】

1.p指向目標結(jié)點
2.將目標結(jié)點的前一個結(jié)點與后一個連接(跳過中間那個)
3釋放內(nèi)存


【操作算法】
status ListDelete_Dul(DuLinkList &L,int i,ElemType &e)
{ 刪除頭結(jié)點的雙向循環(huán)鏈表L中第i個元素返回,1=i=表長
if(!p=GetElem_Dul(L,i))
return ERROR; 查找第i個指針
e=p-data; 將p指向結(jié)點數(shù)據(jù)域中的值取出
p-prior-next=p-next; p前一個結(jié)點的后驅(qū)指向p的后一個結(jié)點
p-next-prior=p-prior; 后指向前
free§; 釋放p
return OK;

} ListDelete_DuL

【 算法評價:T(n)=O(n) 】

!注意:如何選擇合適的存儲結(jié)構(gòu)
鏈表只能順序存取,在單鏈表的最后一個元素后插入元素,需遍歷整個鏈表

頻繁插入刪除用鏈式存儲
偶爾 用順序存儲

2.4一元多項式的表示及相加

  • n階多項式的表示:
    n階多項式有n+1項
    指數(shù)按升冪排序

【 優(yōu)點:

  • 多項式的項數(shù)可以動態(tài)增長,不存在存儲溢出的問題
  • 插入,刪除方便,不移動元素

【表示:
有兩個數(shù)據(jù)域,一個地址域


【一元多項式的建立算法:

void polycreate(Polylist &head) { polylist rear,s; int c,e; head=(Polynode *)malloc(sizeof(POlynode)); rear=head; //尾插法 scanf("%d,%d",&c,&e); while(c!=0){ s=(Polynode *)malloc(sizeof(Polynode));s->coef=c; s->exp=e;rear->next=s; rear=s;scanf("%d,%d",&c,&e);rear->next=NULL;} }

【一元多項式相加:

  • 掃描兩個多項式
    {若當前被檢測項指數(shù)相等,系數(shù)相加。 和不為0,則結(jié)果加到結(jié)果多項式

    {若檢查指數(shù)不等,將指數(shù)小的加到結(jié)果多項式,然后往后移

  • 若一個多項式檢測完,將另一個多項式剩余全部復制到結(jié)果多項式

【設(shè)計思想:


算法:

void polyadd(Polylist polya,Polylist polyb) { Polynode *pa,*pb,*pc,*r; int sum; pa=polya->next; pb=polyb->next; pc=polyb; //pre指向和多項式的尾結(jié)點while(pa!=NULL&&pb!=NULL) { if(pa->exp<pb->exp){pa->next=pa; pc=pa;pa=pa->next;} //【1.】 pa指數(shù)小于pb指數(shù),把pa給了pc else if(pa->exp==pb->exp){sum=pa->coef+pb->cofe;if(sum!=0) //【3.】指數(shù)相等,但系數(shù)sum不是0{pa->cofe=sum; pc->next=pa;pc=pa; pa=pa->next;r=pb; pb=pb->next ; free(r);}else //【4.】指數(shù)相等,系數(shù)sum為0{r=pa; pa=pa->next;free(r);r=pb;pb=pb->next;free(r);}}else{pc->next=pb; pc=pb;pb=pb->next;} // 【2.】pb指數(shù)小于pa指數(shù),把pb給了pcif(pa!=NULL)pc->next=pa; else pc->next=pb; }}

總結(jié)

以上是生活随笔為你收集整理的第2章线性表的基本使用及其cpp示例(第二章汇总,线性表都在这里)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。