欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

目錄

柚子快報(bào)激活碼778899分享:數(shù)據(jù)結(jié)構(gòu)--雙鏈表

柚子快報(bào)激活碼778899分享:數(shù)據(jù)結(jié)構(gòu)--雙鏈表

http://yzkb.51969.com/

目錄

一、引言

二 、鏈表的分類(lèi)

1.單向或雙向

2.帶頭或不帶頭?

3.循環(huán)或不循環(huán)?

?三、雙鏈表的概念與基本結(jié)構(gòu)

1.概念

2.基本結(jié)構(gòu)?

三、雙鏈表的常見(jiàn)操作

1.創(chuàng)建節(jié)點(diǎn)

2.初始化?

3.頭插

4.尾插

5.頭刪

6.尾刪

7.打印

8.查找

9.插入節(jié)點(diǎn)

10.刪除節(jié)點(diǎn)

11.銷(xiāo)毀鏈表

五、完整代碼

1.List.h

2.List.c

3.test.c

六、總結(jié)

一、引言

雙鏈表是一種在節(jié)點(diǎn)之間通過(guò)兩個(gè)指針進(jìn)行連接的數(shù)據(jù)結(jié)構(gòu),每個(gè)節(jié)點(diǎn)都有兩個(gè)指針:一個(gè)指向前一個(gè)節(jié)點(diǎn),另一個(gè)指向下一個(gè)節(jié)點(diǎn)。帶頭節(jié)點(diǎn)的雙鏈表在實(shí)際應(yīng)用中非常常見(jiàn),本文將詳細(xì)介紹其實(shí)現(xiàn)方法,并提供完整的 C 語(yǔ)言代碼示例。

二 、鏈表的分類(lèi)

鏈表的結(jié)構(gòu)?常多樣,以下情況組合起來(lái)就有8種(2 x 2 x 2)鏈表結(jié)構(gòu):

1.單向或雙向

單向鏈表:

每個(gè)節(jié)點(diǎn)包含一個(gè)指向下一個(gè)節(jié)點(diǎn)的指針。只能從頭到尾單向遍歷。插入和刪除操作較簡(jiǎn)單,但需要從頭開(kāi)始查找節(jié)點(diǎn)。 雙向鏈表:

每個(gè)節(jié)點(diǎn)包含兩個(gè)指針,一個(gè)指向下一個(gè)節(jié)點(diǎn),一個(gè)指向前一個(gè)節(jié)點(diǎn)??梢詮念^到尾或尾到頭雙向遍歷。插入和刪除操作更靈活,但每個(gè)節(jié)點(diǎn)占用更多內(nèi)存。

2.帶頭或不帶頭?

帶頭節(jié)點(diǎn):

鏈表有一個(gè)額外的頭節(jié)點(diǎn),它不存儲(chǔ)實(shí)際數(shù)據(jù),只作為鏈表的起始點(diǎn)。操作如插入和刪除更簡(jiǎn)單,因?yàn)轭^節(jié)點(diǎn)簡(jiǎn)化了邊界條件處理。 不帶頭節(jié)點(diǎn):

鏈表從第一個(gè)實(shí)際數(shù)據(jù)節(jié)點(diǎn)開(kāi)始,沒(méi)有額外的頭節(jié)點(diǎn)。需要特別處理空鏈表和邊界情況。

3.循環(huán)或不循環(huán)?

循環(huán)鏈表:

鏈表的尾節(jié)點(diǎn)指向頭節(jié)點(diǎn),形成一個(gè)循環(huán)結(jié)構(gòu)。遍歷時(shí)可以從任何節(jié)點(diǎn)開(kāi)始,不會(huì)遇到“末尾”問(wèn)題。 非循環(huán)鏈表:

鏈表的尾節(jié)點(diǎn)指向 NULL,表示鏈表的結(jié)束。遍歷時(shí)需要檢查是否到達(dá)鏈表末尾。

