国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

數(shù)據(jù)結(jié)構(gòu)學(xué)習(xí)分享之雙向鏈表詳解

這篇具有很好參考價(jià)值的文章主要介紹了數(shù)據(jù)結(jié)構(gòu)學(xué)習(xí)分享之雙向鏈表詳解。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。


1.前言

? ? ??博主CSDN:杭電碼農(nóng)-NEO????????
?
? ? ?專欄分類:數(shù)據(jù)結(jié)構(gòu)學(xué)習(xí)分享(持續(xù)更新中??)???????
?

? ? 我們上一期說到,兩鏈表中有兩個(gè)最常用的結(jié)構(gòu),一個(gè)是最簡(jiǎn)單的無頭不循環(huán)單向鏈表,還有一個(gè)就是 結(jié)構(gòu)相對(duì)比較復(fù)雜的帶頭雙向循環(huán)鏈表 ,我們這一章節(jié)就來分享雙向帶頭循環(huán)鏈表的具體實(shí)現(xiàn):

要看所有代碼的朋友:? ? ? ? ?? 我的碼云放在了最后 ??
數(shù)據(jù)結(jié)構(gòu)學(xué)習(xí)分享之雙向鏈表詳解



2. 結(jié)構(gòu)分析

與我們上一章講的單鏈表不同,這里雙向帶頭循環(huán)鏈表的結(jié)構(gòu)要復(fù)雜一點(diǎn),主要需要注意這幾個(gè)點(diǎn):

  • 定義結(jié)構(gòu)體時(shí),單鏈表只需要定義一個(gè)指針next,雙鏈表需要定義額外一個(gè)指針:prev用來指向上一個(gè)節(jié)點(diǎn)

  • 帶頭(帶哨兵位)的鏈表在初始化時(shí)就要給哨兵位開辟一份空間,并且哨兵位不存儲(chǔ)數(shù)據(jù),第一個(gè)節(jié)點(diǎn)要鏈接在哨兵位的下一個(gè)位置

  • 循環(huán)的鏈表的尾節(jié)點(diǎn)的next不能指向NULL,要指向第一個(gè)節(jié)點(diǎn),形成循環(huán)結(jié)構(gòu)

  • 我們?cè)谶M(jìn)行插入刪除的時(shí)候可以不傳二級(jí)指針!因?yàn)槲覀儞碛辛松诒蛔鳛槲覀冎羔樦赶虻牡谝粋€(gè)位置,并且哨兵位是不會(huì)改變的!

  • 不循環(huán)的鏈表判斷尾節(jié)點(diǎn)是cur->next == NULL時(shí),然而循環(huán)的帶頭鏈表判斷尾節(jié)點(diǎn)是cur->next==head時(shí),這里的head指的是哨兵位


3. 雙鏈表的實(shí)現(xiàn)

單鏈表我們使用的名字是SList,意為single list 就是單個(gè)的意思,這里我們直接用List表示雙鏈表

3.1 初始化結(jié)構(gòu)

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<malloc.h>
typedef int LTDateType;//隨時(shí)可以改變類型

typedef struct ListNode
{
	LTDateType data;
	struct ListNode* prev;//指向上一個(gè)節(jié)點(diǎn)
	struct ListNode* next;//指向下一個(gè)節(jié)點(diǎn)
}LTNode;//簡(jiǎn)化名字

3.2 初始化函數(shù)

在我們寫初始化函數(shù)之前我們要先明白一點(diǎn),那就是當(dāng)鏈表為空時(shí),我們哨兵位的next和prev都指向自己本身!

數(shù)據(jù)結(jié)構(gòu)學(xué)習(xí)分享之雙向鏈表詳解


LTNode* ListInit()
{
	LTNode* phead = (LTNode*)malloc(sizeof(LTNode));//為哨兵位開辟一個(gè)節(jié)點(diǎn)
	phead->next = phead;
	phead->prev = phead;
	return phead;//將phead返回后,在test.c文件中賦值給結(jié)構(gòu)體指針
}
void TestList1()
{
	LTNode* plist = ListInit();//plist里面存儲(chǔ)一個(gè)哨兵位
}

