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

【數(shù)據(jù)結構】線性表——帶頭雙向循環(huán)鏈表

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


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

  • 帶頭雙向循環(huán)鏈表的優(yōu)點

1.支持任意位置時間復雜度為O(1)的插入和刪除。

2.按照需求申請釋放空間,無需擔心空間不夠用,無需擔心浪費。

3.帶頭可以省去鏈表為空時的判斷,可以使代碼更加簡約

  • 帶頭雙向循環(huán)鏈表的缺點

1.不可以進行下標隨機訪問。

2.緩存利用率低

帶頭雙向循環(huán)鏈表是線性表的一種,帶頭雙向循環(huán)鏈表是鏈式存儲的線性表,不同于順序表,鏈表在內(nèi)存空間中不連續(xù)。

  • 帶頭:帶頭就是帶哨兵位,可以省鏈表為空時進行的判斷。

  • 雙向:由結構體內(nèi)的next指針下一條數(shù)據(jù)進行鏈接,由prev對前一條數(shù)據(jù)進行鏈接??。

  • 循環(huán):以循環(huán)方式進行鏈接,頭的(前一個)prev是尾,尾的next(后一個)是頭。

PS:需要源碼直接通過目錄跳轉到最后

帶頭雙向循環(huán)鏈表主體結構

默認大小與擴容大小還有類型都可以是任意大小或類型

typedef int DListDataType;		//數(shù)據(jù)類型

typedef struct ListNode
{
	DListDataType data;	
	struct ListNode* prev;		//指針指向前一個結點
	struct ListNode* next;		//指針指向后一個結點
}LTNode;

【數(shù)據(jù)結構】線性表——帶頭雙向循環(huán)鏈表

帶頭雙向循環(huán)鏈表操作函數(shù)介紹

  1. LTNode* InitLTNode(); //鏈表初始化
  2. void ListInsert(LTNode* pos, DListDataType x); //任意位置插入
  3. void ListPushBack(LTNode* phead, DListDataType x); //尾插
  4. void ListPushFront(LTNode* phead, DListDataType x); //頭插
  5. void print(LTNode* phead); //輸出鏈表
  6. void ListErase(LTNode* pos); //任意位置刪除
  7. void ListPopBack(LTNode* phead); //尾刪
  8. void ListPopFront(LTNode* phead); //頭刪
  9. LTNode* LTModify(LTNode* phead, DListDataType x); //修改指定結點
  10. LTNode* LTFind(LTNode* phead, DListDataType x); //查找指定結點
  11. void LTDestory(LTNode* phead); //銷毀鏈表

為了代碼方便閱讀,將帶頭雙向循環(huán)鏈表操作函數(shù)全部放在LinkedList.c文件中,將頭文件放在LinkedList.h,測試文件test.c ??

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

為了方便調(diào)試,建議每寫完1-2個函數(shù)就進行測試,初始化之后,首先實現(xiàn)print函數(shù)可以方便我們進行調(diào)試。

帶頭雙向循環(huán)鏈表的初始化函數(shù):

LTNode* Phead = InitLTNode();	//初始化哨兵位

LTNode* BuyNewNode(DListDataType x)		//開辟一個新結點
{
	LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
	if (newnode == NULL)
	{
		perror("malloc");
		return NULL;
	}
	newnode->next = NULL;
	newnode->prev = NULL;
	newnode->data = x;
	return newnode;
}

LTNode* InitLTNode()
{
	LTNode* phead = BuyNewNode(-1);
	phead->next = phead;
	phead->prev = phead;
	return phead;
}

必須先進行初始化哨兵位,將哨兵位指向自己形成循環(huán)

打印函數(shù)

先寫出打印函數(shù),方便進行調(diào)試

void print(LTNode* phead)
{
	assert(phead);
	LTNode* cur = phead->next;
	printf("head");
	while (cur!=phead)
	{
		printf("->%d", cur->data);
		cur = cur->next;
	}
	printf("\n");
}

帶頭雙向循環(huán)鏈表插入函數(shù):

指定結點后插入和查找函數(shù)

兩個函數(shù)可以配合使用,使用LTFind查找到需要插入的位置,然后使用ListInsert進行更改

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

LTNode* BuyNewNode(DListDataType x)
{
	LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
	if (newnode == NULL)
	{
		perror("malloc");
		return NULL;
	}
	newnode->next = NULL;
	newnode->prev = NULL;
	newnode->data = x;
	return newnode;
}