雖然有這么多的鏈表的結(jié)構(gòu),但是我們實(shí)際中最常?還是兩種結(jié)構(gòu):?jiǎn)捂湵砗碗p向帶頭循環(huán)鏈表1. ?頭單向?循環(huán)鏈表:結(jié)構(gòu)簡(jiǎn)單,?般不會(huì)單獨(dú)?來(lái)存數(shù)據(jù)。實(shí)際中更多是作為其他數(shù)據(jù)結(jié) 構(gòu)的?結(jié)構(gòu),如哈希桶、圖的鄰接表等等。另外這種結(jié)構(gòu)在筆試?試中出現(xiàn)很多。 2. 帶頭雙向循環(huán)鏈表:結(jié)構(gòu)最復(fù)雜,?般?在單獨(dú)存儲(chǔ)數(shù)據(jù)。實(shí)際中使?的鏈表數(shù)據(jù)結(jié)構(gòu),都 是帶頭雙向循環(huán)鏈表。另外這個(gè)結(jié)構(gòu)雖然結(jié)構(gòu)復(fù)雜,但是使?代碼實(shí)現(xiàn)以后會(huì)發(fā)現(xiàn)結(jié)構(gòu)會(huì)帶 來(lái)很多優(yōu)勢(shì),實(shí)現(xiàn)反?簡(jiǎn)單了,后?我們代碼實(shí)現(xiàn)了就知道了。

本節(jié)我們所講的雙鏈表即為雙向帶頭循環(huán)鏈表。?

?三、雙鏈表的概念與基本結(jié)構(gòu)

1.概念

雙鏈表簡(jiǎn)介 雙鏈表是一種鏈表變體,每個(gè)節(jié)點(diǎn)都包含三個(gè)部分: 存儲(chǔ)的數(shù)據(jù)。 指向前一個(gè)節(jié)點(diǎn)的指針(prev)。 指向下一個(gè)節(jié)點(diǎn)的指針(next)。 帶頭節(jié)點(diǎn)的雙鏈表有一個(gè)特殊的節(jié)點(diǎn)稱(chēng)為頭節(jié)點(diǎn),它不存儲(chǔ)有效數(shù)據(jù),只是作為鏈表的一個(gè)起始輔助節(jié)點(diǎn)存在。頭節(jié)點(diǎn)的 prev 指針指向自己,next 指針指向鏈表的第一個(gè)有效節(jié)點(diǎn)。

2.基本結(jié)構(gòu)?

雙鏈表的基本結(jié)構(gòu)如下:

typedef struct ListNode

{

DataType data;//數(shù)據(jù)域

struct ListNode* prev;//指針域,指向前一個(gè)節(jié)點(diǎn)

struct ListNode* next;//指針域,指向后一個(gè)節(jié)點(diǎn)

}LN;

三、雙鏈表的常見(jiàn)操作

1.創(chuàng)建節(jié)點(diǎn)

//申請(qǐng)節(jié)點(diǎn)

LN* ListBuyNode(DataType x)

{

LN* node = (LN*)malloc(sizeof(LN));

if (node == NULL)

{

perror("malloc fail!");

exit(1);

}

node->data = x;

node->prev = node->next = node;//前后指針都指向自己,使得鏈表循環(huán)起來(lái)

}

2.初始化?

//初始化

void ListInit(LN** pphead)

{

*pphead = ListBuyNode(-1);//頭節(jié)點(diǎn),隨便給一個(gè)值(用不到)

}

3.頭插

//頭插

void ListPushFront(LN* phead, DataType x)

{

assert(phead);

LN* newnode = ListBuyNode(x);

newnode->next = phead->next;

newnode->prev = phead;

phead->next->prev = newnode;

phead->next = newnode;

//上面兩行代碼位置不能交換

}

4.尾插

//尾插

void ListPushBack(LN* phead, DataType x)

{

assert(phead);

LN* newnode = ListBuyNode(x);

newnode->prev = phead->prev;//新節(jié)點(diǎn)prev指向原來(lái)的尾節(jié)點(diǎn)

newnode->next = phead;//新節(jié)點(diǎn)next指向頭節(jié)點(diǎn)

phead->prev->next = newnode;//原來(lái)的尾節(jié)點(diǎn)next指向newnode

phead->prev = newnode;//頭節(jié)點(diǎn)的prev指向newnode

//上面兩行代碼位置不能交換

}

5.頭刪

//頭刪

void ListPopFront(LN* phead)

{

assert(phead && phead->next != phead);//鏈表必須有效且鏈表不為空

LN* del = phead->next;

del->next->prev = phead;

phead->next = del->next;

//刪除del節(jié)點(diǎn)

free(del);

del = NULL;

}

?

6.尾刪

//尾刪

void ListPopBack(LN* phead)

