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

【數(shù)據(jù)結(jié)構(gòu)】C語言實現(xiàn)雙向鏈表(帶頭結(jié)點、循環(huán))

這篇具有很好參考價值的文章主要介紹了【數(shù)據(jù)結(jié)構(gòu)】C語言實現(xiàn)雙向鏈表(帶頭結(jié)點、循環(huán))。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。


一、帶頭結(jié)點的循環(huán)雙向鏈表

【數(shù)據(jù)結(jié)構(gòu)】C語言實現(xiàn)雙向鏈表(帶頭結(jié)點、循環(huán))

二、結(jié)點與接口定義

結(jié)點定義:

typedef int ListDataType;
typedef struct LinkedListNode
{
	struct LinkedListNode* next;
	struct LinkedListNode* prev;
	ListDataType data;
}LinkedListNode;

接口定義:

LinkedListNode* LinkedListInit();
void LinkedListPrint(LinkedListNode* phead);

bool LinkedListEmpty(LinkedListNode* phead);
void LinkedListPushBack(LinkedListNode* phead, ListDataType x);
void LinkedListPushFront(LinkedListNode* phead, ListDataType x);
void LinkedListPopBack(LinkedListNode* phead);
void LinkedListPopFront(LinkedListNode* phead);

LinkedListNode* LinkedListFind(LinkedListNode* phead, ListDataType x);

// 在pos之前插入
void LinkedListInsert(LinkedListNode* pos, ListDataType x);
// 刪除pos位置的值
void LinkedListErase(LinkedListNode* pos);

void LinkedListDestroy(LinkedListNode* phead);

三、實現(xiàn)

3.1 申請節(jié)點

我們將申請結(jié)點的代碼封裝成函數(shù),方便后續(xù)使用

