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

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

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

一、帶頭雙向循環(huán)鏈表的定義

帶頭雙向循環(huán)鏈表:結(jié)構(gòu)最復(fù)雜,一般用在單獨(dú)存儲數(shù)據(jù)。實(shí)際中使用的鏈表數(shù)據(jù)結(jié)構(gòu),都是帶頭雙向循環(huán)鏈表。另外這個(gè)結(jié)構(gòu)雖然結(jié)構(gòu)復(fù)雜,但是使用代碼實(shí)現(xiàn)以后會(huì)發(fā)現(xiàn)結(jié)構(gòu)會(huì)帶來很多優(yōu)勢。
帶頭雙向循環(huán)鏈表包括一個(gè)帶有哨兵位的頭節(jié)點(diǎn),該節(jié)點(diǎn)既可以作為鏈表的第一個(gè)節(jié)點(diǎn),也可以作為鏈表的最后一個(gè)節(jié)點(diǎn).
這種鏈表的特點(diǎn)是每個(gè)節(jié)點(diǎn)都有兩個(gè)指針,一個(gè)指向前一個(gè)節(jié)點(diǎn),一個(gè)指向后一個(gè)節(jié)點(diǎn),這樣就可以實(shí)現(xiàn)雙向遍歷。
同時(shí),鏈表的最后一個(gè)節(jié)點(diǎn)的后繼指針指向頭節(jié)點(diǎn),形成了循環(huán)的結(jié)構(gòu)。這樣,我們可以在任意一個(gè)節(jié)點(diǎn)上進(jìn)行前后移動(dòng),插入和刪除操作,而不需要像單鏈表那樣遍歷整個(gè)鏈表去找到前一個(gè)節(jié)點(diǎn)。
需要注意的是,帶頭雙向循環(huán)鏈表為空并不意味著沒有一個(gè)節(jié)點(diǎn),而是只有一個(gè)帶哨兵位的頭節(jié)點(diǎn),所以在使用之前需要對鏈表進(jìn)行初始化。

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

2.1初始化創(chuàng)建帶頭雙向循環(huán)鏈表的節(jié)點(diǎn)

typedef struct ListNode
{
	Listdatatype data;
	struct ListNode* next;
	struct ListNode* prev;
}LTNode;

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

在創(chuàng)建帶頭雙向循環(huán)鏈表的節(jié)點(diǎn)中比之前單鏈表節(jié)點(diǎn)的創(chuàng)建多了一個(gè)struct ListNode* prev;結(jié)構(gòu)體指針,目的在與存儲前一個(gè)節(jié)點(diǎn)的地址,便于將整個(gè)鏈表連在一起。

2.2申請新節(jié)點(diǎn)

//創(chuàng)建新節(jié)點(diǎn)
LTNode* BuyLTNode(Listdatatype x)
{
	LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return NULL;
	}
	newnode->data = x;
	newnode->next = NULL;
	newnode->prev = NULL;
	return newnode;
}

動(dòng)態(tài)申請內(nèi)存結(jié)點(diǎn),函數(shù)返回的是一個(gè)指針類型,用malloc開辟一個(gè)LTNode大小的空間,并用node指向這個(gè)空間,再判斷是否為空,如為空就perror,顯示錯(cuò)誤信息。反之則把需要存儲的數(shù)據(jù)x存到newnode指向的空間里面,并且把newnode->next,newnode->prev置為空。

2.3節(jié)點(diǎn)的初始化

LTNode* LTInit()
{
	LTNode* phead = BuyLTNode(-1);
	phead->next = phead;
	phead->prev = phead;

	return phead;
}

通過動(dòng)態(tài)內(nèi)存申請節(jié)點(diǎn),申請了一個(gè)頭節(jié)點(diǎn)。并且將它的phead->next ,phead->prev 都置為phead,得到如下圖的頭節(jié)點(diǎn)。
數(shù)據(jù)結(jié)構(gòu)——帶頭雙向循環(huán)鏈表,數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),鏈表

2.4帶頭雙向循環(huán)鏈表的尾插

void LTPushBack(LTNode* phead, Listdatatype x)
{
	assert(phead);
	LTNode* tail = phead->prev;
	LTNode* newnode = BuyLTNode(x);

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

尾插節(jié)點(diǎn)的方法:首先通過內(nèi)存申請一個(gè)節(jié)點(diǎn), 然后改變四個(gè)指針的指向,便可以完成帶頭雙向循環(huán)鏈表的尾插。
數(shù)據(jù)結(jié)構(gòu)——帶頭雙向循環(huán)鏈表,數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),鏈表
數(shù)據(jù)結(jié)構(gòu)——帶頭雙向循環(huán)鏈表,數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),鏈表

