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

鏈表的極致——帶頭雙向循環(huán)鏈表

這篇具有很好參考價值的文章主要介紹了鏈表的極致——帶頭雙向循環(huán)鏈表。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

?

雙向帶頭循環(huán)鏈表簡介:

雙向帶頭循環(huán)鏈表是鏈表結構最復雜,但使用最方便的鏈表。
鏈表的極致——帶頭雙向循環(huán)鏈表,c語言,鏈表,數(shù)據(jù)結構

[圖中phead表示鏈表的頭節(jié)點(哨兵);

d1,d2等表示鏈表存儲的數(shù)據(jù);

d1,d2等左側(cè)的方框存儲是指向該節(jié)點的上一個節(jié)點的指針(prev),右側(cè)方框存儲指向該節(jié)點的下一個的指針(next)]


雙向:

雙向帶頭循環(huán)鏈表的每一個節(jié)點的指針域都有倆個指針,一個指針(prev)指向該節(jié)點的前一個節(jié)點,一個指針(next)指向它的后一個節(jié)點。
解決了單鏈表只能向后訪問,不能向前訪問的問題


帶頭:

特點:

  1. 雙向帶頭循環(huán)鏈表的頭節(jié)點(哨兵)位于第一個存儲數(shù)據(jù)的鏈表的前一個結點

  2. 雙向帶頭循環(huán)鏈表有一個頭節(jié)點(哨兵),該節(jié)點無論鏈表是否為空它都存在

  3. 頭節(jié)點(哨兵)的數(shù)據(jù)域一般不存儲數(shù)據(jù)或者存儲鏈表的信息(有幾個節(jié)點等)

  4. 雙向帶頭循環(huán)鏈表的頭節(jié)點(哨兵)指針域的也有兩個指針,且指向前一個節(jié)點的指針(prev)指向鏈表的最后一個節(jié)點,指向下一個節(jié)點的指針(next)指向鏈表的第一個節(jié)點


鏈表帶頭節(jié)點的好處:

  1. 由于開始結點的位置被存放在頭結點的指針域中,所以在鏈表的第一個節(jié)點上的操作就和在表的其它位置上操作一致,無須對鏈表的第一個節(jié)點進行進行特殊處理。 不會再改變鏈表phead指向的位置,也就不用再函數(shù)傳參時有時傳phead,有時傳*phead,讓鏈表的接口函數(shù)的參數(shù)類型也統(tǒng)一了。
  2. 無論鏈表是否為空,其頭指針是指向頭結點的非空指針,因此空表和非空表的處理也就統(tǒng)一了,不需要再分情況。

循環(huán):

特點:

  1. 雙向帶頭循環(huán)鏈表的最后一個節(jié)點的指向下一個節(jié)點的指針(next)指向頭節(jié)點(哨兵)
  2. 頭節(jié)點(哨兵)的指向上一個節(jié)點的指針(prev)指向鏈表的最后一個節(jié)點
  3. 當鏈表為空時,只有頭節(jié)點(哨兵),此時頭節(jié)點(哨兵)的prev指向它自己,它的next也指向它自己

循環(huán)的好處:

  1. 尾插時不用遍歷找鏈表的最后一個節(jié)點(尾節(jié)點),因為指向雙向帶頭循環(huán)鏈表的最后一個的節(jié)點的指針被存放在頭節(jié)點(哨兵)的prev中。
  2. 在進行刪除操作后,能保證鏈表不斷開
  3. 從鏈表中任意結點出發(fā)都能遍歷整個鏈表。
  4. 可以實現(xiàn)循環(huán)遍歷,即在遍歷到鏈表末尾后能夠自動回到鏈表頭部進行下一輪遍歷。

雙向帶頭循環(huán)鏈表的接口函數(shù)實現(xiàn)

準備工作:

創(chuàng)建一個頭文件(SList.h)兩個源文件(SList.c和test.c)

  • SList.h:用于包含庫函數(shù)的頭文件,鏈表節(jié)點結構體聲明,接口函數(shù)的聲明等【另外兩個源文件要包含SList.h這個頭文件,才能使用其中的聲明】
  • SList.h:用于實現(xiàn)單鏈表的接口函數(shù)
  • test.c:存放main函數(shù),用于鏈表的測試