LinkedListNode* CreateLinkedListNode(ListDataType x)
{
	LinkedListNode* newnode = (LinkedListNode*)malloc(sizeof(LinkedListNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return NULL;
	}

	newnode->data = x;
	newnode->next = NULL;
	newnode->prev = NULL;
	return newnode;
}

3.2 初始化

由于是帶頭結(jié)點的雙向鏈表,因此在使用鏈表前,我們需要對鏈表進行初始化。

LinkedListNode* LinkedListInit()
{
	LinkedListNode* phead = CreateLinkedListNode(230510);
	phead->next = phead;
	phead->prev = phead;

	return phead;
}

3.3 打印

遍歷鏈表,值得說的是,帶頭結(jié)點的雙向鏈表的循環(huán)結(jié)束條件是 cur != phead

void LinkedListPrint(LinkedListNode* phead)
{
	assert(phead);

	LinkedListNode* cur = phead->next;

	printf("guard<->");
	while (cur != phead)
	{
		printf("%d<->", cur->data);
		cur = cur->next;
	}
	printf("\n");
}

3.4 尾插

尾插時,需要先找到尾結(jié)點,然后將新結(jié)點插入到尾結(jié)點后面。

void LinkedListPushBack(LinkedListNode* phead, ListDataType x)
{
	assert(phead);

	// 1.找到尾結(jié)點
	LinkedListNode* tail = phead->prev;

	// 2.插入到尾結(jié)點后面
	LinkedListNode* newnode = CreateLinkedListNode(x);
	tail->next = newnode;
	newnode->prev = tail;
	newnode->next = phead;
	phead->prev = newnode;
}

3.5 頭插

第一種寫法,要注意現(xiàn)將newnode后面的結(jié)點進行鏈接,然后再講newnode鏈接到phead后面。

void LinkedListPushFront(LinkedListNode* phead, ListDataType x)
{
	assert(phead);

	LinkedListNode* newnode = CreateLinkedListNode(x);
	// 與原來的第一個數(shù)據(jù)結(jié)點鏈接
	newnode->next = phead->next;
	phead->next->prev = newnode; // newnode->next->prev = newnode;

	// newnode變?yōu)樾碌牡谝粋€數(shù)據(jù)結(jié)點
	phead->next = newnode;
	newnode->prev = phead;
}

第二種寫法(推薦寫法),我們使用變量記錄phead的next,記為first,這樣newnode插入到phead和first之間,這樣邏輯比較清楚。

void LinkedListPushFront(LinkedListNode* phead, ListDataType x)
{
	assert(phead);

	LinkedListNode* newnode = CreateLinkedListNode(x);
	// 用變量記錄第一個結(jié)點
	LinkedListNode* first = phead->next;

	// 與原來的第一個數(shù)據(jù)結(jié)點鏈接
	newnode->next = first;
	first->prev = newnode; 

	// newnode變?yōu)樾碌牡谝粋€數(shù)據(jù)結(jié)點
	phead->next = newnode;
	newnode->prev = phead;
}

3.6 尾刪

phead的prev是尾tail,tail的prev是tailPrev。

void LinkedListPopBack(LinkedListNode* phead)
{
	assert(phead);

	LinkedListNode* tail = phead->prev;
	LinkedListNode* tailPrev = tail->prev;

	free(tail);
	tailPrev->next = phead;
	phead->prev = tailPrev;
}

上面代碼的問題是鏈表為空的情況報錯,于是我們在該函數(shù)內(nèi)部對空鏈表進行斷言:

void LinkedListPopBack(LinkedListNode* phead)
{
	assert(phead);
	assert(!LinkedListEmpty(phead)); // 刪除時鏈表不能為空

	LinkedListNode* tail = phead->prev;
	LinkedListNode* tailPrev = tail->prev;

	free(tail);
	tailPrev->next = phead;
	phead->prev = tailPrev;
}

3.7 判斷鏈表為空斷言

判斷鏈表為空邏輯:

bool LinkedListEmpty(LinkedListNode* phead)
{
	assert(phead);

	return phead->next == phead;
}

使用鏈表為空的斷言:

assert(!LinkedListEmpty(phead)); // 鏈表為空時error

3.8 頭刪

頭刪時需要將第一個結(jié)點刪除,很容易便想到以下代碼:

void LinkedListPopFront(LinkedListNode* phead)
{
	assert(phead);
	assert(!LinkedListEmpty(phead)); // 刪除時鏈表不能為空

	LinkedListNode* next = phead->next;

	phead->next = next->next;
	phead->next->prev = phead; // next->next->prev = phead;
	free(next); 
}

為了提高可讀性,推薦使用以下代碼,定義first和second兩個變量指向第一個和第二個:

void LinkedListPopFront(LinkedListNode* phead)
{
	assert(phead);
	assert(!LinkedListEmpty(phead)); // 刪除時鏈表不能為空

	LinkedListNode* first = phead->next;
	LinkedListNode* second = first->next;

	phead->next = second;
	second->prev = phead;
	free(first);
}

3.9 查找find

查找的本質(zhì)就是遍歷鏈表

LinkedListNode* LinkedListFind(LinkedListNode* phead, ListDataType x)
{
	assert(phead);
	
	LinkedListNode* cur = phead->next;
	while (cur != phead)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

3.10 插入insert-在pos之前插入

pos的來源一般是find的結(jié)果

void LinkedListInsert(LinkedListNode* pos, ListDataType x)
{
	assert(pos);

	LinkedListNode* prev = pos->prev;
	LinkedListNode* newnode = CreateLinkedListNode(x);

	// prev newnode pos
	prev->next = newnode;
	newnode->prev = prev;
	newnode->next = pos;
	pos->prev = newnode;
}

3.11 頭插尾插復(fù)用insert

有了上面的insert在任意位置插入,我們可以修改尾插代碼:

void LinkedListPushBack(LinkedListNode* phead, ListDataType x)
{
	assert(phead);

	// 在phead之前插入,也就是尾插
	LinkedListInsert(phead, x);
}

同理也可以修改頭插代碼:

void LinkedListPushFront(LinkedListNode* phead, ListDataType x)
{
	assert(phead);

	LinkedListInsert(phead->next, x);
}

3.12 刪除erase-刪除pos位置

同insert一樣,pos也應(yīng)該是調(diào)用者通過find返回的結(jié)果。

void LinkedListErase(LinkedListNode* pos)
{
	assert(pos);

	LinkedListNode* posPrev = pos->prev;
	LinkedListNode* posNext = pos->next;

	posPrev->next = posNext;
	posNext->prev = posPrev;
	free(pos);
}

3.13 頭刪尾刪復(fù)用erase

有了上面的erase在任意位置刪除,我們可以修改尾刪的代碼:

void LinkedListPopBack(LinkedListNode* phead)
{
	assert(phead);
	assert(!LinkedListEmpty(phead));
	LinkedListErase(phead->prev);
}

同理也可以修改頭刪的代碼:

void LinkedListPopFront(LinkedListNode* phead)
{
	assert(phead);
	assert(!LinkedListEmpty(phead));

	LinkedListErase(phead->next);
}

3.14 銷毀destroy

記得釋放頭結(jié)點phead:

void LinkedListDestroy(LinkedListNode* phead)
{
	assert(phead);

	LinkedListNode* cur = phead->next;
	while (cur != phead)
	{
		LinkedListNode* next = cur->next;
		free(cur);
		cur = next;
	}

	free(phead);
}

源碼

gitee-LinkedList

總結(jié)

帶頭結(jié)點、雙向、循環(huán)鏈表的實現(xiàn)都非常的簡單,需要注意判空條件與遍歷終止的條件。

在代碼寫法上,對于某個節(jié)點的前一個或后一個的問題,我們最好分別使用變量去記錄,這樣代碼的邏輯更清晰,可讀性更高。例如尾插時的tail,尾刪時的tail和tailPrev,以及頭刪時的first與second,erase中的posPrev與posNext,這些變量的使用,提高了代碼的可讀性。文章來源地址http://www.zghlxwxcb.cn/news/detail-438544.html

到了這里,關(guān)于【數(shù)據(jù)結(jié)構(gòu)】C語言實現(xiàn)雙向鏈表(帶頭結(jié)點、循環(huán))的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

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

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

相關(guān)文章

  • 數(shù)據(jù)結(jié)構(gòu):鏈表基礎(chǔ)OJ練習(xí)+帶頭雙向循環(huán)鏈表的實現(xiàn)

    數(shù)據(jù)結(jié)構(gòu):鏈表基礎(chǔ)OJ練習(xí)+帶頭雙向循環(huán)鏈表的實現(xiàn)

    目錄 一.leetcode劍指 Offer II 027.?回文鏈表 1.問題描述 2.問題分析與求解 (1) 快慢指針法定位鏈表的中間節(jié)點 (2)?將鏈表后半部分進行反轉(zhuǎn) 附:遞歸法反轉(zhuǎn)鏈表 (3)?雙指針法判斷鏈表是否回文 二.帶頭雙向循環(huán)鏈表的實現(xiàn) 1.頭文件 2.節(jié)點內(nèi)存申請接口和鏈表初始化接口 3.鏈表的打

    2024年02月02日
    瀏覽(30)
  • 玩轉(zhuǎn)帶頭雙向鏈表——【數(shù)據(jù)結(jié)構(gòu)】

    玩轉(zhuǎn)帶頭雙向鏈表——【數(shù)據(jù)結(jié)構(gòu)】

    W...Y的主頁 今天我們接著來說數(shù)據(jù)結(jié)構(gòu)——帶頭雙向鏈表 目錄 帶頭雙向鏈表的實現(xiàn) 結(jié)構(gòu)體的創(chuàng)建 初始化兵創(chuàng)建哨兵節(jié)點 釋放鏈表所以內(nèi)容? 打印鏈表函數(shù) 尾插 尾刪 頭插 ?編輯 頭刪 計數(shù)函數(shù)實現(xiàn) 查找數(shù)據(jù)相應(yīng)位置函數(shù) 在pos位置之前插入? 在pos位置刪除? 順序表與鏈表的

    2024年02月14日
    瀏覽(21)
  • 數(shù)據(jù)結(jié)構(gòu)之帶頭雙向鏈表(易學(xué)版)

    數(shù)據(jù)結(jié)構(gòu)之帶頭雙向鏈表(易學(xué)版)

    目錄 1.問題引入 2.結(jié)構(gòu)實現(xiàn) 2.3.1接口實現(xiàn) 2.3.2函數(shù)實現(xiàn) 3.總結(jié) ,又和大家見面了,今天要給大家分享的是雙鏈表的知識,跟著我的腳步,包學(xué)包會哦~ 規(guī)矩不亂,先贊后看! ps:(孫權(quán)勸學(xué)) 前期學(xué)習(xí)了單鏈表,我們嘗到了它的甜頭,但是容易越界訪問這一個問題也是時有出

    2024年03月22日
    瀏覽(18)
  • 【數(shù)據(jù)結(jié)構(gòu) -- C語言】 雙向帶頭循環(huán)鏈表的實現(xiàn)

    【數(shù)據(jù)結(jié)構(gòu) -- C語言】 雙向帶頭循環(huán)鏈表的實現(xiàn)

    目錄 1、雙向帶頭循環(huán)鏈表的介紹 2、雙向帶頭循環(huán)鏈表的接口 3、接口實現(xiàn) 3.1 開辟結(jié)點 3.2 創(chuàng)建返回鏈表的頭結(jié)點 3.3 判斷鏈表是否為空 3.4 打印 3.5 雙向鏈表查找 3.6 雙向鏈表在pos的前面進行插入 3.6.1 頭插 3.6.2 尾插 3.6.3 更新頭插、尾插寫法 3.7 雙向鏈表刪除pos位置的節(jié)點

    2024年02月09日
    瀏覽(88)
  • 數(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日
    瀏覽(20)
  • 數(shù)據(jù)結(jié)構(gòu)入門(C語言版)線性表帶頭雙向循環(huán)鏈表接口實現(xiàn)

    數(shù)據(jù)結(jié)構(gòu)入門(C語言版)線性表帶頭雙向循環(huán)鏈表接口實現(xiàn)

    在上一篇博客我們講述了鏈表的概念和結(jié)構(gòu),還實現(xiàn)了無頭單向非循環(huán)鏈表接口寫法,那么這一章節(jié),我們來實現(xiàn)另一種常用的鏈表組成結(jié)構(gòu)——帶頭雙向循環(huán)鏈表。 如果對前面的鏈表基本概念還是不了解,可以看作者的上一篇博客: 線性表中鏈表介紹及無頭單向非循環(huán)鏈

    2023年04月12日
    瀏覽(19)
  • 【數(shù)據(jù)結(jié)構(gòu)】鏈表:帶頭雙向循環(huán)鏈表的增刪查改

    【數(shù)據(jù)結(jié)構(gòu)】鏈表:帶頭雙向循環(huán)鏈表的增刪查改

    本篇要分享的內(nèi)容是帶頭雙向鏈表,以下為本片目錄 目錄 一、鏈表的所有結(jié)構(gòu) 二、帶頭雙向鏈表 2.1尾部插入 2.2哨兵位的初始化 2.3頭部插入 2.4 打印鏈表 2.5尾部刪除 2.6頭部刪除 ?2.7查找結(jié)點 2.8任意位置插入 2.9任意位置刪除? 在剛開始接觸鏈表的時候,我們所學(xué)僅僅所學(xué)的

    2024年02月05日
    瀏覽(28)
  • 追夢之旅【數(shù)據(jù)結(jié)構(gòu)篇】——詳解C語言動態(tài)實現(xiàn)帶頭結(jié)點的雙向循環(huán)鏈表結(jié)構(gòu)

    追夢之旅【數(shù)據(jù)結(jié)構(gòu)篇】——詳解C語言動態(tài)實現(xiàn)帶頭結(jié)點的雙向循環(huán)鏈表結(jié)構(gòu)

    ? ? ??博客昵稱:博客小夢 ??最喜歡的座右銘:全神貫注的上吧!??! ??作者簡介:一名熱愛C/C++,算法等技術(shù)、喜愛運動、熱愛K歌、敢于追夢的小博主! ??博主小留言:哈嘍! ??各位CSDN的uu們,我是你的博客好友小夢,希望我的文章可以給您帶來一定的幫助,話不

    2024年01月17日
    瀏覽(107)
  • 雙向鏈表--C語言實現(xiàn)數(shù)據(jù)結(jié)構(gòu)

    雙向鏈表--C語言實現(xiàn)數(shù)據(jù)結(jié)構(gòu)

    本期帶大家一起用C語言實現(xiàn)雙向鏈表?????? 鏈表是一種物理存儲單元上非連續(xù)、非順序的存儲結(jié)構(gòu),數(shù)據(jù)元素的邏輯順序是通過鏈表中的指針鏈接次序?qū)崿F(xiàn)的;簡單來說,線性表的鏈式存儲結(jié)構(gòu)生成的表,稱作“鏈表”。 每個元素本身由兩部分組成: 1、本身的信息,稱

    2024年02月04日
    瀏覽(29)
  • 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計題目——鏈表綜合算法設(shè)計、帶頭雙向循環(huán)鏈表、插入、顯示、刪除、修改、排序

    數(shù)據(jù)結(jié)構(gòu)課程設(shè)計題目——鏈表綜合算法設(shè)計、帶頭雙向循環(huán)鏈表、插入、顯示、刪除、修改、排序

    ??課程設(shè)計題目1–鏈表綜合算法設(shè)計 ??一、設(shè)計內(nèi)容 ??已知簡單的人事信息系統(tǒng)中職工記錄包含職工編號(no)、職工姓名(name)、部門名稱(depname)、職稱(title)和工資數(shù)(salary)等信息(可以增加其他信息),設(shè)計并完成一個簡單的人事信息管理系統(tǒng),要求完成但不

    2024年02月08日
    瀏覽(26)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包