目錄
- 前言
- 1. 鏈表的概念
- 3. 鏈表的結構
- 4. 無頭單向非回圈鏈表的實作
- 4.1 創建工程
- 4.2 定義結構體
- 4.3 創建一個新節點
- 4.3.1 SList.h 宣告
- 4.3.2 SList.c 定義
- 4.4 頭插尾插操作
- 4.4.1 SList.h 宣告
- 4.3.2 SList.c 定義
- 4.5 頭刪尾刪操作
- 4.5.1 SList.h 宣告
- 4.5.2 SList.c 定義
- 4.6 查找操作
- 4.6.1 SList.h 宣告
- 4.6.2 SList.c 定義
- 4.7 修改操作
- 4.7.1 SList.h 宣告
- 4.7.2 SList.c 定義
- 4.8 前插后插操作
- 4.8.1 SList.h 宣告
- 4.8.2 SList.c 定義
- 4.9 現刪后刪操作
- 4.9.1 SList.h 宣告
- 4.9.2 SList.c 定義
- 4.10 完整代碼展示及運行
- 4.10.1 SeqList.h
- 4.10.2 SeqList.c
- 4.10.3 test.c
- 4.10.4 運行測驗
- 5. 帶頭雙向回圈鏈表的實作
- 5.1 創建工程
- 5.2 定義結構體
- 5.3 創建一個新節點和創建頭節點
- 5.3.1 DList.h宣告
- 5.3.2 DList.c定義
- 5.4 插入操作
- 5.4.1 DList.h宣告
- 5.4.2 DList.c定義
- 5.5 洗掉操作
- 5.5.1 DList.h宣告
- 5.5.2 DList.c定義
- 5.6 查找操作
- 5.6.1 DList.h宣告
- 5.6.2 DList.c定義
- 5.7 修改操作
- 5.7.1 DList.h宣告
- 5.7.2 DList.c定義
- 5.8 判空求長和銷毀操作
- 5.8.1 DList.h宣告
- 5.8.2 DList.c定義
- 5.9 完整代碼展示及運行
- 5.9.1 DList.h
- 5.9.2 DList.c
- 5.9.3 test.c
- 5.9.4 運行測驗
- 6. 順序表和鏈表的優缺點對比
- 6.1 順序表的優點
- 6.2 順序表缺點
- 6.3 鏈表優點
- 6.4 鏈表缺點
- 6.5 總結
- 后記
前言
hello,大家好,這期文章繼續用來更新資料結構方面的知識——鏈表,,這期文章依舊是對之前的文章資料結構:紅玫瑰與白玫瑰之爭的補充,希望對大家有所幫助,我們在之前的文章中已經介紹過順序表,鏈表和順序表有很大的不同,相對于順序表,鏈表無疑是更加靈活的,順序表在實作程序中頭部插入資料時需要挪動資料,在增容的程序中也會消耗性能,并且以倍數的方式增容也會造成空間的浪費,鏈表相對于順序表而言,也許會做的更好
1. 鏈表的概念
鏈表是一種物理存盤結構上非連續、非順序的存盤結構,資料元素的邏輯順序是通過鏈表中的指標鏈接次序實作的
通俗理解,鏈表就是把資料塊連接起來,還方便拆卸,可以隨時將資料塊加入進去,或者拿出去,


3. 鏈表的結構

在這些鏈表結構的組合之中,我們最常用的是兩種

- 無頭單向非回圈鏈表:結構簡單,一般不會單獨用來存資料,實際中更多是作為其他資料結構的子結構,如哈希桶、圖的鄰接表等等,另外這種結構在筆試面試中出現很多,
- 帶頭雙向回圈鏈表:結構最復雜,一般用在單獨存盤資料,實際中使用的鏈表資料結構,都是帶頭雙向回圈鏈表,另外這個結構雖然結構復雜,但是使用代碼實作以后會發現結構會帶來很多優勢,實作反而簡單了
4. 無頭單向非回圈鏈表的實作
4.1 創建工程
依舊采用多檔案的方式

4.2 定義結構體
typedef int SLDataType;
typedef struct SListNode
{
int data;
struct SListNode *next;
}SLNode;
4.3 創建一個新節點
4.3.1 SList.h 宣告
SLNode *BuySLNode(SLDataType x);
4.3.2 SList.c 定義
SLNode *BuySLNode(SLDataType x)
{
SLNode *node = (SLNode*)malloc(sizeof(SLNode));
node->data = x;
node->next = NULL;
return node;
}