鏈表的極致——帶頭雙向循環(huán)鏈表,c語言,鏈表,數(shù)據(jù)結構

上圖包含了以下3個操作

1.庫函數(shù)的頭文件的包含:

stdio.h:輸入/輸出等函數(shù)
stdlib.h:動態(tài)內(nèi)存申請
assert.h:報錯函數(shù)assert
2.給鏈表節(jié)點的數(shù)據(jù)域的數(shù)據(jù)類型重命名
為什么要重命名呢?
這是為了以后如果改變了LTNoed結構體中數(shù)據(jù)存儲的類型時,
不用到處改函數(shù)參數(shù)等地方的數(shù)據(jù)類型,只要改typedef后的int 為對應要改成的數(shù)據(jù)類型就可以。

3.鏈表節(jié)點結構體定義和重命名


初始化鏈表(頭結點)

鏈表的極致——帶頭雙向循環(huán)鏈表,c語言,鏈表,數(shù)據(jù)結構
參數(shù)設計:
無需參數(shù),將返回值賦值給一個指針,這個指針就成為鏈表的phead。


尾插

鏈表的極致——帶頭雙向循環(huán)鏈表,c語言,鏈表,數(shù)據(jù)結構


參數(shù)設計

LTNode*phead:
上面說了因為頭指針(phead)不會改變,所以傳一級指針phead即可

LTDaType x:
要插入的數(shù)據(jù)


圖解

鏈表的極致——帶頭雙向循環(huán)鏈表,c語言,鏈表,數(shù)據(jù)結構
鏈表為空的時候也不需要像單鏈表那樣特殊考慮,這也是雙向帶頭循環(huán)鏈表的好處


打印鏈表

鏈表的極致——帶頭雙向循環(huán)鏈表,c語言,鏈表,數(shù)據(jù)結構


圖解

鏈表的極致——帶頭雙向循環(huán)鏈表,c語言,鏈表,數(shù)據(jù)結構


頭插

鏈表的極致——帶頭雙向循環(huán)鏈表,c語言,鏈表,數(shù)據(jù)結構


圖解

鏈表的極致——帶頭雙向循環(huán)鏈表,c語言,鏈表,數(shù)據(jù)結構


尾刪

鏈表的極致——帶頭雙向循環(huán)鏈表,c語言,鏈表,數(shù)據(jù)結構


圖解

鏈表的極致——帶頭雙向循環(huán)鏈表,c語言,鏈表,數(shù)據(jù)結構


頭刪

鏈表的極致——帶頭雙向循環(huán)鏈表,c語言,鏈表,數(shù)據(jù)結構


圖解

鏈表的極致——帶頭雙向循環(huán)鏈表,c語言,鏈表,數(shù)據(jù)結構


查找

鏈表的極致——帶頭雙向循環(huán)鏈表,c語言,鏈表,數(shù)據(jù)結構


隨機插入

鏈表的極致——帶頭雙向循環(huán)鏈表,c語言,鏈表,數(shù)據(jù)結構
隨機插入的pos要配合查找函數(shù)的返回值使用·


圖解

鏈表的極致——帶頭雙向循環(huán)鏈表,c語言,鏈表,數(shù)據(jù)結構


隨機刪除

鏈表的極致——帶頭雙向循環(huán)鏈表,c語言,鏈表,數(shù)據(jù)結構


圖解

鏈表的極致——帶頭雙向循環(huán)鏈表,c語言,鏈表,數(shù)據(jù)結構


銷毀鏈表

鏈表的極致——帶頭雙向循環(huán)鏈表,c語言,鏈表,數(shù)據(jù)結構


圖解

鏈表的極致——帶頭雙向循環(huán)鏈表,c語言,鏈表,數(shù)據(jù)結構


全部代碼

SList.h

#define _CRT_SECURE_NO_WARNINGS

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

typedef int LTDateType;

typedef struct LTNode
{
	LTDateType data;
	struct LTNode* next;
	struct LTNode* prev;
}LTNode;