{

assert(phead&&phead->next!=phead);//鏈表必須有效且鏈表不為空

LN* del = phead->prev;

del->prev->next = phead;

phead->prev = del->prev;

//刪除del節(jié)點(diǎn)

free(del);

del = NULL;

}

7.打印

//打印

void ListPrint(LN* phead)

{

LN* pcur = phead->next;

while (pcur != phead)

{

printf("%d->", pcur->data);

pcur = pcur->next;

}

printf("NULL\n");

}

8.查找

//查找

LN* ListFind(LN* phead, DataType x)

{

LN* pcur = phead->next;

while (pcur != phead)

{

if (pcur->data == x)

{

return pcur;//找到了

}

pcur = pcur->next;

}

return NULL;//沒(méi)有找到

}

9.插入節(jié)點(diǎn)

//插入,pos節(jié)點(diǎn)后插入

void ListInsert(LN* pos, DataType x)

{

assert(pos);

LN* newnode = ListBuyNode(x);

newnode->next = pos->next;

newnode->prev = pos;

pos->next->prev = newnode;

pos->next = newnode;

}

10.刪除節(jié)點(diǎn)

//刪除

void ListErase(LN* pos)//這里不傳二級(jí)指針,是為了保持接口一致性

{

assert(pos);

pos->next->prev = pos->prev;

pos->prev->next = pos->next;

free(pos);

pos = NULL;

}

11.銷(xiāo)毀鏈表

//銷(xiāo)毀鏈表

void ListDestory(LN* phead)

{

assert(phead);

LN* pcur = phead->next;

while (pcur != phead)

{

LN* next = pcur->next;

free(pcur);

pcur = next;

}

free(phead);

phead = NULL;

}

注:

LTErase和LTDestroy參數(shù)理論上要傳一級(jí),因?yàn)槲覀冃枰屝螀⒌母淖冇绊懙綄?shí)參,但是為了保持接口一致性才傳的一級(jí)。傳一級(jí)存在的問(wèn)題是,當(dāng)形參phead置為NULL后,實(shí)參plist不會(huì)被修改為NULL,因此解決辦法是:調(diào)用完方法后手動(dòng)將實(shí)參置為NULL~?

五、完整代碼

1.List.h

該部分放順序表結(jié)構(gòu)定義、函數(shù)的聲明

#pragma once

#include

#include

#include

typedef int DataType;

typedef struct ListNode

{

DataType data;//數(shù)據(jù)域

struct ListNode* prev;//指針域,指向前一個(gè)節(jié)點(diǎn)

struct ListNode* next;//指針域,指向后一個(gè)節(jié)點(diǎn)

}LN;

//初始化

void ListInit(LN** pphead);

//尾插

void ListPushBack(LN*phead,DataType x);

//頭插

void ListPushFront(LN*phead,DataType x);

//打印

void ListPrint(LN* phead);

//尾刪

void ListPopBack(LN* phead);

//頭刪

void ListPopFront(LN* phead);

//查找

LN* ListFind(LN* phead, DataType x);

//插入,pos節(jié)點(diǎn)后插入

void ListInsert(LN* pos, DataType x);

//刪除

void ListErase(LN* pos);

//銷(xiāo)毀鏈表

void ListDestory(LN* phead);

2.List.c

該部分是函數(shù)功能的實(shí)現(xiàn)

#define _CRT_SECURE_NO_WARNINGS

#include"List.h"

//申請(qǐng)節(jié)點(diǎn)

LN* ListBuyNode(DataType x)

{

LN* node = (LN*)malloc(sizeof(LN));

if (node == NULL)

{

perror("malloc fail!");

exit(1);

}

node->data = x;

node->prev = node->next = node;//前后指針都指向自己,使得鏈表循環(huán)起來(lái)

}

//初始化

void ListInit(LN** pphead)

{

*pphead = ListBuyNode(-1);//頭節(jié)點(diǎn),隨便給一個(gè)值(用不到)

}

//尾插

void ListPushBack(LN* phead, DataType x)

{

assert(phead);

LN* newnode = ListBuyNode(x);

newnode->prev = phead->prev;//新節(jié)點(diǎn)prev指向原來(lái)的尾節(jié)點(diǎn)

newnode->next = phead;//新節(jié)點(diǎn)next指向頭節(jié)點(diǎn)

phead->prev->next = newnode;//原來(lái)的尾節(jié)點(diǎn)next指向newnode

phead->prev = newnode;//頭節(jié)點(diǎn)的prev指向newnode

//上面兩行代碼位置不能交換

}

