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

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

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

數(shù)據(jù)結(jié)構(gòu)雙向鏈表,數(shù)據(jù)結(jié)構(gòu),鏈表,網(wǎng)絡(luò)

Hello,好久不見,今天我們講鏈表的雙向鏈表,這是一個很厲害的鏈表,帶頭雙向且循環(huán),學了這個鏈表,你會發(fā)現(xiàn)順序表的頭插頭刪不再是一個麻煩問題,單鏈表的尾插尾刪也變得簡單起來了,那廢話不多說,讓我們開始我們的學習吧!

首先我們要了解它的物理和邏輯結(jié)構(gòu),那他們的樣子是怎樣的呢,首先是一個帶頭的,那這個難道是我們的哨兵位嗎,又是雙向,且循環(huán),那讓我們來畫圖了解它吧。

數(shù)據(jù)結(jié)構(gòu)雙向鏈表,數(shù)據(jù)結(jié)構(gòu),鏈表,網(wǎng)絡(luò)

大致就是這樣的一個形狀,那我們現(xiàn)在需要這樣的一個結(jié)構(gòu)體來實現(xiàn)這樣的功能,首先應(yīng)該有一個存儲數(shù)據(jù)的,就是data,然后就是得有兩個指針,一個指向前面的節(jié)點,一個就是指向后面的節(jié)點,那我們就叫它們一個pre指向前面,一個next指向后面,我們來實現(xiàn)一下吧。

typedef int DListType;
typedef struct DList
{
	struct DList* pre;
	struct DList* next;
	DListType data;
	
}DLNode;

為了方便我們寫后面的時候結(jié)構(gòu)體方便一點,我們先定義結(jié)構(gòu)體為DLNode,這樣更加方便使用。

現(xiàn)在我們要實現(xiàn)下面的各種接口來完成雙鏈表

首先最重要的就是怎么初始化
初始化的話我們先要想想這個接口函數(shù)改的參數(shù)和返回值
因為是雙向鏈表,所以得有一個head的頭節(jié)點,這樣才能鏈接后面的內(nèi)容

初始化雙鏈表

DLNode* DListInit();

接口函數(shù)的名字
這里我們分析首先我們得返回值為什么不是void,而是DLNode*
因為我們要在這里面創(chuàng)建一個頭節(jié)點,這個節(jié)點我們后面都得使用,其次還有一個原因就是這樣頭節(jié)點就不會被銷毀,當然我們也可以在外面創(chuàng)建一個節(jié)點,然后我們在傳它的指針進去,對結(jié)構(gòu)體的內(nèi)容進行修改,都可以達到相同的作用,廢話不多說,我們來實現(xiàn)吧!

DLNode* DListInit()
{
	DLNode* pHead = (DLNode*)malloc(sizeof(DLNode));
	assert(pHead);
	pHead->next = pHead;
	pHead->pre = pHead;
}

其實很簡單,這里必須指針指向自己才可以,如果不這樣的話,那我們的循環(huán)就不能實現(xiàn)了。
接下來就是怎么打印,打印很簡單,我們將它這個指針傳過去就行了。

打印雙鏈表

void DListPrint(DLNode* pHead)
{
	assert(pHead);
	DLNode* cur = pHead->next;
	while (cur != pHead)
	{
		printf("%d ", cur->data);
		cur = cur->next;
	}
	printf("\n");
}

打印函數(shù)的想法就是我們找head后面的那個節(jié)點,然后打印,因為頭節(jié)點我們不打印,所以取cur開始,因為是循環(huán),所以cur最后會等于pHead,這樣的話就是一個循環(huán),所以我們找下一個就行了,然后打印后更新cur。
接下來我們要創(chuàng)建一個節(jié)點,這樣才能鏈接起來我們的節(jié)點。

DLNode* CreatNewNode(DListType x)
DLNode* CreatNewNode(DListType x)
{
	DLNode* newnode = (DLNode*)malloc(sizeof(DLNode));
	assert(newnode);
	newnode->data = x;
	newnode->next = NULL;
	newnode->pre = NULL;
	return newnode;
}

創(chuàng)造節(jié)點好了,接下來就是尾插一個節(jié)點進去,我們前面單鏈表尾插首先要找到尾的位置,然后再去尾插,同時要先找到尾的前一個位置,然后free尾,這樣時間復雜度就是O(N),所以效率不是特別高,那我們現(xiàn)在因為head的位置里存放的就是尾的位置,所以不用進行查找了。我們現(xiàn)在來實現(xiàn)一下吧