//初始化鏈表
LTNode* ListInit(void);
//打印鏈表
void ListPrint(LTNode* phead);
//尾插
void ListPushBack(LTNode* phead, LTDateType x);
//頭插
void ListPushFront(LTNode* phead, LTDateType x);
//尾刪
void ListPopBack(LTNode* phead);
//頭刪
void ListPopFront(LTNode* phead);
//查找x,找到了返回指向x的結構指針,找不到返回NULL
LTNode* ListFind(LTNode* phead, LTDateType x);
//在pos之前插入數(shù)據(jù)
void ListInsert(LTNode* phead, LTNode* pos, LTDateType x);
//刪除pos指向的節(jié)點
void ListEase(LTNode* phead, LTNode* pos);
//銷毀鏈表
void ListDestory(LTNode* phead);

SList.c

#define _CRT_SECURE_NO_WARNINGS
#include"List.h"

LTNode* ListInit()
{
	//哨兵位頭節(jié)點
	LTNode* phead = (LTNode*)malloc(sizeof(LTNode));//為頭結點申請空間

	phead->data = 0;//不存儲鏈表數(shù)據(jù)(鏈表的長度等)時也可不初始化

	phead->next = phead;//鏈表為空時頭結點的next指向自己
	phead->prev = phead;//鏈表為空時頭結點的prev也指向自己

	return phead;//返回被一個節(jié)點(phead)接收
}

void ListPushBack(LTNode* phead, LTDateType x)
{
	LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));//為新節(jié)點申請空間
	if (newnode == NULL)//如果為新節(jié)點申請空間失敗
	{
		printf("malloc失敗");
		exit(-1);//結束程序,-1表示程序非正常結束
	}
	LTNode* tail = phead->prev;//tail指向鏈表的最后一個節(jié)點

	tail->next = newnode;//讓新節(jié)點成為原尾節(jié)點的下一個節(jié)點

	newnode->prev = tail;//讓原尾節(jié)點成為新節(jié)點的上一個節(jié)點

	phead->prev = newnode;//更新頭結點中存儲的尾節(jié)點

	newnode->next = phead;//讓新節(jié)點的下一個節(jié)點為頭結點(phead)

	newnode->data = x;//存儲數(shù)據(jù)
}

void ListPrint(LTNode* phead)
{
	LTNode* cur = phead->next;//將鏈表的第一個節(jié)點賦值給cur

	while (cur != phead)//因為雙向帶頭循環(huán)鏈表沒有指向NULL的指針了,而且鏈表的尾節(jié)點的next指向頭結點(phead)
		                //所以遍歷鏈表結束的條件為cur==phead
	{
		printf("%d  ", cur->data);//打印節(jié)點數(shù)據(jù)域的數(shù)據(jù)
		cur = cur->next;//讓cur指向下一個節(jié)點
	}
}

//頭插
void ListPushFront(LTNode* phead, LTDateType x)
{
	LTNode* cur = phead->next;//讓cur指向鏈表的第一個節(jié)點
	LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));//為新節(jié)點申請空間

	if (newnode == NULL)//如果為新節(jié)點申請空間失敗
	{
		printf("malloc失敗");
		exit(-1);//結束程序,-1表示程序非正常結束
	}
	phead->next = newnode;//讓頭結點的下一個節(jié)點為新節(jié)點

	newnode->next = cur;//讓新節(jié)點的下一個節(jié)點為原鏈表的第一個節(jié)點

	newnode->prev = phead;//讓新節(jié)點的上一個節(jié)點為頭結點

	newnode->data = x;

	cur->prev = newnode;//讓原鏈表的第一個節(jié)點的上一個節(jié)點為新節(jié)點
}
//尾刪
void ListPopBack(LTNode* phead)
{
	assert(phead->next != phead);//鏈表為空時不能再刪除

	LTNode* tail = phead->prev;//讓tail指向尾節(jié)點

	tail->prev->next = phead;//讓尾節(jié)點(tail)的前一個節(jié)點的next指向頭結點,

	phead->prev = tail->prev;//讓刪除之前的尾節(jié)點的前一個節(jié)點成為新的尾節(jié)點

	free(tail);//釋放刪除之前的尾節(jié)點
}
//頭刪
void ListPopFront(LTNode* phead)
{
	assert(phead->next != phead);//鏈表為空時不能再刪除

	LTNode* cur = phead->next;//讓cur指向鏈表的第一個節(jié)點

	phead->next = cur->next;//讓頭節(jié)點的下一個節(jié)點為原鏈表第一個節(jié)點的下一個節(jié)點(原鏈表的第二個節(jié)點)

	cur->next->prev = phead;//讓原鏈表的第二個節(jié)點的前一個節(jié)點為頭結點

	free(cur);//釋放原鏈表第一個節(jié)點
}
//查找x,找到了返回指向x的結構指針,找不到返回NULL
LTNode* ListFind(LTNode* phead, LTDateType x)
{
	LTNode* cur = phead->next;//讓cur指向鏈表的第一個節(jié)點

	while (cur != phead)//因為雙向帶頭循環(huán)鏈表沒有指向NULL的指針了,而且鏈表的尾節(jié)點的next指向頭結點(phead)
		                //所以遍歷鏈表結束的條件為cur==phead
	{
		if (cur->data == x)
		{
			return cur;//找到了就直接返回
		}
		else
		{
			cur = cur->next;//讓cur指向下一個節(jié)點
		}
	}
	return NULL;//找不到就返回NULL
}