void ListInsert(LTNode* pos,DListDataType x)
{
	assert(pos);
	LTNode* newnode = BuyNewNode(x);
	LTNode* prev = pos->prev;

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

【數(shù)據(jù)結構】線性表——帶頭雙向循環(huán)鏈表

頭插

頭插將新結點插入到哨兵位后面的結點

這里面有一種簡單的寫法,就是直接復用ListInsert,將哨兵位后面的結點傳過去,也是頭插的效果

void ListPushFront(LTNode* phead, DListDataType x)
{
	assert(phead);
    //第一種方法
	//ListInsert(phead->next,x);
    //第二種方法
	LTNode* newnode = BuyNewNode(x);
	LTNode* secound = phead->next;
	newnode->next = secound;
	secound->prev = newnode;
	phead->next = newnode;
	newnode->prev = phead;
}

尾插

從最后一個結點后面插入新結點

尾插也可以復用ListInsert函數(shù)

  • 尾插也會用到申請新結點的函數(shù),這里不重復了
void ListPushBack(LTNode* phead, DListDataType x)
{
	assert(phead);
    //第一種辦法
	//ListInsert(phead,x);
    //第二種辦法
	LTNode* newnode = BuyNewNode(x);
	LTNode* tail = phead->prev;
	tail->next = newnode;
	newnode->prev = tail;
	newnode->next = phead;
	phead->prev = newnode;
}

帶頭雙向循環(huán)鏈表刪除函數(shù)

指定結點刪除

刪除指定結點,配合STFInd使用,將指定節(jié)點前一個結點的next連接到指定結點后一個結點,再將指定結點后面結點的prev連接到指定指定結點前一個結點。

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

頭刪

記得進行斷言,當只有一個哨兵位時與頭結點為空都無法進行刪除

可以對STErase進行復用

void ListPopFront(LTNode* phead)
{
	assert(phead);
	assert(phead != phead->next);
    //第一種方法
	//ListErase(phead->next);
    //第二種
	LTNode* secound = phead->next;
	phead->next = secound->next;
	secound->next->prev = phead;
	free(secound);
}

尾刪

void ListPopBack(LTNode* phead)
{
	assert(phead);
	assert(phead != phead->next);
    //第一種方法
    //ListErase(phead->prev);
    //第二種方法
	LTNode* tail = phead->prev;
	phead->prev = tail->prev;
	tail->prev->next = phead;
	free(tail);
}

帶頭雙向循環(huán)鏈表修改函數(shù)

配合LTFind函數(shù)使用

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

LTNode* LTModify(LTNode* phead, DListDataType x)
{
	LTNode* pos = LTFind(phead, x);
	int y;
	scanf("%d", &y);
	pos->data = y;
}

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

將每個結點依次釋放。最后將哨兵位釋放。

void LTDestory(LTNode* phead)
{
	assert(phead);
	LTNode* cur = phead->next;
	while (cur!=phead)
	{
		LTNode* next = cur->next;
		free(cur);	
		cur = next;
	}
	free(phead);
}

源代碼文件

????為了使代碼更有閱讀性,我們不建議把所有函數(shù)寫在一個文件里,所以這里分成三個文件,模塊化管理

test.c

測試文件

#include "DList.h"

void test1()
{
	LTNode* Phead = InitLTNode();
	ListPushBack(Phead, 666);
	ListPushBack(Phead, 777);
	ListPushBack(Phead, 9999);
	ListPushBack(Phead, 888);
	print(Phead);
	ListPopBack(Phead);
	print(Phead);
	ListPopFront(Phead);
	print(Phead);
	ListPopFront(Phead);
	ListPopFront(Phead);
	print(Phead);
	ListPushFront(Phead,111);
	print(Phead);
	ListPushFront(Phead, 112);
	print(Phead);
	LTDestory(Phead);
	Phead = NULL;

}

int main()
{
	test1();
}

DList.c

i將所有函數(shù)封裝在此文件下

#include "DList.h"


LTNode* BuyNewNode(DListDataType x)
{
	LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
	if (newnode == NULL)
	{
		perror("malloc");
		return NULL;
	}
	newnode->next = NULL;
	newnode->prev = NULL;
	newnode->data = x;
	return newnode;
}
LTNode* InitLTNode()
{
	LTNode* phead = BuyNewNode(-1);
	phead->next = phead;
	phead->prev = phead;
	return phead;
}

void ListInsert(LTNode* pos,DListDataType x)
{
	assert(pos);
	LTNode* newnode = BuyNewNode(x);
	LTNode* prev = pos->prev;

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

void ListPushBack(LTNode* phead, DListDataType x)
{
	//ListInsert(phead,x);
	assert(phead);
	LTNode* newnode = BuyNewNode(x);
	LTNode* tail = phead->prev;
	tail->next = newnode;
	newnode->prev = tail;
	newnode->next = phead;
	phead->prev = newnode;
}

void ListPushFront(LTNode* phead, DListDataType x)
{
	//ListInsert(phead->next,x);
	assert(phead);
	LTNode* newnode = BuyNewNode(x);
	LTNode* secound = phead->next;
	newnode->next = secound;
	secound->prev = newnode;
	phead->next = newnode;
	newnode->prev = phead;
}

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

void ListPopBack(LTNode* phead)
{
	//ListErase(phead->prev);
	assert(phead);
	assert(phead != phead->next);
	LTNode* tail = phead->prev;
	phead->prev = tail->prev;
	tail->prev->next = phead;
	free(tail);
}

void ListPopFront(LTNode* phead)
{
	assert(phead);
	assert(phead != phead->next);
	//ListErase(phead->next);
	LTNode* secound = phead->next;
	phead->next = secound->next;
	secound->next->prev = phead;
	free(secound);
}

void print(LTNode* phead)
{
	assert(phead);
	LTNode* cur = phead->next;
	printf("head");
	while (cur!=phead)
	{
		printf("->%d", cur->data);
		cur = cur->next;
	}
	printf("\n");
}

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

LTNode* LTModify(LTNode* phead, DListDataType x)
{
	LTNode* pos = LTFind(phead, x);
	int y;
	scanf("%d", &y);
	pos->data = y;
}

void LTDestory(LTNode* phead)
{
	assert(phead);
	LTNode* cur = phead->next;
	while (cur!=phead)
	{
		LTNode* next = cur->next;
		free(cur);	
		cur = next;
	}
	free(phead);
}

DLlist.h

將主程序所需要的函數(shù)全部在頭文件中聲明,增加代碼閱讀性

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <malloc.h>
#include <assert.h>

typedef int DListDataType;

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

LTNode* InitLTNode();
void ListInsert(LTNode* pos, DListDataType x);
void ListPushBack(LTNode* phead, DListDataType x);
void ListPushFront(LTNode* phead, DListDataType x);
void print(LTNode* phead);
void ListErase(LTNode* pos);
void ListPopBack(LTNode* phead);
void ListPopFront(LTNode* phead);
LTNode* LTModify(LTNode* phead, DListDataType x);
LTNode* LTFind(LTNode* phead, DListDataType x);
void LTDestory(LTNode* phead);

撒花

這就是實現(xiàn)帶頭雙向循環(huán)鏈表的全部內(nèi)容了,創(chuàng)作不易,還請各位小伙伴多多點贊??關注收藏?,以后也會更新各種關于c語言,數(shù)據(jù)結構的博客,撒花!文章來源地址http://www.zghlxwxcb.cn/news/detail-438244.html

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

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

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

相關文章

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

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

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

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

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

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

    2023年04月09日
    瀏覽(29)
  • 數(shù)據(jù)結構——帶頭雙向循環(huán)鏈表

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

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

    2024年02月09日
    瀏覽(25)
  • 數(shù)據(jù)結構之帶頭雙向循環(huán)鏈表

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

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

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

    相較于之前的順序表和單向鏈表,雙向鏈表的邏輯結構稍微復雜一些,但是在實現(xiàn)各種接口的時候是很簡單的。因為不用找尾,寫起來會舒服一點。(也可能是因為最近一直在寫這個的原因) 在實現(xiàn)接口的時候,除了沒有找尾,其他的操作和單向鏈表是差不多的,這里就不多

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

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

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

    2024年02月10日
    瀏覽(20)
  • 【數(shù)據(jù)結構】帶頭雙向循環(huán)鏈表及其實現(xiàn)

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

    目錄 1.帶頭雙向循環(huán)鏈表 2.帶頭雙向循環(huán)鏈表實現(xiàn) 2.1初始化 2.2銷毀 2.3頭插 2.4鏈表打印 2.5頭刪數(shù)據(jù) 2.6尾插數(shù)據(jù) 2.7尾刪數(shù)據(jù) 2.8鏈表判空? 2.9查找一個數(shù)據(jù) 2.10在pos位置前插入數(shù)據(jù) 2.11刪除pos位置 2.12求鏈表的長度 2.順序表和鏈表的比較 我們已經(jīng)實現(xiàn)了無頭單向循環(huán)鏈表 帶頭雙

    2024年02月10日
    瀏覽(25)
  • 【數(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)的鏈表,是為了讓大家更好的理解鏈表,現(xiàn)在我們就來學習學習他的升級版,雙向,帶頭,循環(huán)鏈表。希望多多支持哦! 目錄 定義的結構體節(jié)點 ?開辟結構體節(jié)點的函數(shù) 頭插函數(shù) 尾插函數(shù) 頭刪函數(shù) 尾刪函數(shù) 首先我們

    2024年02月21日
    瀏覽(20)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

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

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

二維碼1

領取紅包

二維碼2

領紅包