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

【數(shù)據(jù)結(jié)構(gòu)】鏈表的分類和雙向鏈表

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

本篇是基于上篇單鏈表所作,推薦與上篇配合閱讀,效果更加

http://t.csdnimg.cn/UhXEj

1.鏈表的分類

鏈表的結(jié)構(gòu)非常多樣,以下情況組合起來就有8種(2 x 2 x 2)鏈表結(jié)構(gòu):
【數(shù)據(jù)結(jié)構(gòu)】鏈表的分類和雙向鏈表,鏈表,數(shù)據(jù)結(jié)構(gòu)我們一般叫這個頭為哨兵位
我們上回講的單鏈表就是不帶頭單項不循環(huán)鏈表。
今天我們要講帶頭雙向循環(huán)的鏈表。
不過在次之前容我先為大家畫一畫8種鏈表結(jié)構(gòu):

1.帶頭單向循環(huán)鏈表:

【數(shù)據(jù)結(jié)構(gòu)】鏈表的分類和雙向鏈表,鏈表,數(shù)據(jù)結(jié)構(gòu)

2.帶頭單向不循環(huán)鏈表

【數(shù)據(jù)結(jié)構(gòu)】鏈表的分類和雙向鏈表,鏈表,數(shù)據(jù)結(jié)構(gòu)

3.帶頭雙向循環(huán)鏈表

【數(shù)據(jù)結(jié)構(gòu)】鏈表的分類和雙向鏈表,鏈表,數(shù)據(jù)結(jié)構(gòu)

4.帶頭雙向不循環(huán)鏈表

【數(shù)據(jù)結(jié)構(gòu)】鏈表的分類和雙向鏈表,鏈表,數(shù)據(jù)結(jié)構(gòu)

5.不帶頭單向循環(huán)鏈表

【數(shù)據(jù)結(jié)構(gòu)】鏈表的分類和雙向鏈表,鏈表,數(shù)據(jù)結(jié)構(gòu)

6.不帶頭單向不循環(huán)鏈表

【數(shù)據(jù)結(jié)構(gòu)】鏈表的分類和雙向鏈表,鏈表,數(shù)據(jù)結(jié)構(gòu)

7.不帶頭雙向循環(huán)鏈表

【數(shù)據(jù)結(jié)構(gòu)】鏈表的分類和雙向鏈表,鏈表,數(shù)據(jù)結(jié)構(gòu)

8.不帶頭雙向不循環(huán)鏈表

【數(shù)據(jù)結(jié)構(gòu)】鏈表的分類和雙向鏈表,鏈表,數(shù)據(jù)結(jié)構(gòu)

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

2.雙向帶頭循環(huán)鏈表

我們還是經(jīng)典三個文件:

【數(shù)據(jù)結(jié)構(gòu)】鏈表的分類和雙向鏈表,鏈表,數(shù)據(jù)結(jié)構(gòu)

我們先定義頭文件所需要的函數(shù)

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>

//定義雙向鏈表中節(jié)點的結(jié)構(gòu)
typedef int LTDataType;
typedef struct ListNode {
	LTDataType data;
	struct ListNode* prev;
	struct ListNode* next;
}LTNode;

//注意,雙向鏈表是帶有哨兵位的,插入數(shù)據(jù)之前鏈表中必須要先初始化一個哨兵位
//void LTInit(LTNode** pphead);
LTNode* LTInit();
//void LTDesTroy(LTNode** pphead);
void LTDesTroy(LTNode* phead);   //推薦一級(保持接口一致性)

void LTPrint(LTNode* phead);

//不需要改變哨兵位,則不需要傳二級指針
//如果需要修改哨兵位的話,則傳二級指針
void LTPushBack(LTNode* phead, LTDataType x);
void LTPushFront(LTNode* phead, LTDataType x);

//頭刪、尾刪
void LTPopBack(LTNode* phead);
void LTPopFront(LTNode* phead);

//查找
LTNode* LTFind(LTNode* phead, LTDataType x);

//在pos位置之后插入數(shù)據(jù)
void LTInsert(LTNode* pos, LTDataType x);
//刪除pos位置的數(shù)據(jù)
void LTErase(LTNode* pos);