//在pos之前插入數(shù)據(jù)
void ListInsert(LTNode** phead, LTNode* pos, LTDateType x)
{
	LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
	if (newnode == NULL)//如果為新節(jié)點申請空間失敗
	{
		printf("malloc失敗");
		exit(-1);//結束程序,-1表示程序非正常結束
	}
	newnode->data = x;//存放數(shù)據(jù)

	newnode->next = pos;//讓新節(jié)點的下一個節(jié)點為pos指向的節(jié)點

	newnode->prev = pos->prev;//讓新節(jié)點的上一個節(jié)點為pos指向節(jié)點的前一個節(jié)點

	pos->prev->next = newnode;//pos指向節(jié)點的上一個節(jié)點的下一個節(jié)點為新節(jié)點

	pos->prev = newnode;//讓新節(jié)點成為pos指向節(jié)點的上一個節(jié)點
}

//刪除pos指向的節(jié)點
void ListEase(LTNode* phead, LTNode* pos)
{
	assert(pos != phead);//鏈表為空時再不能刪除

	pos->prev->next = pos->next;//讓pos指向節(jié)點的前一個節(jié)點的next指向pos指向節(jié)點的下一個節(jié)點

	pos->next->prev = pos->prev;//讓pos指向節(jié)點的下一個節(jié)點的prev指向pos指向節(jié)點的上一個節(jié)點

	free(pos);//釋放pos指向節(jié)點
}

//銷毀鏈表
void ListDestory(LTNode* phead)
{
	LTNode* cur = phead->next;//讓cur指向鏈表的第一個節(jié)點

	LTNode* tmp = phead->next;

	while (cur != phead)
	{
		tmp = cur->next;//tmp指向cur的下一個節(jié)點,防止cur被釋放了,找不到下一個節(jié)點了
		free(cur);
		cur = tmp;//讓cur指向下一個節(jié)點
	}
	phead->prev = phead;//鏈表的所有節(jié)點都被釋放后,頭節(jié)點的prev要指向自己,讓鏈表下一次使用時不會出錯

	phead->next = phead;//鏈表的所有節(jié)點都被釋放后,頭節(jié)點的next也要指向自己
}

以上就是所有內(nèi)容了,如果對你有幫助的話,可以點個贊支持一下!文章來源地址http://www.zghlxwxcb.cn/news/detail-846604.html

到了這里,關于鏈表的極致——帶頭雙向循環(huán)鏈表的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

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

領支付寶紅包贊助服務器費用