3.3 尾插函數(shù)

我們說存儲(chǔ)數(shù)據(jù)的結(jié)構(gòu)都離不開增刪查改,這里我們定義的雙向帶頭循環(huán)鏈表進(jìn)行增刪查改是很簡(jiǎn)單的

void ListPushBack(LTNode* phead, LTDateType x)//尾插
{
	assert(phead);
	LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));//為插入的數(shù)據(jù)開辟空間
	if (newnode == NULL)//這個(gè)if語句是為了判斷我們的動(dòng)態(tài)開辟空間有沒有失敗
	{
		printf("fail");
		exit(-1);
	}
	newnode->data = x;//將數(shù)據(jù)x給上
	LTNode* tail = phead->prev;//這里也可以不定義tail,直接用phead->prev表示尾
    tail->next = newnode;//尾節(jié)點(diǎn)與新節(jié)點(diǎn)相連
	newnode->prev = tail;//新的尾節(jié)點(diǎn)的prev與舊的尾相連
	newnode->next = phead;//新的尾節(jié)點(diǎn)與頭相連形成循環(huán)
	phead->prev = newnode;
}

我們發(fā)現(xiàn)當(dāng)我們定義鏈表結(jié)構(gòu)為雙向帶頭循環(huán)鏈表時(shí),插入數(shù)據(jù)是很方便的,只需要判斷好鏈接關(guān)系就可以了,而我們之前的單鏈表還需要判斷鏈表為空的情況,這種情況要拿出來特殊處理,但是這個(gè)地方當(dāng)鏈表為空時(shí)也是沒有問題的!

數(shù)據(jù)結(jié)構(gòu)學(xué)習(xí)分享之雙向鏈表詳解


3.4 尾刪函數(shù)

我們有了之前的基礎(chǔ)后,直接上代碼!

void ListPopBack(LTNode* phead)
{
	assert(phead);
	assert(phead->next != phead);//不能把哨兵為給刪除了
	LTNode* tail = phead->prev;
	LTNode* prev = tail->prev;//后面就處理鏈接關(guān)系
	free(tail);
	tail = NULL;
	prev->next = phead;
	phead->prev = prev;
}

值得注意的是,這里的assert(phead->next!=phead)是當(dāng)我們的phead->next等于自己本身時(shí),代表我們鏈表中已經(jīng)沒有數(shù)據(jù)了,只剩下一個(gè)哨兵位了.這時(shí)需要斷言報(bào)錯(cuò) ??????


3.5 頭插函數(shù)

void ListPushFront(LTNode* phead, LTDateType x)
{
	assert(phead);
	LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));//只要是插入數(shù)據(jù)就需要開辟空間
	newnode->data = x;
	LTNode* next = phead->next;//頭插相當(dāng)于就是插入在哨兵位后面
	phead->next = newnode;//注意鏈接關(guān)系別寫漏就沒問題
	newnode->prev = phead;
	newnode->next = next;
	next->prev = newnode;
}

同樣的,當(dāng)我們鏈表中沒有數(shù)據(jù)時(shí),這時(shí)的頭插也是沒有問題的,這里我就不做過多說明


3.6 頭刪函數(shù)

void ListPopFront(LTNode* phead)
{
	assert(phead);
	assert(phead->next != phead);
	LTNode* next = phead->next;
	phead->next = next->next;
	next->next->prev = phead;
	free(next);
	next = NULL;
}

頭刪和尾刪一樣,不能把哨兵位一起刪了,并且需要注意一點(diǎn),我們的free不能太早使用,不然我們就找不到我們next的next和next的prev了,所以我們要把所有鏈接關(guān)系全部修改完之后,才能把next的空間給釋放掉


3.7 銷毀鏈表

void ListDestroy(LTNode* phead)
{
	assert(phead);
	LTNode* cur = phead->next;
	while (cur!=phead)//釋放掉所有的數(shù)據(jù)空間
	{
		LTNode* next = cur->next;//這里需要定義一個(gè)next指針,因?yàn)槲覀儼裞ur給釋放掉后就找不到cur->next的了
		free(cur);
		cur = next;
	}
	free(phead);//最后將哨兵位也釋放掉,然后置空
	phead = NULL;
}