雙鏈表尾插

void DListPushBACK(DLNode* pHead, DListType x)
{
	assert(pHead);
	DLNode* newnode = CreatNewNode(x);
	DLNode* pre = pHead->pre;
	pHead->pre = newnode;
	newnode->next = pHead;
	pre->next = newnode;
	newnode->pre = pre;
}

其實尾插也很簡單,我們這里先用一個指針保存位置,這樣的話下一次插入就可以找到尾的位置,而且還不用注重順序,這樣大大的提升效率

有了尾插那就肯定有頭插,一樣的辦法我們來實現(xiàn)一下

雙鏈表的頭插


void DListPushFront(DLNode* pHead, DListType x)
{
	assert(pHead);
	DLNode* newnode = CreatNewNode(x);
	DLNode* next = pHead->next;
	pHead->next = newnode;
	newnode->pre = pHead;
	newnode->next = next;
	next->pre = newnode;
}

有了頭插這些,那肯定還有頭刪和尾刪
那我們也來實現(xiàn)一下吧

尾刪

void DListPopBack(DLNode* pHead)
{
	assert(pHead);
	if (pHead->next != pHead)
	{
		DLNode* del = pHead->pre;
		del->pre->next = pHead;
		pHead->pre = del->pre;
		free(del);
	}
}

前面寫的代碼都需要測試一下,我們先來測試三個

#include"DList.h"
void test()
{
	DLNode* head = DListInit();
	DListPushBack(head, 1);
	DListPushBack(head, 2);
	DListPushBack(head, 3);
	DListPushBack(head, 4);
	DListPrint(head);
	DListPushFront(head, 111);
	DListPushFront(head, 111);
	DListPushFront(head, 111);
	DListPrint(head);
	DListPopBack(head);
	DListPopBack(head);
	DListPopBack(head);
	DListPrint(head);
}
int main()
{
	test();
	return 0;
}

發(fā)現(xiàn)我們的程序沒有問題,我們再來實現(xiàn)一下頭刪

void DListPopFront(DLNode* pHead)
{
	assert(pHead);
	if (pHead->next != pHead)
	{
		DLNode* del = pHead->next;
		pHead->next = del->next;
		del->next->pre = pHead;
		free(del);
	}
}

接下來就是雙鏈表的查找,有了查找我們才能和在任意位置的刪除和插入連用,那我們現(xiàn)在來實現(xiàn)一下吧