2.5帶頭雙向循環(huán)鏈表的頭插

void LTFrontBack(LTNode* phead, Listdatatype x)
{
	assert(phead);
	LTNode* newnode = BuyLTNode(x);
	newnode->next = phead->next;
	phead->next->prev = newnode;
	phead->next = newnode;
	newnode->prev = phead;
}

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

2.6判空函數(shù)

bool LTEmpty(LTNode* phead)
{
	assert(phead);

	return phead->next == phead;
}

2.7帶頭雙向循環(huán)鏈表的打印函數(shù)

//打印
void LTPrint(LTNode* phead)
{
	LTNode* cur = phead->next;
	printf("guard<->");
	while (cur != phead)
	{
		printf("%d<->", cur->data);
		cur = cur->next;
	}
	printf("\n");
}

2.8帶頭雙向循環(huán)鏈表的尾刪

//尾刪
void LTPopBack(LTNode* phead)
{
	assert(phead);
	assert(! LTEmpty(phead));
	LTNode* tail = phead->prev;
	LTNode* tailprev = tail->prev;
	//改變指針的指向
	free(tail);
	tailprev->next = phead;
	phead->prev = tailprev;
}

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

2.9帶頭雙向循環(huán)鏈表的頭刪

void LTPopFront(LTNode* phead)
{
	assert(phead);
	assert(!LTEmpty(phead));
	LTNode* first = phead->next;
	LTNode* firstnext = first->next;
	free(first);
	phead->next = firstnext;
	firstnext->prev = phead;
}

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

2.11帶頭雙向循環(huán)鏈表的在pos之前插入

void LTInsert(LTNode* pos, Listdatatype x)
{
	assert(pos);
	LTNode* newnode = BuyLTNode(x);
	LTNode* posprev = pos->prev;
	posprev->next = newnode;
	newnode->prev = posprev;
	newnode->next = pos;
	pos->prev = newnode;
}

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

2.12帶頭雙向循環(huán)鏈表的在pos位置刪除

void LTErase(LTNode* pos)
{
	assert(pos);
	LTNode* posprev = pos->prev;
	LTNode* posnext = pos->next;
	posprev->next = posnext;
	posnext->prev = posprev;
	free(pos);
}

數(shù)據(jù)結(jié)構(gòu)——帶頭雙向循環(huán)鏈表,數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),鏈表文章來源地址http://www.zghlxwxcb.cn/news/detail-707060.html

2.14帶頭雙向循環(huán)鏈表的銷毀

//銷毀
LTNode* LTDestory(LTNode* phead)
{
	LTNode* cur = phead->next;
	while (cur != phead)
	{
		LTNode* next = cur->next;
		free(cur);
		cur = next;
	}
	free(phead);
}

三、完整代碼

3.1LIst.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
typedef int  Listdatatype;
typedef struct ListNode
{
	Listdatatype data;
	struct ListNode* next;
	struct ListNode* prev;
}LTNode;

//初始化
LTNode* LTInit();

//尾插
void LTPushBack(LTNode* phead, Listdatatype x);

//尾刪
void LTPopBack(LTNode* phead);

//頭插
void LTFrontBack(LTNode* phead, Listdatatype x);

//頭刪
void LTPopFront(LTNode* phead);

//打印
void LTPrint(LTNode* phead);

//判空
bool LTEmpty(LTNode* phead);

//在pos之前插入
void LTInsert(LTNode* pos, Listdatatype x);

//在pos之前刪除
void LTErase(LTNode* pos);

//尋找
LTNode* LTFind(LTNode* phead, Listdatatype x);

//銷毀
LTNode* LTDestory(LTNode* phead);

3.2List.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"List.h"
//創(chuàng)建新節(jié)點(diǎn)
LTNode* BuyLTNode(Listdatatype x)
{
	LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return NULL;
	}
	newnode->data = x;
	newnode->next = NULL;
	newnode->prev = NULL;
	return newnode;
}