3.8 其他函數(shù)

這里我給出幾個(gè)除了頭插頭刪,尾插尾刪的函數(shù).

  • Find函數(shù):返回與x值相同的節(jié)點(diǎn)
LTNode* ListFind(LTNode* phead, LTDateType x)
{
	assert(phead);
	LTNode* cur = phead->next;
	while ( cur != phead)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

  • Insert函數(shù):在pos位置之前插入數(shù)據(jù)
void ListInsert(LTNode* pos, LTDateType x)
{
	assert(pos);
	LTNode* prev = pos->prev;
	LTNode* next = pos->next;
	LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
	newnode->data = x;
	newnode->prev = prev;
	newnode->next = pos;
	pos->prev = newnode;
	prev->next = newnode;
}

  • Erase函數(shù):刪除pos位置的節(jié)點(diǎn)
void ListErase(LTNode* pos)
{
	assert(pos);
	LTNode* prev = pos->prev;
	LTNode* next = pos->next;
	prev->next = next;
	next->prev = prev;
    free(pos);
	pos = NULL;
}


4. 緩存利用率

我們上一章總結(jié)順序表和鏈表的區(qū)別的時(shí)候提到:順序表的緩存利用率高,鏈表的緩存利用率低,那么到底什么是緩存利用率?這里我給大家大致提一下:我們的計(jì)算器存在很多存儲(chǔ)方式:

數(shù)據(jù)結(jié)構(gòu)學(xué)習(xí)分享之雙向鏈表詳解

我們?cè)跀?shù)組中開辟空間和在鏈表上開辟空間時(shí),這種緩存的命中是不一樣的,有興趣了解的朋友具體的細(xì)節(jié)可以參考這篇文章CPU緩存知識(shí).


5. 總結(jié)

我們關(guān)于鏈表的知識(shí)的分享就要告一段落了,但是鏈表這一章節(jié)雖然只有兩次分享,但是它在諸多面試題中考察的概率是很高的,特別是單鏈表,因?yàn)槲覀冎绬捂湵硎怯泻芏嗳毕莸?所以在校招和很多OJ題中,單鏈表考察的地方非常之多,建議多刷刷題找找思路,我的專欄單鏈表OJ中也總結(jié)了不少OJ題的思路以及衍生問題,有興趣的朋友可以來指導(dǎo)指導(dǎo).

?? 我的碼云:gitee-杭電碼農(nóng)-NEO??文章來源地址http://www.zghlxwxcb.cn/news/detail-439312.html

?? 下期預(yù)告:棧的實(shí)現(xiàn) ??

