数据结构之线性表(附代码)
數(shù)據(jù)結(jié)構(gòu) 之 線性表(附代碼)
- 線性表思維導(dǎo)圖:
- 線性表定義(邏輯結(jié)構(gòu)):
- 一、順序表
- 1、順序表思維導(dǎo)圖:
- 2、順序表的邏輯結(jié)構(gòu):
- 3、順序表基本操作的功能實現(xiàn):
- 1.線性表的靜態(tài)定義:
- 2.線性表的動態(tài)定義:
- 3. 線性表的靜態(tài)初始化:
- 4. 線性表的動態(tài)初始化:
- 5. 線性表的插入:
- 6. 線性表的刪除:
- 7. 線性表的按位查找:
- 8. 線性表的按值查找:
- 9.動態(tài)增長內(nèi)存:
- 二、鏈表:
- 1. 鏈表的思維導(dǎo)圖:
- 2.鏈表的邏輯結(jié)構(gòu):
- 3. 單鏈表:
- 1.單鏈表的定義:
- 2.不帶頭節(jié)點的單鏈表的初始化:
- 3.帶頭結(jié)點的單鏈表的初始化:
- 4.指定節(jié)點的后插操作:
- 5.帶頭結(jié)點的按位序插入:
- 6.不帶頭結(jié)點的按位序插入:
- 7.指定節(jié)點的前插操作:
- 8.帶頭節(jié)點的按位序刪除:
- 9.指定節(jié)點的刪除:
- 10.帶頭結(jié)點的按位查找:
- 11.帶頭結(jié)點的按值查找:
- 12.求表的長度:
- 13.帶頭結(jié)點的判斷空表:
- 14.尾插法建立單鏈表:
- 15.頭插法建立單鏈表:
- 4.雙鏈表:
- 1.雙鏈表的定義:
- 2. 雙鏈表的初始化:
- 3.雙鏈表的后插操作:
- 4.雙鏈表的節(jié)點刪除:
- 5.雙鏈表的銷毀:
- 6.雙鏈表的前向遍歷:
- 7.雙鏈表的后向遍歷:
- 5.循環(huán)單鏈表:
- 6.循環(huán)雙鏈表
- 1.循環(huán)雙鏈表的定義:
- 2.循環(huán)雙鏈表的初始化:
- 3.循環(huán)雙鏈表的判空:
- 4.判斷節(jié)點P是否為循環(huán)雙鏈表的表尾節(jié)點:
- 5.循環(huán)雙鏈表的插入:
- 6.循環(huán)雙鏈表的刪除:
- 7.靜態(tài)鏈表:
- 1.什么是靜態(tài)鏈表:
- 2. 靜態(tài)單鏈表的定義:
- 3.靜態(tài)鏈表的特點:
- 三、順序表和鏈表的對比:
- 1.順序表:
- 1.優(yōu)點:
- 2.缺點:
- 2.鏈表:
- 1.優(yōu)點:
- 2.缺點:
線性表思維導(dǎo)圖:
線性表定義(邏輯結(jié)構(gòu)):
線性表L是具有相同數(shù)據(jù)結(jié)構(gòu)類型的n個數(shù)據(jù)元素的有限序列
L=(a1,a2,a3,a4,…,ai,…,an)
注: 1. 元素個數(shù)有限
2. 邏輯上有先后順序性,有先后次序
3. 都是數(shù)據(jù)元素,數(shù)據(jù)類型相同,占空間相同
4. 除a1外,都有唯一前驅(qū); 除an外,都有唯一后繼
注:&表示對修改的結(jié)果“帶回來”,即操作同一地址空間的數(shù)據(jù),例:
#include<stdio.h>void test(int x){x = 1024;printf("test內(nèi)部x=%d\n",x); }int main(){int x = 1;printf("執(zhí)行test前x=%d\n",x);test(x);printf("執(zhí)行test后x=%d\n",x); } 運行結(jié)果:1,1024,1 #include<stdio.h>void test(int &x){x = 1024;printf("test內(nèi)部x=%d\n",x); }int main(){int x = 1;printf("執(zhí)行test前x=%d\n",x);test(x);printf("執(zhí)行test后x=%d\n",x); } 運行結(jié)果:1,1024,1024一、順序表
1、順序表思維導(dǎo)圖:
2、順序表的邏輯結(jié)構(gòu):
邏輯相鄰物理也相鄰3、順序表基本操作的功能實現(xiàn):
1.線性表的靜態(tài)定義:
#define MaxSize 100; //定義順序表最大長度 typedef struct{ElemType data[MaxSize]; int length; //當(dāng)前順序表的長度 }SqlList; //順序表的類型定義2.線性表的動態(tài)定義:
typedef struct{int *data; //動態(tài)分配數(shù)組的指針 int MaxSize; //順序表的最大容量int length; //當(dāng)前順序表的長度 }SqlList; //順序表的類型定義3. 線性表的靜態(tài)初始化:
void InitList(SqlList &L){for(int i = 0;i < MaxSize; i++)L.data[i] = 0; //防止“臟數(shù)據(jù)”L.length = 0; }4. 線性表的動態(tài)初始化:
#define InitSize 10 void InitList(SqlList &L){L.data = (int *)malloc(InitSize * sizeof(int))L.length = 0;L.MaxSize = InitSize; }5. 線性表的插入:
bool ListInsert(SqlList &L,int i,ElemType e){if(i < 1 || i > L.length) //判斷i值是否合法return false;if(L.length > L.MaxSize) //判斷return false;for(int j = L.length;j >= i;j--)L.data[j] = L.data[j-1];L.data[i-1] = e;L.length++;return true; }6. 線性表的刪除:
bool ListDelete(SqlList &L,int i,ElemType &e){if(i < 1 || i > L.length)return false;e = L.data[i-1];for(int j = i;j < L.length;j ++)L.data[j-1] = L.data[j];L.length--;return true; }7. 線性表的按位查找:
ElemType GetElem(SqlList L,int i){return L.data[i-1]; }8. 線性表的按值查找:
ElemType LocateElem(SqlList L,ElemType e){for(int i = 0;i < L.length;i ++)if(L.data[i] == e)return i+1;return 0; }9.動態(tài)增長內(nèi)存:
void IncreaseSize(SqlList &L,int len){int *p = L.data;L.data = (int *)malloc((L.MaxSize+len) * sizeof(int));for(int i = 0;i < L.length;i++)L.data[i] = p[i];L.MaxSize = L.MaxSize + len;free(p); }二、鏈表:
1. 鏈表的思維導(dǎo)圖:
2.鏈表的邏輯結(jié)構(gòu):
邏輯上相鄰物理上不一定相鄰,由指針指向下一個數(shù)據(jù)元素
3. 單鏈表:
注: 未明確說明,一律按帶頭節(jié)點處理
注: LNode * = LinkList,但是LinkList強(qiáng)調(diào)的是一個鏈表,而LNode *強(qiáng) 調(diào)的是一個節(jié)點。例如:
聲明一個單鏈表時:
定義一個節(jié)點時:
LNode *p;1.單鏈表的定義:
typedef struct LNode{int data;struct LNode *next; }LNode,*LinkList;2.不帶頭節(jié)點的單鏈表的初始化:
bool InitList(LinkList &L){L = NULL; //空表 return true; }3.帶頭結(jié)點的單鏈表的初始化:
bool InitList (LinkList &L){L = (LNode *)malloc(sizeof(LNode));if(L == false)return false; //內(nèi)存不足,無法分配 L->next = NULL;return true; }4.指定節(jié)點的后插操作:
bool InsertNextNode(LNode *p,int e){if(p == NULL)return false;LNode *s = (LNode *)malloc(sizeof(LNode));if(s == NULL)return false;s->data = e;s->next = p->next;return true; }5.帶頭結(jié)點的按位序插入:
bool ListInsert(LinkList &L,int i,int e){if(i < 1)return false;LNode *p;int j = 0;p = L;while(p != NULL && j < i-1){ //找要插入位置節(jié)點的前驅(qū)節(jié)點 p = p->next;j++;} InsertNextNode(p,e); //后插操作 }6.不帶頭結(jié)點的按位序插入:
bool ListInsert(LinkList &L,int i,int e){if(i < 1)return false;if(i == 1){LNode *s = (LNode *)malloc(sizeof(LNode));s->data = e;s->next = L;return true;}LNode *p;int j = 0;p = L;while(p != NULL && j < i-1){ //找要插入位置節(jié)點的前驅(qū)節(jié)點 p = p->next;j++;} InsertNextNode(p,e); //后插操作 }7.指定節(jié)點的前插操作:
bool InsertPriorNode(LNode *p,LNode *s){//第一種方法:遍歷整個單鏈表,找到p節(jié)點的前驅(qū)節(jié)點,執(zhí)行后插操作//第二種方法:在p節(jié)點后直接插入新節(jié)點q,然后交換 p節(jié)點和q節(jié)點的值//此處只演示第二種方法if(p == NULL || s == NULL)return false;s->next = p->next;p->next = s;int temp = p->data;p->data = s->data;s->data = temp;return true; }8.帶頭節(jié)點的按位序刪除:
bool ListDelete(LinkList &L,int i,int &e){if(i < 1)return false;LNode *p;int j=0;p = L;while(p != NULL && j < i-1){p = p->next;j++;}if(p == NULL)return false;if(p->next == NULL)return false;LNode *q = p->next;e = q->data;p->next = q->next;free(q);return true; }9.指定節(jié)點的刪除:
bool DeleteNode(LNode *p){if(p == NULL)return false;LNode *q = p->next;p->data = p->next->data;p->next - q->next;free(q);return true; }10.帶頭結(jié)點的按位查找:
LNode* GetElem(LinkList L,int i){if(i < 0)return NULL;LNode *p;int j = 0;p = L;while(p != NULL && j < i){p = p->next;j++;} return p; }11.帶頭結(jié)點的按值查找:
LNode* locateElem(LinkList L,int e){LNode *p = L->next;while(p != NULL && p->data != e)p = p->next;return p; }12.求表的長度:
int length(LinkList L){int len = 0;LNode *p = L;while(p->next != NULL){p = p->next;len++;}return len; }13.帶頭結(jié)點的判斷空表:
bool Empty(LinkList L){if(L->next == NULL)return true;elsereturn false; }14.尾插法建立單鏈表:
LinkList List_TailInsert(LinkList &L){int x;L = (LinkList)malloc(sizeof(LNode));LNode *s,*r = L;scanf("%d",&x);while(x != 9999){s = (LNode *)malloc(sizeof(LNode));s->data = x;r->next = s;r = s;scanf("%d",&x);}r->next = NULL;return L; }15.頭插法建立單鏈表:
LinkList List_HeadInsert(LinkList &L){int x;LNode *s;L = (LinkList)malloc(sizeof(LNode));L->next = NULL;scanf("%d",&x);while(x != 9999){s = (LNode *)malloc(sizeof(LNode));s->data = x;s->next = L->next;L->next = s;scanf("%d",&x);}return L; }4.雙鏈表:
1.雙鏈表的定義:
typedef struct DNode{int data;struct DNode *prior,*next; }DNode,*DLinkList;2. 雙鏈表的初始化:
bool InitDLinkList(DLinkList &L){L = (DNode *)malloc(sizeof(DNode));if(L == NULL)return false;L->prior = NULL;L->next = NULL;return true; }3.雙鏈表的后插操作:
bool InsertNextDNode(DNode *p,DNode *s){if(p==NULL || s == NULL)return false;s->next = p->next;if(p->next != NULL) //p節(jié)點有后記節(jié)點 p->next->prior = s;s->prior = p;p->next = s;return true; }4.雙鏈表的節(jié)點刪除:
bool DeleteNextDNode(DNode *p){if(p == NULL)return false;DNode *q = p->next;if(q == NULL)return false;p->next = q->next;if(q->next != NULL)q->next->prior = p;free(q);return true; }5.雙鏈表的銷毀:
void DestoryList(DLinkList &L){while(L->next != NULL)DeleteNextDNode(L);free(L);L = NULL;}6.雙鏈表的前向遍歷:
void PriorTraverse(DNode *p){while(p != NULL){printf("%d\n",p->data);p = p->prior;} }7.雙鏈表的后向遍歷:
void NextTraverse(DNode *p){while(p != NULL){printf("%d\n",p->data);p = p->next;} }5.循環(huán)單鏈表:
把單鏈表的最后一個指針指向頭節(jié)點L即可。其他操作同單鏈表相似,小編就水了哈。
注: 當(dāng)執(zhí)行插入操作時,可將L指向最后一個節(jié)點。這樣就不用遍歷整 個鏈表了,神奇不神奇。
6.循環(huán)雙鏈表
1.循環(huán)雙鏈表的定義:
typedef struct DNode{int data;struct DNode *prior,*next; }DNode,*DLinkList;2.循環(huán)雙鏈表的初始化:
bool InitDLinkList(DLinkList &L){L = (DNode *)malloc(sizeof(DNode));if(L == NULL)return false;L->prior = L;L->next = L;return true; }3.循環(huán)雙鏈表的判空:
bool Empty(DLinkList L){if(L->next == L)return true;elsereturn false; }4.判斷節(jié)點P是否為循環(huán)雙鏈表的表尾節(jié)點:
bool isTail(DLinkList L,DNode *p){if(p->next == L)return true;elsereturn false; }5.循環(huán)雙鏈表的插入:
bool InsertNextDNode(DNode *p,DNode *s){if(p==NULL || s == NULL)return false;s->next = p->next;p->next->prior = s;s->prior = p;p->next = s;return true; }6.循環(huán)雙鏈表的刪除:
bool DeleteNextDNode(DNode *p){if(p == NULL)return false;DNode *q = p->next;if(q == NULL)return false;p->next = q->next;q->next->prior = p;free(q);return true; }7.靜態(tài)鏈表:
1.什么是靜態(tài)鏈表:
特殊類型的單鏈表,分配一片連續(xù)的存儲空間,各個節(jié)點集中安置,單鏈表的指針映射成游標(biāo),即用數(shù)組的方式實現(xiàn)鏈表。如圖:
注:假設(shè)第一個數(shù)據(jù)元素的地址為addr,一個數(shù)據(jù)元素4B,一個游標(biāo)4B,則第n個數(shù)據(jù)元素的地址:(addr + n * 8)B
2. 靜態(tài)單鏈表的定義:
typedef struct Node SLinkList[MaxSize];typedef struct Node{int data; //存儲數(shù)據(jù)元素 int next; //存儲數(shù)據(jù)元素的數(shù)組下標(biāo) }SLinkList[MaxSize];void test(){SLinkList a; //初始化了一個MaxSize大小的數(shù)組 }或者
struct Node{int data; //存儲數(shù)據(jù)元素 int next; //存儲數(shù)據(jù)元素的數(shù)組下標(biāo) };typedef struct Node SLinkList[MaxSize];二者等價
3.靜態(tài)鏈表的特點:
優(yōu)點:增刪不需要移動大量的元素
缺點:不能隨機(jī)存取,查找不便;容量固定不可變
三、順序表和鏈表的對比:
1.順序表:
1.優(yōu)點:
1.隨機(jī)存取,查找速度快。2.存儲密度高,每個數(shù)據(jù)元素只需要存儲數(shù)據(jù)本身即可2.缺點:
1.空間分配不便,需要一塊連續(xù)的存儲空間2.改變?nèi)萘坎槐?2.鏈表:
1.優(yōu)點:
1.空間分配方便,只需分配離散的小空間即可2.容量改變方便2.缺點:
1.存儲密度小,除了要存儲數(shù)據(jù)本身外,還要存儲指針2.不可隨機(jī)存取,查找不便開放式答題框架技巧:
ps: 累死小編了,整整敲了一天代碼,有些地方直接省略掉了,大家腦補(bǔ)腦補(bǔ)哈。這是小編第一次寫博客,不足之處請多多諒解。有任何問題,隨時可以叨擾小編。若有錯誤的地方,請聯(lián)系小編指正。
總結(jié)
以上是生活随笔為你收集整理的数据结构之线性表(附代码)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。