相關文章

  • 鏈接未來:深入理解鏈表數(shù)據(jù)結構(二.c語言實現(xiàn)帶頭雙向循環(huán)鏈表)

    鏈接未來:深入理解鏈表數(shù)據(jù)結構(二.c語言實現(xiàn)帶頭雙向循環(huán)鏈表)

    上篇文章簡述講解了鏈表的基本概念并且實現(xiàn)了無頭單向不循環(huán)鏈表:鏈接未來:深入理解鏈表數(shù)據(jù)結構(一.c語言實現(xiàn)無頭單向非循環(huán)鏈表)-CSDN博客 那今天接著給大家?guī)韼ь^雙向循環(huán)鏈表的實現(xiàn) : 頭文件DoubleList.h:用來基礎準備(常量定義,typedef),鏈表表的基本框架

    2024年01月16日
    瀏覽(58)
  • 【數(shù)據(jù)結構】雙向帶頭循環(huán)鏈表的實現(xiàn)

    【數(shù)據(jù)結構】雙向帶頭循環(huán)鏈表的實現(xiàn)

    前言:在前面我們學習了順序表、單向鏈表,今天我們在單鏈表的基礎上進一步來模擬實現(xiàn)一個帶頭雙向鏈表。 ?? 博主CSDN主頁:衛(wèi)衛(wèi)衛(wèi)的個人主頁 ?? ?? 專欄分類:數(shù)據(jù)結構 ?? ??代碼倉庫:衛(wèi)衛(wèi)周大胖的學習日記?? ??關注博主和博主一起學習!一起努力! 帶頭雙向循環(huán)鏈

    2024年01月15日
    瀏覽(23)
  • 數(shù)據(jù)結構-帶頭雙向循環(huán)鏈表的實現(xiàn)

    數(shù)據(jù)結構-帶頭雙向循環(huán)鏈表的實現(xiàn)

    前言 ? ? ? ? ? 帶頭雙向循環(huán)鏈表是一種重要的數(shù)據(jù)結構,它的結構是很完美的,它彌補了單鏈表的許多不足,讓我們一起來了解一下它是如何實現(xiàn)的吧! ? ? ? ? 它的節(jié)點中存儲著數(shù)據(jù)和兩個指針,一個 指針_prev 用來記錄前一個節(jié)點的地址,另一個指針 _next 用來記錄后一

    2024年02月13日
    瀏覽(28)
  • 數(shù)據(jù)結構 - 鏈表詳解(二)—— 帶頭雙向循環(huán)鏈表

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

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

    2024年04月26日
    瀏覽(21)
  • 【數(shù)據(jù)結構和算法】實現(xiàn)帶頭雙向循環(huán)鏈表(最復雜的鏈表)

    【數(shù)據(jù)結構和算法】實現(xiàn)帶頭雙向循環(huán)鏈表(最復雜的鏈表)

    前文,我們實現(xiàn)了認識了鏈表這一結構,并實現(xiàn)了無頭單向非循環(huán)鏈表,接下來我們實現(xiàn)另一種常用的鏈表結構,帶頭雙向循環(huán)鏈表。如有仍不了解單向鏈表的,請看這一篇文章(7條消息) 【數(shù)據(jù)結構和算法】認識線性表中的鏈表,并實現(xiàn)單向鏈表_小王學代碼的博客-CSDN博客

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

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

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

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

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

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

    2024年02月08日
    瀏覽(26)
  • 數(shù)據(jù)結構入門(C語言版)線性表帶頭雙向循環(huán)鏈表接口實現(xiàn)

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

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

    2023年04月12日
    瀏覽(20)
  • 追夢之旅【數(shù)據(jù)結構篇】——詳解C語言動態(tài)實現(xiàn)帶頭結點的雙向循環(huán)鏈表結構

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

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

    2024年01月17日
    瀏覽(108)
  • 雙向帶頭循環(huán)鏈表的實現(xiàn)

    雙向帶頭循環(huán)鏈表的實現(xiàn)

    當我們要學習和了解一個事物時,我們要做的第一步便是對這個事物有一個體的的了解。現(xiàn)在我們要學習雙向帶頭循環(huán)鏈表的第一步也是這個,我們現(xiàn)在先來了解一下這種鏈表的結構---- 就像該圖所呈現(xiàn)的那樣,雙向循環(huán)鏈表就是長這樣。但是你可 千萬不要將head當成head。 ?

    2024年02月05日
    瀏覽(25)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

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

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

二維碼1

領取紅包

二維碼2

領紅包