到了這里,關(guān)于數(shù)據(jù)結(jié)構(gòu)學(xué)習(xí)分享之雙向鏈表詳解的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 數(shù)據(jù)結(jié)構(gòu)之雙向鏈表詳解

    數(shù)據(jù)結(jié)構(gòu)之雙向鏈表詳解

    ??博主CSDN主頁(yè):小源_?? ???個(gè)人專欄:《數(shù)據(jù)結(jié)構(gòu)》??? ??努力追逐大佬們的步伐~ 上一篇文章中我們重點(diǎn)講解了無頭單向非循環(huán)鏈表的模擬實(shí)現(xiàn),現(xiàn)在我們來講解LinkedList(無頭雙向鏈表實(shí)現(xiàn) )的模擬實(shí)現(xiàn)。 本章重點(diǎn): 本文著重講解了LinkedList(無頭雙向單鏈表)的實(shí)現(xiàn)

    2024年02月04日
    瀏覽(20)
  • 數(shù)據(jù)結(jié)構(gòu) - 鏈表詳解(二)—— 帶頭雙向循環(huán)鏈表

    數(shù)據(jù)結(jié)構(gòu) - 鏈表詳解(二)—— 帶頭雙向循環(huán)鏈表

    鏈表的結(jié)構(gòu)一共有 八種 :帶頭單向循環(huán)鏈表、帶頭單向非循環(huán)鏈表、帶頭雙向循環(huán)鏈表、帶頭雙向非循環(huán)鏈表、無頭單向循環(huán)鏈表、無頭單向非循環(huán)鏈表、無頭雙向循環(huán)鏈表、無頭雙向非循環(huán)鏈表。 今天我們來詳解帶頭雙向循環(huán)鏈表 帶頭雙向循環(huán)鏈表是一種數(shù)據(jù)結(jié)構(gòu),它通

    2024年04月26日
    瀏覽(21)
  • 數(shù)據(jù)結(jié)構(gòu):線性表之-循環(huán)雙向鏈表(萬字詳解)

    數(shù)據(jù)結(jié)構(gòu):線性表之-循環(huán)雙向鏈表(萬字詳解)

    目錄 基本概念 1,什么是雙向鏈表 2,與單向鏈表的區(qū)別 雙向鏈表詳解 功能展示: 1. 定義鏈表 2,創(chuàng)建雙向鏈表 3,初始化鏈表 4,尾插 5,頭插 6,尾刪 判斷鏈表是否被刪空 尾刪代碼 7,頭刪 8,pos位置之前插入 優(yōu)化后的頭插 優(yōu)化后的尾插 9,刪除pos位置的節(jié)點(diǎn) 優(yōu)化后的尾刪 優(yōu)

    2024年02月09日
    瀏覽(23)
  • 【數(shù)據(jù)結(jié)構(gòu)與算法】4、雙向鏈表(學(xué)習(xí) jdk 的 LinkedList 部分源碼)

    【數(shù)據(jù)結(jié)構(gòu)與算法】4、雙向鏈表(學(xué)習(xí) jdk 的 LinkedList 部分源碼)

    ?? 單鏈表的節(jié)點(diǎn)中只有一個(gè) next 指針引用著下一個(gè)節(jié)點(diǎn)的地址 ?? 當(dāng)要獲取單鏈表中的最后一個(gè)元素的時(shí)候,需要從頭節(jié)點(diǎn)開始遍歷到最后 ?? 單鏈表一開始的時(shí)候有 first 頭指針引用著頭節(jié)點(diǎn)的地址 ?? 雙向鏈表可以提升鏈表的綜合性能 ?? 雙向鏈表的節(jié)點(diǎn)中有 prev 指針引

    2024年02月12日
    瀏覽(22)
  • 數(shù)據(jù)結(jié)構(gòu):圖文詳解雙向鏈表的各種操作(頭插法,尾插法,任意位置插入,查詢節(jié)點(diǎn),刪除節(jié)點(diǎn),求鏈表的長(zhǎng)度... ...)

    數(shù)據(jù)結(jié)構(gòu):圖文詳解雙向鏈表的各種操作(頭插法,尾插法,任意位置插入,查詢節(jié)點(diǎn),刪除節(jié)點(diǎn),求鏈表的長(zhǎng)度... ...)

    目錄 一.雙向鏈表的概念 二.雙向鏈表的數(shù)據(jù)結(jié)構(gòu) 三.雙向鏈表的實(shí)現(xiàn) 節(jié)點(diǎn)的插入 頭插法 尾插法 任意位置插入 節(jié)點(diǎn)的刪除 刪除鏈表中第一次出現(xiàn)的目標(biāo)節(jié)點(diǎn) 刪除鏈表中所有與相同的節(jié)點(diǎn) 節(jié)點(diǎn)的查找 鏈表的清空 鏈表的長(zhǎng)度 四.模擬實(shí)現(xiàn)鏈表的完整代碼 前言: 在上一

    2024年02月05日
    瀏覽(29)
  • 數(shù)據(jù)結(jié)構(gòu)-鏈表結(jié)構(gòu)-雙向鏈表

    數(shù)據(jù)結(jié)構(gòu)-鏈表結(jié)構(gòu)-雙向鏈表

    雙向鏈表也叫雙鏈表,與單向鏈表不同的是,每一個(gè)節(jié)點(diǎn)有三個(gè)區(qū)域組成:兩個(gè)指針域,一個(gè)數(shù)據(jù)域 前一個(gè)指針域:存儲(chǔ)前驅(qū)節(jié)點(diǎn)的內(nèi)存地址 后一個(gè)指針域:存儲(chǔ)后繼節(jié)點(diǎn)的內(nèi)存地址 數(shù)據(jù)域:存儲(chǔ)節(jié)點(diǎn)數(shù)據(jù) 以下就是雙向鏈表的最基本單位 節(jié)點(diǎn)的前指針域指向前驅(qū),后指針

    2024年02月04日
    瀏覽(31)
  • 青島大學(xué)_王卓老師【數(shù)據(jù)結(jié)構(gòu)與算法】Week04_04_雙向鏈表的插入_學(xué)習(xí)筆記

    青島大學(xué)_王卓老師【數(shù)據(jù)結(jié)構(gòu)與算法】Week04_04_雙向鏈表的插入_學(xué)習(xí)筆記

    本文是個(gè)人學(xué)習(xí)筆記,素材來自青島大學(xué)王卓老師的教學(xué)視頻。 一方面用于學(xué)習(xí)記錄與分享,另一方面是想讓更多的人看到這么好的《數(shù)據(jù)結(jié)構(gòu)與算法》的學(xué)習(xí)視頻。 如有侵權(quán),請(qǐng)留言作刪文處理。 課程視頻鏈接: 數(shù)據(jù)結(jié)構(gòu)與算法基礎(chǔ)–第04周04–2.5.4雙向鏈表2–雙向鏈表

    2024年02月12日
    瀏覽(22)
  • 【數(shù)據(jù)結(jié)構(gòu)】雙向奔赴的愛戀 --- 雙向鏈表

    【數(shù)據(jù)結(jié)構(gòu)】雙向奔赴的愛戀 --- 雙向鏈表

    關(guān)注小莊 頓頓解饞????? 引言:上回我們講解了單鏈表(單向不循環(huán)不帶頭鏈表),我們可以發(fā)現(xiàn)他是存在一定缺陷的,比如尾刪的時(shí)候需要遍歷一遍鏈表,這會(huì)大大降低我們的性能,再比如對(duì)于鏈表中的一個(gè)結(jié)點(diǎn)我們是無法直接訪問它的上一個(gè)結(jié)點(diǎn),那有什么解決方法呢

    2024年04月08日
    瀏覽(27)
  • 數(shù)據(jù)結(jié)構(gòu)—雙向鏈表

    數(shù)據(jù)結(jié)構(gòu)—雙向鏈表

    目錄 1.? 鏈表的種類 2.? 最實(shí)用的兩種鏈表類型 3.? 實(shí)現(xiàn)雙向帶頭循環(huán)鏈表 ? ? ? ? ? ? ? ? ? 3.1 創(chuàng)建頭節(jié)點(diǎn) ????????3.2 實(shí)現(xiàn)雙向循環(huán)功能—返回頭指針 ????????3.3? 尾插?? ????????3.4 頭插 ????????3.5 尾刪 ????????3.6 頭刪 4.? 實(shí)現(xiàn)兩個(gè)重要接口函數(shù) ?

    2023年04月23日
    瀏覽(28)
  • 數(shù)據(jù)結(jié)構(gòu) - 雙向鏈表

    數(shù)據(jù)結(jié)構(gòu) - 雙向鏈表

    文章目錄 目錄 文章目錄 前言 一、什么是雙向鏈表? 雙向鏈表有什么優(yōu)勢(shì)? 二、雙向鏈表的設(shè)計(jì)和實(shí)現(xiàn) 1.設(shè)計(jì)思想 尾增 : 在鏈表的末尾添加新的元素 ?頭插 : 在鏈表頭部插入節(jié)點(diǎn) ?刪除 : 根據(jù)val的值刪除節(jié)點(diǎn) ?查找 : 根據(jù)索引的值查找并返回節(jié)點(diǎn) 總結(jié) 大家好,今天給大家講解

    2024年02月09日
    瀏覽(27)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包