首先我們還是得先定義節(jié)點,由于是雙向鏈表,所以節(jié)點內(nèi)存在兩個節(jié)點的地址,一個是前驅(qū)節(jié)點的(指向其前一個節(jié)點),一個是尾結(jié)點的(指向其后一個節(jié)點)

【數(shù)據(jù)結(jié)構(gòu)】鏈表的分類和雙向鏈表,鏈表,數(shù)據(jù)結(jié)構(gòu)

這一段代碼,是為了確保數(shù)據(jù)類型

我們節(jié)點定義成這樣:

【數(shù)據(jù)結(jié)構(gòu)】鏈表的分類和雙向鏈表,鏈表,數(shù)據(jù)結(jié)構(gòu)

接下來又是完成各個功能:增,刪,查,改。但是,由于我們長線的是帶頭的鏈表,所以我們需要對頭初始化

3.初始化

我們先定義初始化函數(shù),然后寫函數(shù):

void LTInit(LTNode** pphead);
void ltinit(ltnode** pphead) {
	*pphead = (ltnode*)malloc(sizeof(ltnode));
	if (*pphead == null) {
		perror("malloc fail!");
		exit(1);
	}
	(*pphead)->data = -1;
	(*pphead)->next = (*pphead)->prev = *pphead;
}

和上回寫單鏈表差不多,檢測開辟是否成功,成功就接著給數(shù)據(jù)賦值,由于此時只有一個節(jié)點,即哨兵節(jié)點,且是循環(huán)鏈表,所以存放的前驅(qū)和尾節(jié)點就是哨兵節(jié)點自己

【數(shù)據(jù)結(jié)構(gòu)】鏈表的分類和雙向鏈表,鏈表,數(shù)據(jù)結(jié)構(gòu)

所以我們可以得出,如果哨兵節(jié)點的next指針或者prev指針指向自己,說明當前鏈表為空。

4.創(chuàng)建新的節(jié)點

我們寫法和上次差不多

LTNode* LTBuyNode(LTDataType x) {
	LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
	if (newnode == NULL) {
		perror("malloc fail!");
		exit(1);
	}
	newnode->data = x;
	newnode->next = newnode->prev = newnode;

	return newnode;
}

只是這回,多了一個前驅(qū)節(jié)點,我們定義時間默認前驅(qū)和后去節(jié)點指向的是本身。

但是既然我們都這么寫了一個創(chuàng)建新節(jié)點的函數(shù),那么我們可不可以用這個函數(shù)直接去進行哨兵節(jié)點的創(chuàng)建?

答案是肯定的,我們首先先改變以下我們定義的函數(shù),

LTNode* LTInit();

然后調(diào)用創(chuàng)建新節(jié)點的函數(shù),得到哨兵節(jié)點

LTNode* LTInit() {
	LTNode* phead = LTBuyNode(-1);
	return phead;
}

5.頭插和尾插

注意:頭插,是把新的節(jié)點插在第一個節(jié)點前,不是哨兵節(jié)點前

頭插和尾插,頭刪和尾刪的思路整體和單鏈表一致,我就不詳細說明了,直接上代碼

定義函數(shù):

void LTPushBack(LTNode* phead, LTDataType x);
void LTPushFront(LTNode* phead, LTDataType x);

函數(shù)代碼示例:

//尾插
void LTPushBack(LTNode* phead, LTDataType x) {
	assert(phead);
	LTNode* newnode = LTBuyNode(x);
	//phead phead->prev(ptail)  newnode
	newnode->next = phead;
	newnode->prev = phead->prev;

	phead->prev->next = newnode;
	phead->prev = newnode;
}
//頭插
void LTPushFront(LTNode* phead, LTDataType x) {
	assert(phead);

	LTNode* newnode = LTBuyNode(x);
	//phead newnode phead->next
	newnode->next = phead->next;
	newnode->prev = phead;

	phead->next->prev = newnode;
	phead->next = newnode;
}

不懂的你們可以再看看圖:【數(shù)據(jù)結(jié)構(gòu)】鏈表的分類和雙向鏈表,鏈表,數(shù)據(jù)結(jié)構(gòu)

6.頭刪和尾刪