//頭插

void ListPushFront(LN* phead, DataType x)

{

assert(phead);

LN* newnode = ListBuyNode(x);

newnode->next = phead->next;

newnode->prev = phead;

phead->next->prev = newnode;

phead->next = newnode;

//上面兩行代碼位置不能交換

}

//尾刪

void ListPopBack(LN* phead)

{

assert(phead&&phead->next!=phead);//鏈表必須有效且鏈表不為空

LN* del = phead->prev;

del->prev->next = phead;

phead->prev = del->prev;

//刪除del節(jié)點(diǎn)

free(del);

del = NULL;

}

//頭刪

void ListPopFront(LN* phead)

{

assert(phead && phead->next != phead);//鏈表必須有效且鏈表不為空

LN* del = phead->next;

del->next->prev = phead;

phead->next = del->next;

//刪除del節(jié)點(diǎn)

free(del);

del = NULL;

}

//打印

void ListPrint(LN* phead)

{

LN* pcur = phead->next;

while (pcur != phead)

{

printf("%d->", pcur->data);

pcur = pcur->next;

}

printf("NULL\n");

}

//查找

LN* ListFind(LN* phead, DataType x)

{

LN* pcur = phead->next;

while (pcur != phead)

{

if (pcur->data == x)

{

return pcur;//找到了

}

pcur = pcur->next;

}

return NULL;//沒(méi)有找到

}

//插入,pos節(jié)點(diǎn)后插入

void ListInsert(LN* pos, DataType x)

{

assert(pos);

LN* newnode = ListBuyNode(x);

newnode->next = pos->next;

newnode->prev = pos;

pos->next->prev = newnode;

pos->next = newnode;

}

//刪除

void ListErase(LN* pos)//這里不傳二級(jí)指針,是為了保持接口一致性

{

assert(pos);

pos->next->prev = pos->prev;

pos->prev->next = pos->next;

free(pos);

pos = NULL;

}

//銷(xiāo)毀鏈表

void ListDestory(LN* phead)

{

assert(phead);

LN* pcur = phead->next;

while (pcur != phead)

{

LN* next = pcur->next;

free(pcur);

pcur = next;

}

free(phead);

phead = NULL;

}

3.test.c

測(cè)試,函數(shù)的調(diào)用

#define _CRT_SECURE_NO_WARNINGS

#include"List.h"

void test01()

{

LN* plist = NULL;

ListInit(&plist);

/*ListPushBack(plist, 3);

ListPushBack(plist, 2);

ListPushBack(plist, 1);

ListPushBack(plist, 0);*/

ListPushFront(plist, 1);

ListPushFront(plist, 2);

ListPushFront(plist, 3);

ListPushFront(plist, 4);

// ListPopBack(plist);

//ListPopFront(plist);

LN* find = ListFind(plist, 3);

//if (find == NULL)

// printf("沒(méi)找到\n");

//else

// printf("找到了\n");

ListInsert(find, 99);

ListErase(find);

find = NULL;

ListPrint(plist);

ListDestory(plist);

plist = NULL;

}

int main()

{

test01();

return 0;

}

六、總結(jié)

帶頭節(jié)點(diǎn)的雙鏈表在進(jìn)行節(jié)點(diǎn)的插入和刪除操作時(shí)具有較好的靈活性。頭節(jié)點(diǎn)的存在簡(jiǎn)化了鏈表操作的邊界條件,減少了對(duì)空鏈表和鏈表邊界的特殊處理。通過(guò)本文的實(shí)現(xiàn)和示例代碼,你應(yīng)該能掌握雙鏈表的基本操作,并能夠?qū)⑵鋺?yīng)用于實(shí)際的編程任務(wù)中。 希望這個(gè)博客對(duì)你有幫助!如果你有任何問(wèn)題或者需要進(jìn)一步的解釋?zhuān)瑲g迎在評(píng)論區(qū)留言。

柚子快報(bào)激活碼778899分享:數(shù)據(jù)結(jié)構(gòu)--雙鏈表

http://yzkb.51969.com/

文章鏈接

評(píng)論可見(jiàn),查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場(chǎng)。

轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/19525486.html

發(fā)布評(píng)論

您暫未設(shè)置收款碼

請(qǐng)?jiān)谥黝}配置——文章設(shè)置里上傳

掃描二維碼手機(jī)訪問(wèn)

文章目錄