創建一個新節點會在增加操作中頻繁使用,所以我們單獨定義出一個函式來,創建新節點的思路就是開辟一塊空間,空間里存放想要存放的資料,并使這塊空間指向NULL,
4.4 頭插尾插操作
注意,在頭插尾插操作中,我們傳遞的都是二級指標,因為節點本身就是指標,我們知道按地址傳參才可以改變原值,由于plist本身就是指標,要想改變它,所以我們需要傳二級指標**pplist,
4.4.1 SList.h 宣告
void SListPushFront(SLNode **pplist, SLDataType x);
void SListPushBack(SLNode **pplist, SLDataType x);
4.3.2 SList.c 定義
void SListPushFront(SLNode **pplist, SLDataType x)
{
SLNode*newnode = BuySLNode(x);
newnode->next = *pplist;
*pplist = newnode;
}
void SListPushBack(SLNode **pplist, SLDataType x)
{
SLNode*newnode = BuySLNode(x);
//空和非空
if (*pplist == NULL)
{
*pplist = newnode;
}
else
{
//先遍歷找尾
SLNode *tail = *pplist;
while (tail->next != NULL)
{
tail = tail->next;
}
SLNode *newnode = BuySLNode(x);
tail->next = newnode;
}
}
頭插相對于尾插更好實作,只需要在頭節點前鏈接上新節點就好,但是尾插則需要考慮的更多一些,實作我們要判斷鏈表此時是否為空,如果是空則不需尾插,如果非空,我們則需要首先找到鏈表的尾,在尾上插入新的節點,尾插影片演示如下:

4.5 頭刪尾刪操作
4.5.1 SList.h 宣告
void SListPopFront(SLNode **pplist);
void SListPopBack(SLNode **pplist);
4.5.2 SList.c 定義
void SListPopFront(SLNode **pplist)
{
if (*pplist == NULL)
{
return;
}
else
{
SLNode *next= (*pplist)->next;
free(*pplist);
*pplist = next;
}
}
void SListPopBack(SLNode **pplist)
{
if (*pplist == NULL)
{
return;
}
else if ((*pplist)->next == NULL)
{
free(*pplist);
*pplist = NULL;
}
else
{
SLNode *prev = NULL;
SLNode *tail = *pplist;
while (tail->next != NULL)
{
prev = tail;
tail = tail->next;
}
free(tail);
tail = NULL;
prev->next = NULL;
}
}
頭刪只需要去除第一個節點,注意判斷如果鏈表為空則不需要操作,對于尾刪,依舊是要先找到尾部,還要找到尾部節點的前一個節點prev,將尾部節點釋放,然后將prev置為新的尾節點,尾刪影片演示如下:

4.6 查找操作
查找操作要回傳該節點的指標,注意考慮空鏈表的情況,
4.6.1 SList.h 宣告
SLNode*SListFind(SLNode **pplist, SLDataType x);
4.6.2 SList.c 定義
SLNode*SListFind(SLNode **pplist, SLDataType x)
{
SLNode *cur = *pplist;
while (cur)
{
if (cur->data == x)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
4.7 修改操作
修改操作時在查找的基礎上進行的,找到要修改的值的節點,然后進行修改,注意要考慮找不到要修改的資料的情況,
4.7.1 SList.h 宣告
void SListModify(SLNode *plist, SLDataType x, SLDataType y);
4.7.2 SList.c 定義
void SListModify(SLNode *plist, SLDataType x, SLDataType y)
{
SLNode *pos = SListFind(&plist, x);
if (pos)
{
pos->data = y;
}
else
{
printf("沒有該數字,無法修改\n");
}
}
4.8 前插后插操作
前插后插比頭插尾插更復雜一些,尤其是前插操作,需要考慮的東西會多一點,后插我們只需要在位置后加入一個新的節點,而前插則需要考慮該位置是不是頭節點,如果不是頭節點,還需要找到該位置并且需要找到該位置的前一個節點,將新節點插入其中,下面通過影片演示非首元素前插的情況:

4.8.1 SList.h 宣告
void SListInsertAfter(SLNode *pos, SLDataType x);
void SListInsertBefore(SLNode **pplist,SLNode *pos, SLDataType x);
4.8.2 SList.c 定義
void SListInsertAfter(SLNode *pos, SLDataType x)
{
assert(pos);
SLNode *newnode = BuySLNode(x);
newnode->next = pos->next;
pos->next = newnode;
}
void SListInsertBefore(SLNode **pplist, SLNode *pos, SLDataType x)
{
assert(pos);
SLNode *newnode = BuySLNode(x);
if (pos == *pplist)
{
newnode->next = pos;
*pplist = newnode;
}
else
{
SLNode *prev = NULL;
SLNode *cur = *pplist;
while (cur != pos)
{
prev = cur;
cur = cur->next;
}
prev->next = newnode;
newnode->next = pos;
}
}
4.9 現刪后刪操作
對于洗掉操作,我們再這里實作洗掉指定位置后的節點和指定位置的節點,因為洗掉指定位置之前的節點實作起來非常麻煩且意義不大,因為我們可以通過改變指定位置來實作洗掉前一個節點,洗掉指定位置后一個節點需要考慮是否為空鏈表,洗掉當前位置節點則需要考慮當前位置是否為首節點,我們在這里用影片演示洗掉非首節點當前節點的操作:

4.9.1 SList.h 宣告
void SListEraseAfter(SLNode*pos);
void SListEraseCur(SLNode **pplist,SLNode*pos);
4.9.2 SList.c 定義
void SListEraseAfter(SLNode*pos)
{
assert(pos);
if (pos->next == NULL)
{
return;
}
else
{
SLNode*next = pos->next;
pos->next = next->next;
free(next);
next = NULL;
}
}
void SListEraseCur(SLNode **pplist,SLNode*pos)
{
if (pos == *pplist)
{
return;
}
else
{
SLNode *prev = NULL;
SLNode *cur = *pplist;
while (cur != pos)
{
prev = cur;
cur = cur->next;
}
prev->next = pos->next;
free(cur);
cur = NULL;
}
}
4.10 完整代碼展示及運行
4.10.1 SeqList.h
#include<stdio.h>
#include<malloc.h>
#include<assert.h>
typedef int SLDataType;
typedef struct SListNode
{
int data;
struct SListNode *next;
}SLNode;
//單向+帶頭+不回圈
void SListPrint(SLNode *plist);
SLNode *BuySLNode(SLDataType x);
//二級指標
void SListPushFront(SLNode **pplist, SLDataType x);
void SListPushBack(SLNode **pplist, SLDataType x);
void SListInsertAfter(SLNode *pos, SLDataType x);
void SListInsertBefore(SLNode **pplist,SLNode *pos, SLDataType x);
void SListPopFront(SLNode **pplist);
void SListPopBack(SLNode **pplist);
void SListEraseAfter(SLNode*pos);
void SListEraseCur(SLNode **pplist,SLNode*pos);
SLNode*SListFind(SLNode **pplist, SLDataType x);
void SListModify(SLNode *plist, SLDataType x, SLDataType y);
4.10.2 SeqList.c
#include"SList.h"
void SListPrint(SLNode *plist)
{
SLNode *cur = plist;
while (cur != NULL)
{
printf("%d->", cur->data);
cur = cur->next;
}
printf("NULL\n");
}
SLNode *BuySLNode(SLDataType x)
{
SLNode *node = (SLNode*)malloc(sizeof(SLNode));
node->data = x;
node->next = NULL;
return node;
}
void SListPushFront(SLNode **pplist, SLDataType x)
{
SLNode*newnode = BuySLNode(x);
newnode->next = *pplist;
*pplist = newnode;
}
void SListPushBack(SLNode **pplist, SLDataType x)
{
SLNode*newnode = BuySLNode(x);
//空和非空
if (*pplist == NULL)
{
*pplist = newnode;
}
else
{
//先遍歷找尾
SLNode *tail = *pplist;
while (tail->next != NULL)
{
tail = tail->next;
}
SLNode *newnode = BuySLNode(x);
tail->next = newnode;
}
}
void SListPopFront(SLNode **pplist)
{
if (*pplist == NULL)
{
return;
}
else
{
SLNode *next= (*pplist)->next;
free(*pplist);
*pplist = next;
}
}
void SListPopBack(SLNode **pplist)
{
if (*pplist == NULL)
{
return;
}
else if ((*pplist)->next == NULL)
{
free(*pplist);
*pplist = NULL;
}
else
{
SLNode *prev = NULL;
SLNode *tail = *pplist;
while (tail->next != NULL)
{
prev = tail;
tail = tail->next;
}
free(tail);
tail = NULL;
prev->next = NULL;
}
}
SLNode*SListFind(SLNode **pplist, SLDataType x)
{
SLNode *cur = *pplist;
while (cur)
{
if (cur->data == x)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
void SListModify(SLNode *plist, SLDataType x, SLDataType y)
{
SLNode *pos = SListFind(&plist, x);
if (pos)
{
pos->data = y;
}
else
{
printf("沒有該數字,無法修改\n");
}
}
void SListInsertAfter(SLNode *pos, SLDataType x)
{
assert(pos);
SLNode *newnode = BuySLNode(x);
newnode->next = pos->next;
pos->next = newnode;
}
void SListInsertBefore(SLNode **pplist, SLNode *pos, SLDataType x)
{
assert(pos);
SLNode *newnode = BuySLNode(x);
if (pos == *pplist)
{
newnode->next = pos;
*pplist = newnode;
}
else
{
SLNode *prev = NULL;
SLNode *cur = *pplist;
while (cur != pos)
{
prev = cur;
cur = cur->next;
}
prev->next = newnode;
newnode->next = pos;
}
}
void SListEraseAfter(SLNode*pos)
{
assert(pos);
if (pos->next == NULL)
{
return;
}
else
{
SLNode*next = pos->next;
pos->next = next->next;
free(next);
next = NULL;
}
}
void SListEraseCur(SLNode **pplist,SLNode*pos)
{
if (pos == *pplist)
{
return;
}
else
{
SLNode *prev = NULL;
SLNode *cur = *pplist;
while (cur != pos)
{
prev = cur;
cur = cur->next;
}
prev->next = pos->next;
free(cur);
cur = NULL;
}
}
4.10.3 test.c
#include"SList.h"
void TestOne()
{
SLNode *plist = NULL;
SListPushBack(&plist, 1);
SListPushBack(&plist, 2);
SListPushBack(&plist, 3);
SListPushBack(&plist, 4);
SListPrint(plist);
SListPushFront(&plist, 5);
SListPushFront(&plist, 6);
SListPrint(plist);
SListPopBack(&plist);
SListPrint(plist);
SListPopFront(&plist);
SListPrint(plist);
SLNode *pos = SListFind(&plist, 3);
if (pos)
{
printf("找到了\n");
}
else
{
printf("沒有找到\n");
}
SListInsertBefore(&plist, pos, 0);
SListInsertAfter(pos, 9);
SListPrint(plist);
SListEraseAfter(pos);
SListPrint(plist);
SListEraseCur(&plist,pos);
SListPrint(plist);
}
int main()
{
TestOne();
return 0;
}
4.10.4 運行測驗

5. 帶頭雙向回圈鏈表的實作
5.1 創建工程
依舊采用多檔案形式

5.2 定義結構體
typedef int LDataType;
typedef struct ListNode
{
struct ListNode*next;
struct ListNode*prev;
LDataType data;
}ListNode;
5.3 創建一個新節點和創建頭節點
5.3.1 DList.h宣告
ListNode *BuyListNode(LDataType x);
ListNode * ListCreate();
5.3.2 DList.c定義
ListNode *BuyListNode(LDataType x)
{
ListNode*node = (ListNode*)malloc(sizeof(ListNode));
node->next = NULL;
node->prev = NULL;
node->data = x;
return node;
}
ListNode * ListCreate()
{
ListNode*phead = BuyListNode(0);
phead->next = phead;
phead->prev = phead;
return phead;
}
創建的新節點:

創建的頭節點:

5.4 插入操作
插入操作我們要實作的有頭插尾插和指定位置的插入,
5.4.1 DList.h宣告
void ListPushFront(ListNode *phead, LDataType x);
void ListPushBack(ListNode *phead, LDataType x);
void ListInsert(ListNode * pos, LDataType x);
5.4.2 DList.c定義
void ListPushFront(ListNode *phead, LDataType x)
{
assert(phead);
ListNode*first = phead->next;
ListNode*newnode = BuyListNode(x);
phead->next = newnode;
newnode->prev = phead;
newnode->next = first;
first->prev = newnode;
}
void ListPushBack(ListNode *phead, LDataType x)
{
assert(phead);
ListNode *tail = phead->prev;
ListNode *newnode = BuyListNode(x);
tail->next = newnode;
newnode->prev = tail;
newnode->next = phead;
phead->prev = newnode;
}
void ListInsert(ListNode * pos, LDataType x)
{
assert(pos);
ListNode*prev = pos->prev;
ListNode*newnode = BuyListNode(x);
prev->next = newnode;
newnode->prev = prev;
newnode->next = pos;
pos->prev = newnode;
}
頭插:

尾插:

指定位置插入:

5.5 洗掉操作
洗掉操作我們來實作頭刪尾刪和指定位置的洗掉,洗掉操作要考慮空鏈表的情況,我們用斷言來判斷,assert((phead->next) != phead);,如果頭節點的next指向頭節點,則證明鏈表為空,
5.5.1 DList.h宣告
void ListPopFront(ListNode *phead);
void ListPopBack(ListNode *phead);
void ListErase(ListNode * pos);
5.5.2 DList.c定義
void ListPopFront(ListNode *phead)
{
assert(phead);
assert((phead->next) != phead);
ListNode*first = phead->next;
ListNode*second = first->next;
free(first);
first = NULL;
phead->next = second;
second->prev = phead;
}
void ListPopBack(ListNode *phead)
{
assert(phead);
assert((phead->next)!= phead);
ListNode*tail = phead->prev;
ListNode*tailprev = tail->prev;
free(tail);
tail = NULL;
tailprev->next = phead;
phead->prev = tailprev;
}
void ListErase(ListNode * pos)
{
assert(pos);
ListNode *prev = pos->prev;
ListNode *next = pos->next;
prev->next = next;
next->prev = prev;
free(pos);
pos = NULL;
}
頭刪:

尾刪:

指定位置的洗掉:

5.6 查找操作
5.6.1 DList.h宣告
ListNode *ListFind(ListNode *phead,LDataType x);
5.6.2 DList.c定義
ListNode *ListFind(ListNode *phead, LDataType x)
{
assert(phead);
ListNode*cur = phead->next;
while (cur != phead)
{
if (cur->data == x)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
5.7 修改操作
5.7.1 DList.h宣告
void ListModify(ListNode*pos,LDataType x);
5.7.2 DList.c定義
void ListModify(ListNode*pos, LDataType x)
{
assert(pos);
pos->data = x;
}
5.8 判空求長和銷毀操作
注意在進行銷毀操作時,要逐個釋放,并且在呼叫銷毀操作后,將頭節點置為NULL,
5.8.1 DList.h宣告
int ListEmpty(ListNode *phead);
int ListSize(ListNode *phead);
void ListDestory(ListNode *phead);
5.8.2 DList.c定義
int ListEmpty(ListNode *phead)
{
return phead->next == phead ? 1 : 0;
}
int ListSize(ListNode *phead)
{
assert(phead);
int size = 0;
ListNode*cur = phead->next;
while (cur != phead)
{
++size;
cur = cur->next;
}
return size;
}
void ListDestory(ListNode *phead)
{
assert(phead);
ListNode*cur = phead->next;
while (cur != phead)
{
ListNode*next = cur->next;
free(cur);
cur = next;
}
free(phead);
}
5.9 完整代碼展示及運行
5.9.1 DList.h
#include<stdio.h>
#include<malloc.h>
#include<assert.h>
typedef int LDataType;
typedef struct ListNode
{
struct ListNode*next;
struct ListNode*prev;
LDataType data;
}ListNode;
void ListPrint(ListNode*phead);
ListNode *BuyListNode(LDataType x);
ListNode * ListCreate();
void ListPushFront(ListNode *phead, LDataType x);
void ListPushBack(ListNode *phead, LDataType x);
void ListPopFront(ListNode *phead);
void ListPopBack(ListNode *phead);
ListNode *ListFind(ListNode *phead,LDataType x);
void ListModify(ListNode*pos,LDataType x);
void ListInsert(ListNode * pos, LDataType x);
void ListErase(ListNode * pos);
int ListEmpty(ListNode *phead);
int ListSize(ListNode *phead);
void ListDestory(ListNode *phead);
5.9.2 DList.c
#include"DList.h"
void ListPrint(ListNode*phead)
{
ListNode *cur = phead->next;
while (cur != phead)
{
printf("%d ", cur->data);
cur = cur->next;
}
printf("\n");
}
ListNode *BuyListNode(LDataType x)
{
ListNode*node = (ListNode*)malloc(sizeof(ListNode));
node->next = NULL;
node->prev = NULL;
node->data = x;
return node;
}
ListNode * ListCreate()
{
ListNode*phead = BuyListNode(0);
phead->next = phead;
phead->prev = phead;
return phead;
}
void ListPushFront(ListNode *phead, LDataType x)
{
assert(phead);
ListNode*first = phead->next;
ListNode*newnode = BuyListNode(x);
phead->next = newnode;
newnode->prev = phead;
newnode->next = first;
first->prev = newnode;
}
void ListPushBack(ListNode *phead, LDataType x)
{
assert(phead);
ListNode *tail = phead->prev;
ListNode *newnode = BuyListNode(x);
tail->next = newnode;
newnode->prev = tail;
newnode->next = phead;
phead->prev = newnode;
}
void ListPopFront(ListNode *phead)
{
assert(phead);
assert((phead->next) != phead);
ListNode*first = phead->next;
ListNode*second = first->next;
free(first);
first = NULL;
phead->next = second;
second->prev = phead;
}
void ListPopBack(ListNode *phead)
{
assert(phead);
assert((phead->next)!= phead);
ListNode*tail = phead->prev;
ListNode*tailprev = tail->prev;
free(tail);
tail = NULL;
tailprev->next = phead;
phead->prev = tailprev;
}
ListNode *ListFind(ListNode *phead, LDataType x)
{
assert(phead);
ListNode*cur = phead->next;
while (cur != phead)
{
if (cur->data == x)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
void ListModify(ListNode*pos, LDataType x)
{
assert(pos);
pos->data = x;
}
void ListInsert(ListNode * pos, LDataType x)
{
assert(pos);
ListNode*prev = pos->prev;
ListNode*newnode = BuyListNode(x);
prev->next = newnode;
newnode->prev = prev;
newnode->next = pos;
pos->prev = newnode;
}
void ListErase(ListNode * pos)
{
assert(pos);
ListNode *prev = pos->prev;
ListNode *next = pos->next;
prev->next = next;
next->prev = prev;
free(pos);
pos = NULL;
}
int ListEmpty(ListNode *phead)
{
return phead->next == phead ? 1 : 0;
}
int ListSize(ListNode *phead)
{
assert(phead);
int size = 0;
ListNode*cur = phead->next;
while (cur != phead)
{
++size;
cur = cur->next;
}
return size;
}
void ListDestory(ListNode *phead)
{
assert(phead);
ListNode*cur = phead->next;
while (cur != phead)
{
ListNode*next = cur->next;
free(cur);
cur = next;
}
free(phead);
}
5.9.3 test.c
#include"DList.h"
void TestOne()
{
ListNode*plist = ListCreate();
ListPushBack(plist, 1);
ListPushBack(plist, 2);
ListPushBack(plist, 3);
ListPushBack(plist, 4);
ListPrint(plist);
ListPushFront(plist, 1);
ListPushFront(plist, 2);
ListPushFront(plist, 3);
ListPushFront(plist, 4);
ListPrint(plist);
ListPopBack(plist);
ListPopBack(plist);
ListPrint(plist);
ListNode*pos = ListFind(plist, 1);
if (pos)
{
printf("找到了\n");
}
else
{
printf("沒找到\n");
}
ListInsert(pos, 0);
ListPrint(plist);
ListModify(pos, 9);
ListPrint(plist);
ListErase(pos);
ListPrint(plist);
printf("%d\n", ListEmpty(plist));
printf("%d\n", ListSize(plist));
ListDestory(plist);
plist = NULL;
}
int main()
{
TestOne();
return 0;
}
5.9.4 運行測驗

6. 順序表和鏈表的優缺點對比
鏈表以帶頭雙向回圈鏈表為例
6.1 順序表的優點
支持按下標訪問
6.2 順序表缺點
空間不夠需要增容,有性能消耗,可能會造成空間浪費,
頭部或中間插入資料需要挪動資料,效率較低,
6.3 鏈表優點
按需申請記憶體,不存在空間浪費,
在時間復雜度O(1)的時間內插入洗掉資料,
6.4 鏈表缺點
不支持下標隨機訪問
6.5 總結
鏈表和順序表各有優缺,根據具體場景選擇使用,
后記
好的,這期誠意滿滿干貨滿滿的文章就先分享到這里啦,希望對大家有所幫助,也歡迎大家批評指正,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/300471.html
標籤:其他