LTNode* LTInit()
{
	LTNode* phead = BuyLTNode(-1);
	phead->next = phead;
	phead->prev = phead;

	return phead;
}
//尾插
void LTPushBack(LTNode* phead, Listdatatype x)
{
	assert(phead);
	LTNode* tail = phead->prev;
	LTNode* newnode = BuyLTNode(x);

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


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

//判空
bool LTEmpty(LTNode* phead)
{
	assert(phead);

	return phead->next == phead;
}

//打印
void LTPrint(LTNode* phead)
{
	LTNode* cur = phead->next;
	printf("guard<->");
	while (cur != phead)
	{
		printf("%d<->", cur->data);
		cur = cur->next;
	}
	printf("\n");
}


//尾刪
void LTPopBack(LTNode* phead)
{
	assert(phead);
	assert(! LTEmpty(phead));
	LTNode* tail = phead->prev;
	LTNode* tailprev = tail->prev;
	//改變指針的指向
	free(tail);
	tailprev->next = phead;
	phead->prev = tailprev;
}


//頭刪
void LTPopFront(LTNode* phead)
{
	assert(phead);
	assert(!LTEmpty(phead));
	LTNode* first = phead->next;
	LTNode* firstnext = first->next;
	free(first);
	phead->next = firstnext;
	firstnext->prev = phead;
}


//尋找
LTNode* LTFind(LTNode* phead, Listdatatype x)
{
	assert(phead);
	LTNode* cur = phead->next;
	while (cur != phead)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}



//在pos之前插入
void LTInsert(LTNode* pos, Listdatatype x)
{
	assert(pos);
	LTNode* newnode = BuyLTNode(x);
	LTNode* posprev = pos->prev;
	posprev->next = newnode;
	newnode->prev = posprev;
	newnode->next = pos;
	pos->prev = newnode;
}

在pos之前刪除
//void LTErase(LTNode* pos)
//{
//	assert(pos);
//	LTNode* posprev = pos->prev;
//	free(posprev);
//	posprev->prev->next = pos;
//	pos->prev = posprev->prev;
//	
//}


//在pos位置刪除
void LTErase(LTNode* pos)
{
	assert(pos);
	LTNode* posprev = pos->prev;
	LTNode* posnext = pos->next;
	posprev->next = posnext;
	posnext->prev = posprev;
	free(pos);
}

//銷毀
LTNode* LTDestory(LTNode* phead)
{
	LTNode* cur = phead->next;
	while (cur != phead)
	{
		LTNode* next = cur->next;
		free(cur);
		cur = next;
	}
	free(phead);
}

3.3test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"List.h"
//void test1()
//{
//	LTNode* plist = LTInit();
//	LTPushBack(plist, 1);
//	LTPushBack(plist, 2);
//	LTPushBack(plist, 3);
//	LTPushBack(plist, 4);
//	LTPrint(plist);
//	LTPopBack(plist);
//	LTPrint(plist);

//}
void test2()
{
	LTNode* plist = LTInit();
	LTFrontBack(plist, 1);
	LTFrontBack(plist, 2);
	LTFrontBack(plist, 3);
	LTFrontBack(plist, 4);
	LTPrint(plist);
	LTErase(3);
	LTPrint(plist);
}
int main()
{
	//test1();
	test2();
	return 0;
}

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

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

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

相關(guān)文章

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

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

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

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

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

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

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

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

    ????????????????????????Take your time ! ???????????????????????? ??個(gè)人主頁:??????大魔王?????? ??所屬專欄:??魔王的修煉之路–數(shù)據(jù)結(jié)構(gòu)?? 如果你覺得這篇文章對你有幫助,請?jiān)谖恼陆Y(jié)尾處留下你的 點(diǎn)贊 ??和 關(guān)注 ??,支持一

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

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

    在創(chuàng)建帶頭雙向循環(huán)鏈表的節(jié)點(diǎn)中比之前單鏈表節(jié)點(diǎn)的創(chuàng)建多了一個(gè)struct ListNode* prev;結(jié)構(gòu)體指針,目的在與存儲前一個(gè)節(jié)點(diǎn)的地址,便于將整個(gè)鏈表連在一起。 動(dòng)態(tài)申請內(nèi)存結(jié)點(diǎn),函數(shù)返回的是一個(gè)指針類型,用malloc開辟一個(gè)LTNode大小的空間,并用node指向這個(gè)空間,再判斷

    2024年02月09日
    瀏覽(24)
  • 【數(shù)據(jù)結(jié)構(gòu)】帶頭雙向循環(huán)鏈表

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

    ??????? 個(gè)人主頁:簡 料 ???? 所屬專欄:C++ ???? 個(gè)人社區(qū):越努力越幸運(yùn)社區(qū) ???? 簡? ? ?? 介: 簡料簡料,簡單有料~在校大學(xué)生一枚,專注C/C++/GO的干貨分享,立志成為您的好幫手 ~ C/C++學(xué)習(xí)路線 (點(diǎn)擊解鎖) ?? C語言階段(已結(jié)束) ?? 數(shù)據(jù)結(jié)構(gòu)與算法(ing) ?

    2024年01月16日
    瀏覽(33)
  • 數(shù)據(jù)結(jié)構(gòu)---帶頭雙向循環(huán)鏈表

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

    什么是雙向帶頭循環(huán)鏈表? 上面簡單的一個(gè)非空 帶頭循環(huán)雙向鏈表邏輯圖 如何定義一個(gè)雙向鏈表? 根據(jù)圖和代碼可以看雙向鏈表就是單鏈表的每個(gè)結(jié)點(diǎn)中,在設(shè)置一個(gè)指向前驅(qū)節(jié)點(diǎn)的指針 簡單認(rèn)識之后,對他進(jìn)行初始化(申請一個(gè)頭節(jié)點(diǎn),讓前驅(qū)和后驅(qū)指針都指向自己) 代碼

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

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

    前言: 鏈表有很多種,上一章結(jié),我復(fù)盤了單鏈表,這一章節(jié),主要針對雙鏈表的知識點(diǎn)進(jìn)行,整理復(fù)盤,如果將鏈表分類的話,有很多種,我就學(xué)習(xí)的方向考察的重點(diǎn),主要針對這兩種鏈表進(jìn)行整理。 帶頭雙向循環(huán)鏈表:結(jié)構(gòu)最復(fù)雜,一般用在單獨(dú)存儲數(shù)據(jù)。實(shí)際中使用

    2023年04月09日
    瀏覽(28)
  • 數(shù)據(jù)結(jié)構(gòu)之帶頭雙向循環(huán)鏈表

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

    目錄 鏈表的分類 帶頭雙向循環(huán)鏈表的實(shí)現(xiàn) 帶頭雙向循環(huán)鏈表的結(jié)構(gòu) 帶頭雙向循環(huán)鏈表的結(jié)構(gòu)示意圖 空鏈表結(jié)構(gòu)示意圖 單結(jié)點(diǎn)鏈表結(jié)構(gòu)示意圖 ?多結(jié)點(diǎn)鏈表結(jié)構(gòu)示意圖 鏈表創(chuàng)建結(jié)點(diǎn) 雙向鏈表初始化 銷毀雙向鏈表 打印雙向鏈表 ?雙向鏈表尾插 尾插函數(shù)測試 雙向鏈表頭插

    2024年02月08日
    瀏覽(17)
  • 數(shù)據(jù)結(jié)構(gòu)_帶頭雙向循環(huán)鏈表

    相較于之前的順序表和單向鏈表,雙向鏈表的邏輯結(jié)構(gòu)稍微復(fù)雜一些,但是在實(shí)現(xiàn)各種接口的時(shí)候是很簡單的。因?yàn)椴挥谜椅?,寫起來?huì)舒服一點(diǎn)。(也可能是因?yàn)樽罱恢痹趯戇@個(gè)的原因) 在實(shí)現(xiàn)接口的時(shí)候,除了沒有找尾,其他的操作和單向鏈表是差不多的,這里就不多

    2024年04月14日
    瀏覽(21)
  • 【數(shù)據(jù)結(jié)構(gòu)】實(shí)現(xiàn)帶頭雙向循環(huán)鏈表

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

    之前我們已經(jīng)學(xué)習(xí)了單鏈表,有了單鏈表的基礎(chǔ),現(xiàn)在開始學(xué)習(xí)帶頭雙向循環(huán)鏈表~ 結(jié)構(gòu)最復(fù)雜 ,一般用在單獨(dú)存儲數(shù)據(jù)。 實(shí)際中使用的鏈表數(shù)據(jù)結(jié)構(gòu),都是帶頭雙向循環(huán)鏈表 。另外這個(gè)結(jié)構(gòu)雖然結(jié)構(gòu)復(fù)雜,但是使用代碼實(shí)現(xiàn)以后會(huì)發(fā)現(xiàn) 結(jié)構(gòu)會(huì)帶來很多優(yōu)勢 ,實(shí)現(xiàn)反而簡單

    2024年02月10日
    瀏覽(20)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

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

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包