DLNode* DListFind(DLNode* pHead, DListType x)
{
	assert(pHead);
	DLNode* cur = pHead->next;
	while (cur != pHead)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

隨機插入

void DListInsert(DLNode* pos, DListType x)
{
	assrt(pos);
	DLNode* newnode = CreatNewNode(x);
	DLNode* pospre = pos->pre;
	pospre->next = newnode;
	newnode->pre = pospre;
	newnode->next = pos;
	pos->pre = newnode;

}

也不是隨機插入,是在pos位置之前插入,我們直接傳pos和x就行,然后在根據(jù)之前的想法一步一步的進行插入鏈接就行

這里可以更新一下頭插和尾插,這里就不演示了
那我們在寫一個刪除pos位置的函數(shù)

刪除pos位置

void DListPop(DLNode* pos)
{
	assert(pos);
	DLNode* pospre = pos->pre;
	DLNode* posnext = pos->next;
	pospre->next = posnext;
	posnext->pre = pospre;
	free(pos);
}

還有一個destory我們開辟的空間,這個遍歷一遍數(shù)組, 然后一個一個釋放就行,但是會有問題,我們釋放的時候必須看要機記住位置,可以從尾巴開始釋放,用一個指針記住前面一個的位置,然后釋放掉尾巴,然后更新前一個位置,用while控制一下就行了

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
typedef int DListType;
typedef struct DList
{
	struct DList* pre;
	struct DList* next;
	DListType data;
	
}DLNode;

DLNode* DListInit();

void DListPrint(DLNode* pHead);

DLNode* CreatNewNode(DListType x);

void DListPushBack(DLNode* pHead, DListType x);

void DListPushFront(DLNode* pHead, DListType x);


void DListPopBack(DLNode* pHead);

void DListPopFront(DLNode* pHead);

DLNode* DListFind(DLNode* pHead, DListType x);

void DListInsert(DLNode* pos, DListType x);

void DListPop(DLNode* pos);
#include"DList.h"

DLNode* DListInit()
{
	DLNode* pHead = (DLNode*)malloc(sizeof(DLNode));
	pHead->next = pHead;
	pHead->pre = pHead;
}

void DListPrint(DLNode* pHead)
{
	assert(pHead);
	DLNode* cur = pHead->next;
	while (cur != pHead)
	{
		printf("%d ", cur->data);
		cur = cur->next;
	}
	printf("\n");
}

DLNode* CreatNewNode(DListType x)
{
	DLNode* newnode = (DLNode*)malloc(sizeof(DLNode));
	assert(newnode);
	newnode->data = x;
	newnode->next = NULL;
	newnode->pre = NULL;
	return newnode;
}


void DListPushBack(DLNode* pHead, DListType x)
{
	DLNode* newnode = CreatNewNode(x);
	DLNode* pre = pHead->pre;
	pHead->pre = newnode;
	newnode->next = pHead;
	pre->next = newnode;
	newnode->pre = pre;
}

void DListPushFront(DLNode* pHead, DListType x)
{
	DLNode* newnode = CreatNewNode(x);
	DLNode* next = pHead->next;
	pHead->next = newnode;
	newnode->pre = pHead;
	newnode->next = next;
	next->pre = newnode;
}

void DListPopBack(DLNode* pHead)
{
	assert(pHead);
	if (pHead->next != pHead)
	{
		DLNode* del = pHead->pre;
		del->pre->next = pHead;
		pHead->pre = del->pre;
		free(del);
	}
}

void DListPopFront(DLNode* pHead)
{
	assert(pHead);
	if (pHead->next != pHead)
	{
		DLNode* del = pHead->next;
		pHead->next = del->next;
		del->next->pre = pHead;
		free(del);
	}
}

DLNode* DListFind(DLNode* pHead, DListType x)
{
	assert(pHead);
	DLNode* cur = pHead->next;
	while (cur != pHead)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

void DListInsert(DLNode* pos, DListType x)
{
	assrt(pos);
	DLNode* newnode = CreatNewNode(x);
	DLNode* pospre = pos->pre;
	pospre->next = newnode;
	newnode->pre = pospre;
	newnode->next = pos;
	pos->pre = newnode;

}


void DListPop(DLNode* pos)
{
	assert(pos);
	DLNode* pospre = pos->pre;
	DLNode* posnext = pos->next;
	pospre->next = posnext;
	posnext->pre = pospre;
	free(pos);
}

謝謝大家,我們下期再見文章來源地址http://www.zghlxwxcb.cn/news/detail-675057.html

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

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

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

相關(guān)文章

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

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

    ??系列專欄:??數(shù)據(jù)結(jié)構(gòu) ?? ?歡迎關(guān)注:??點贊??收藏??留言 ?? 博客主頁:??_麥麥_的博客_CSDN博客-領(lǐng)域博主 ??如果我們都不能夠擁有黑夜,又該怎樣去仰望星空? ? 目錄 一、前言 二、正文——雙向鏈表的實現(xiàn) 2.1模塊化 2.2 數(shù)據(jù)類型與結(jié)構(gòu)體定義 ?2.3鏈表的初始化

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

    單向鏈表:一塊內(nèi)存指向下一個內(nèi)存。 單鏈表存在一些缺陷: 1.查找速度慢。 2.不能從后往前找。 3.找不到前驅(qū)。 鏈表的結(jié)構(gòu)分為8種: 1.單向和雙向 2.帶頭和不帶頭 帶頭的鏈表有一個帶哨兵位的頭結(jié)點,這個節(jié)點不存儲有效數(shù)據(jù)。 好處 :尾插更方便,不需要二級指針了,

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

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

    在單鏈表那一篇博客中介紹了單鏈表和雙向鏈表的優(yōu)缺點,所以此篇博客直接分享怎樣實現(xiàn)一個帶頭雙向循環(huán)鏈表。 單鏈表博客: 首先我們需要寫一個結(jié)構(gòu)體,雙向帶頭鏈表的話需要一個前驅(qū)指針prev和一個后驅(qū)指針next,前驅(qū)指針的作用是方便找尾節(jié)點,因為頭節(jié)點的prev指

    2024年02月05日
    瀏覽(44)
  • 數(shù)據(jù)結(jié)構(gòu)——實現(xiàn)雙向鏈表

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

    怎么說呢?光乍一聽名字好像很難的樣子是吧,那如果你這樣認為的話,可就要讓你大跌眼鏡了哦,其實雙向帶頭循環(huán)鏈表從操作和理解上來說都是要易于單項不帶頭不循環(huán)鏈表(俗稱單鏈表)的。 咱們就來見識見識吧!希望真的能讓你們“大跌眼鏡”哈! 雙向帶頭循環(huán)鏈

    2024年02月07日
    瀏覽(22)
  • 【數(shù)據(jù)結(jié)構(gòu)】鏈表的分類和雙向鏈表

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

    本篇是基于上篇單鏈表所作,推薦與上篇配合閱讀,效果更加 http://t.csdnimg.cn/UhXEj 鏈表的結(jié)構(gòu)非常多樣,以下情況組合起來就有8種(2 x 2 x 2)鏈表結(jié)構(gòu): 我們一般叫這個頭為哨兵位 我們上回講的單鏈表就是不帶頭單項不循環(huán)鏈表。 今天我們要講帶頭雙向循環(huán)的鏈表。 不過

    2024年01月25日
    瀏覽(26)
  • 數(shù)據(jù)結(jié)構(gòu)入門 — 鏈表詳解_雙向鏈表

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

    數(shù)據(jù)結(jié)構(gòu)入門 — 雙向鏈表詳解 博客主頁鏈接:https://blog.csdn.net/m0_74014525 關(guān)注博主,后期持續(xù)更新系列文章 文章末尾有源碼 *****感謝觀看,希望對你有所幫助***** 第一篇:數(shù)據(jù)結(jié)構(gòu)入門 — 鏈表詳解_單鏈表 第二篇:數(shù)據(jù)結(jié)構(gòu)入門 — 鏈表詳解_雙向鏈表 第三篇:數(shù)據(jù)結(jié)構(gòu)入門

    2024年02月11日
    瀏覽(19)
  • 數(shù)據(jù)結(jié)構(gòu):詳解【鏈表】的實現(xiàn)(單向鏈表+雙向鏈表)

    數(shù)據(jù)結(jié)構(gòu):詳解【鏈表】的實現(xiàn)(單向鏈表+雙向鏈表)

    1.順序表的問題和思考 問題: 中間/頭部的插入刪除,時間復雜度為O(N)。 增容需要申請新空間,拷貝數(shù)據(jù),釋放舊空間,會有不小的消耗。 增容一般是呈2倍的增長,勢必會有一定的空間浪費。例如當前容量為100,滿了以后增容到200,我們再繼續(xù)插入了5個數(shù)據(jù),后面沒有數(shù)據(jù)

    2024年03月26日
    瀏覽(35)
  • 數(shù)據(jù)結(jié)構(gòu)與算法:雙向鏈表

    數(shù)據(jù)結(jié)構(gòu)與算法:雙向鏈表

    朋友們大家好啊,在上節(jié)完成單鏈表的講解后,我們本篇文章來對 帶頭循環(huán)雙向鏈表進行講解 單鏈表中,一個節(jié)點存儲數(shù)據(jù)和指向下一個節(jié)點的指針,而雙向鏈表除了上述兩個內(nèi)容,還包括了 指向上一個節(jié)點的指針 帶頭的雙向鏈表,是指在雙向鏈表的最前端添加了一個 額

    2024年02月20日
    瀏覽(26)
  • 【數(shù)據(jù)結(jié)構(gòu)】手撕雙向鏈表

    【數(shù)據(jù)結(jié)構(gòu)】手撕雙向鏈表

    目錄 前言 1. 雙向鏈表? 帶頭雙向循環(huán)鏈表的結(jié)構(gòu) 2. 鏈表的實現(xiàn) 2.1 初始化 2.2 尾插 2.3 尾刪 2.4 頭插 2.5 頭刪 2.6 在pos位置之前插入 2.7 刪除pos位置 3.雙向鏈表完整源碼 List.h List.c 在上一期中我們介紹了單鏈表,也做了一些練習題,在一些題中使用單鏈表會十分繁瑣。因為單鏈

    2024年02月05日
    瀏覽(27)
  • 【數(shù)據(jù)結(jié)構(gòu)】雙向鏈表詳解

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

    當我們學習完單鏈表后,雙向鏈表就簡單的多了,雙向鏈表中的頭插,尾插,頭刪,尾刪,以及任意位置插,任意位置刪除比單鏈表簡單,今天就跟著小張一起學習吧??! 還有雙向帶頭不循環(huán)鏈表,雙向不帶頭循環(huán)鏈表,著重使用雙向帶頭循環(huán)鏈表,帶頭也就是有哨兵位。

    2024年02月09日
    瀏覽(17)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

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

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包