定義函數(shù):

void LTPopBack(LTNode* phead);
void LTPopFront(LTNode* phead);

函數(shù)代碼示例:

//尾刪
void LTPopBack(LTNode* phead) {
	assert(phead);
	//鏈表為空:只有一個哨兵位節(jié)點
	assert(phead->next != phead);

	LTNode* del = phead->prev;
	LTNode* prev = del->prev;

	prev->next = phead;
	phead->prev = prev;

	free(del);
	del = NULL;
}
//頭刪
void LTPopFront(LTNode* phead) {
	assert(phead);
	assert(phead->next != phead);

	LTNode* del = phead->next;
	LTNode* next = del->next;

	//phead del next
	next->prev = phead;
	phead->next = next;

	free(del);
	del = NULL;
}

7.查找

整體思路還是遍歷,和單鏈表十分相似

定義函數(shù):

LTNode* LTFind(LTNode* phead, LTDataType x);

函數(shù)代碼示例:

LTNode* LTFind(LTNode* phead, LTDataType x) {
	assert(phead);
	LTNode* pcur = phead->next;
	while (pcur != phead)
	{
		if (pcur->data == x) {
			return pcur;
		}
		pcur = pcur->next;
	}
	return NULL;
}

8.在pos位置之后插入數(shù)據(jù)

這個和單戀表的也很相似,多了一個prev指針而已,寫的時候要注意順序,函數(shù)定義我就不寫了

函數(shù)代碼示例:

//在pos位置之后插入數(shù)據(jù)
void LTInsert(LTNode* pos, LTDataType x) {
	assert(pos);
	LTNode* newnode = LTBuyNode(x);
	//pos newnode pos->next
	newnode->next = pos->next;
	newnode->prev = pos;

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

9.刪除pos位置的數(shù)據(jù)

這個和單鏈表還是一樣的,遍歷整個表,然后相愛指針指向的地址,然后釋放內(nèi)存

函數(shù)代碼示例:

void LTErase(LTNode* pos) {
	assert(pos);

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

	free(pos);
	pos = NULL;
}

10.打印

這個其實是用來看每個節(jié)點中間的數(shù)據(jù)的,我們可以通過前驅(qū)節(jié)點或者尾節(jié)點實現(xiàn)正序或逆序打印,這一步也是遍歷然后看哨兵節(jié)點是否是下一位,是就中斷,我這里之舉一種例子,另一種只要將next改成prev

函數(shù)代碼示例:

void LTPrint(LTNode* phead) {
	//phead不能為空
	assert(phead);
	LTNode* pcur = phead->next;
	while (pcur != phead)
	{
		printf("%d->", pcur->data);
		pcur = pcur->next;
	}
	printf("\n");
}

11.銷毀

這個鏈表的銷毀和點鏈表不大一樣,因為存在哨兵節(jié)點,所以我們要分開釋放內(nèi)存

函數(shù)代碼示例:

void LTDesTroy(LTNode* phead) {
	//哨兵位不能為空
	assert(phead);

	LTNode* pcur = phead->next;
	while (pcur != phead)
	{
		LTNode* next = pcur->next;
		free(pcur);
		pcur = next;
	}
	//鏈表中只有一個哨兵位
	free(phead);
	phead = NULL;
}

最后還是一如既往的測試環(huán)節(jié)就交給大家了。推薦閱讀完http://t.csdnimg.cn/UhXEj

然后再閱讀這個文章來源地址http://www.zghlxwxcb.cn/news/detail-824671.html

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

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

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

相關(guān)文章

  • 探索數(shù)據(jù)結(jié)構(gòu):雙向鏈表的靈活優(yōu)勢

    探索數(shù)據(jù)結(jié)構(gòu):雙向鏈表的靈活優(yōu)勢

    ?? 歡迎大家來到貝蒂大講堂?? ????養(yǎng)成好習慣,先贊后看哦~???? 所屬專欄:數(shù)據(jù)結(jié)構(gòu)與算法 貝蒂的主頁:Betty’s blog 前面我們學習了單鏈表,它解決了順序表中插入刪除需要挪動大量數(shù)據(jù)的缺點。但同時也有仍需改進的地方,比如說:我們有時候需要尋找某個節(jié)點

    2024年03月16日
    瀏覽(24)
  • 數(shù)據(jù)結(jié)構(gòu):雙向鏈表的實現(xiàn)(C實現(xiàn))

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

    個人主頁 : 個人主頁 個人專欄 : 《數(shù)據(jù)結(jié)構(gòu)》 《C語言》 本篇博客,將要實現(xiàn)的是 帶頭雙向循環(huán)鏈表 ,該結(jié)構(gòu)實現(xiàn)尾插,尾刪只需要O(1)的時間復雜度。 其結(jié)構(gòu)如下所示: 既然要實現(xiàn)的鏈表是雙向循環(huán)的,那么對于指針域,我們就需要 指向節(jié)點上一個的指針 和 指向節(jié)點

    2024年02月14日
    瀏覽(21)
  • 【數(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任意位置刪除? 在剛開始接觸鏈表的時候,我們所學僅僅所學的

    2024年02月05日
    瀏覽(28)
  • 【數(shù)據(jù)結(jié)構(gòu)】—帶頭雙向循環(huán)鏈表的實現(xiàn)(完美鏈表)

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

    鏈表結(jié)構(gòu)一共有八種形式,在前面的文章里已經(jīng)講完了不帶頭單向非循環(huán)鏈表的實現(xiàn),但是我們發(fā)現(xiàn)該鏈表實現(xiàn)尾插與尾刪時比較麻煩,要先從頭節(jié)點進行遍歷,找到尾節(jié)點,時間復雜度為O(N),而本次所講的帶頭雙向循環(huán)單鏈表,則可以直接找到尾節(jié)點。 雖然該鏈表看起來

    2024年01月25日
    瀏覽(18)
  • 【數(shù)據(jù)結(jié)構(gòu)】雙向鏈表的增刪查改(C 代碼實現(xiàn))

    【數(shù)據(jù)結(jié)構(gòu)】雙向鏈表的增刪查改(C 代碼實現(xiàn))

    引入雙向鏈表:關(guān)于單鏈表的問題與討論 單鏈表存在的毛病: 因為單鏈表 只能單向 遍歷鏈表, 對于 前插 這個操作,單鏈表必 須得找到所需前插節(jié)點位置的前一個 ,那么這時就得 從頭指針重新遍歷一次 鏈表,會造成時間復雜度大大增加。 沒有頭節(jié)點(哨兵位)無法刪除

    2024年02月08日
    瀏覽(96)
  • 數(shù)據(jù)結(jié)構(gòu):鏈表基礎OJ練習+帶頭雙向循環(huán)鏈表的實現(xiàn)

    數(shù)據(jù)結(jié)構(gòu):鏈表基礎OJ練習+帶頭雙向循環(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)
  • 數(shù)據(jù)結(jié)構(gòu):圖文詳解雙向鏈表的各種操作(頭插法,尾插法,任意位置插入,查詢節(jié)點,刪除節(jié)點,求鏈表的長度... ...)

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

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

    2024年02月05日
    瀏覽(29)
  • 數(shù)據(jù)結(jié)構(gòu)_鏈表_雙向循環(huán)鏈表的初始化、插入、刪除、修改、查詢打?。ɑ贑語言實現(xiàn))

    數(shù)據(jù)結(jié)構(gòu)_鏈表_雙向循環(huán)鏈表的初始化、插入、刪除、修改、查詢打?。ɑ贑語言實現(xiàn))

    版本: 2024年4月26日 V1.0 發(fā)布于博客園 目錄 目錄 雙向循環(huán)鏈表公式 初始化雙向循環(huán)鏈表 構(gòu)建雙向循環(huán)鏈表結(jié)點 創(chuàng)建一個空鏈表(僅頭結(jié)點) 創(chuàng)建一個新結(jié)點 插入數(shù)據(jù) 頭插 中插 尾插 刪除數(shù)據(jù) 頭刪 中刪 尾刪 查詢打印數(shù)據(jù) 遍歷打印 測試 測試結(jié)果: 完整代碼 DoubleCirLList.h

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

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

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

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

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

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

    2024年02月04日
    瀏覽(31)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

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

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包