带头双向链表

一.链表的分类

链表大致分为以下的几种类型

以上的组合一共8种,其中最常用的是不带头单向不循环链表,也就是我们说的单链表,在前面的文章中已经提到了,还有一种就是我们今天提到的带头双向循环链表

带头:

在链表中,我们会定义一个里面没有有效数据的节点,有时候在写的代码的时候运用它会很方便的,这个就叫带头

不带头:

第一个节点是有效节点的叫不带头,单链表就是不带头

 循环和不循环

循环

不循环的就是首尾不相连接的

单向和双向链表

二.说明(有点重要)

单向链表传递参数用的是二级指针,带头双向链表传递参数用的是一级指针

单向链表无头,用二级指针是为了应对空链表的时候,在单链表有节点的情况下,其实传一级指针也行,双向链表已经有头了,所以,用一级指针即可。注意,pphead->next里面的箭头是解引用的意思的哈

三.带头双向链表 

定义 

typedef int SLdatetype;
typedef struct ListNode
{
	SLdatetype val;
	struct ListNode* next;
	struct ListNode* prev;
}ListNode;

初始化链表

ListNode* ListNodeinit()
{
	ListNode* phead = (ListNode*)malloc(sizeof(ListNode));
	phead->val = -1;//个人习惯,可以是任何数字,不放数字也可以
	phead->next = phead;
	phead->prev = phead;//刚开始的时候只有一个节点,由于是带头双向链表,前驱和后继节点都指向自己
	return phead;
}

四.打印链表

void ListNodeprint(ListNode* phead)
{
	assert(phead);
	assert(phead->next);
	ListNode* pcur = phead->next;
	while (pcur!= phead)
	{
		printf("%d->",pcur->val);
		pcur = pcur->next;
	}
	printf("\n");
}

五.申请一个节点

ListNode* buynode(SLdatetype x)
{
	ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
	newnode->val = x;
	newnode->next = newnode->prev = newnode;
	return newnode;
}

六.尾插一个节点

void ListNodepushback(ListNode* phead, SLdatetype x)
{
	assert(phead);
	ListNode* newnode = buynode(x);
	phead->prev->next = newnode;
	newnode->prev = phead->prev;
	phead->prev = newnode;
	newnode->next = phead;
	
}

七.头插一个节点

void ListNodepushfront(ListNode* phead, SLdatetype x)
{
	assert(phead);
	ListNode* newnode = buynode(x);
	phead->next->prev = newnode;
	newnode->next = phead->next;
	phead->next = newnode;
	newnode->prev = phead;
}

八.尾删一个节点

void ListNodepopback(ListNode* phead)
{
	assert(phead);
	assert(phead->next);
	ListNode* del = phead->prev;
	ListNode* prev = del->prev;
	phead->prev = prev;
	prev->next = phead;
}

九.头删一个节点

void ListNodepopfront(ListNode* phead)
{
	assert(phead);
	assert(phead->next);
	ListNode* del = phead->next;
	ListNode* next = del->next;
	phead->next = next;
	next->prev = phead;
	free(del);
	del = NULL;
}

十.查找一个节点

ListNode* ListNodefind(ListNode* phead, SLdatetype x)
{
	assert(phead);
	ListNode* pcur = phead->next;
	while (pcur != phead)
	{
		if (pcur->val == x)
		{
			return pcur;
		}
		pcur = pcur->next;
	}
	return NULL;
}

十一.在pos后面插入一个数据

void ListNodepushpos(ListNode* pos, SLdatetype x)
{
	assert(pos);
	ListNode* push = buynode(x);
	pos->next->prev = push;
	push->next = pos->next;
	pos->next = push;
	push->prev = pos;
}

十二.删除pos位置的节点

void ListNodeerasepos(ListNode* pos)
{
	assert(pos);
	ListNode* pre = pos->prev;
	ListNode* next = pos->next;
	pre->next = next;
	next->prev = pre;
	free(pos);
	pos = NULL;
}

十三.摧毁整个链表

void ListNodedestory(ListNode* phead)
{
	assert(phead);
	ListNode* pcur = phead->next;
	while (pcur!=phead)
	{
		ListNode* next = pcur->next;
		free(pcur);
		pcur = next;
	}
}

注意:在摧毁链表的时候如果要把头节点摧毁的话,必须要使用二级指针,但是为了保持接口的一致性,通常使用一级指针,头节点的释放可以在主函数里面操作

十三.完整的代码

//头文件  
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SLdatetype;
typedef struct ListNode
{
	SLdatetype val;
	struct ListNode* next;
	struct ListNode* prev;
}ListNode;
//初始化链表,定义一个无效的头节点
ListNode* ListNodeinit();
//链表的打印
void ListNodeprint(ListNode* phead);
//创建一个节点
ListNode* buynode(SLdatetype x);
//尾插一个节点
void ListNodepushback(ListNode* phead, SLdatetype x);
//头插一个节点
void ListNodepushfront(ListNode* phead, SLdatetype x);
//尾删一个节点
void ListNodepopback(ListNode* phead);
//头删一个节点
void ListNodepopfront(ListNode* phead);
//查找一个节点
ListNode* ListNodefind(ListNode* phead, SLdatetype x);
//在pos位置之后插入数据
void ListNodepushpos(ListNode* pos, SLdatetype x);
//删除pos位置的数据
void ListNodeerasepos(ListNode* pos);
//摧毁链表
void ListNodedestory(ListNode* phead);
//源文件
#define _CRT_SECURE_NO_WARNINGS 1
#include"ListNode.h"
ListNode* ListNodeinit()
{
	ListNode* phead = (ListNode*)malloc(sizeof(ListNode));
	phead->val = -1;
	phead->next = phead;
	phead->prev = phead;
	return phead;
}
void ListNodeprint(ListNode* phead)
{
	assert(phead);
	assert(phead->next);
	ListNode* pcur = phead->next;
	while (pcur!= phead)
	{
		printf("%d->",pcur->val);
		pcur = pcur->next;
	}
	printf("\n");
}
ListNode* buynode(SLdatetype x)
{
	ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
	newnode->val = x;
	newnode->next = newnode->prev = newnode;
	return newnode;
}
void ListNodepushback(ListNode* phead, SLdatetype x)
{
	assert(phead);
	ListNode* newnode = buynode(x);
	phead->prev->next = newnode;
	newnode->prev = phead->prev;
	phead->prev = newnode;
	newnode->next = phead;
	
}
void ListNodepushfront(ListNode* phead, SLdatetype x)
{
	assert(phead);
	ListNode* newnode = buynode(x);
	phead->next->prev = newnode;
	newnode->next = phead->next;
	phead->next = newnode;
	newnode->prev = phead;
}
void ListNodepopback(ListNode* phead)
{
	assert(phead);
	assert(phead->next);
	ListNode* del = phead->prev;
	ListNode* prev = del->prev;
	phead->prev = prev;
	prev->next = phead;
}
void ListNodepopfront(ListNode* phead)
{
	assert(phead);
	assert(phead->next);
	ListNode* del = phead->next;
	ListNode* next = del->next;
	phead->next = next;
	next->prev = phead;
	free(del);
	del = NULL;
}
ListNode* ListNodefind(ListNode* phead, SLdatetype x)
{
	assert(phead);
	ListNode* pcur = phead->next;
	while (pcur != phead)
	{
		if (pcur->val == x)
		{
			return pcur;
		}
		pcur = pcur->next;
	}
	return NULL;
}
void ListNodepushpos(ListNode* pos, SLdatetype x)
{
	assert(pos);
	ListNode* push = buynode(x);
	pos->next->prev = push;
	push->next = pos->next;
	pos->next = push;
	push->prev = pos;
}
void ListNodeerasepos(ListNode* pos)
{
	assert(pos);
	ListNode* pre = pos->prev;
	ListNode* next = pos->next;
	pre->next = next;
	next->prev = pre;
	free(pos);
	pos = NULL;
}
void ListNodedestory(ListNode* phead)
{
	assert(phead);
	ListNode* pcur = phead->next;
	while (pcur!=phead)
	{
		ListNode* next = pcur->next;
		free(pcur);
		pcur = next;
	}
}
//测试文件
#define _CRT_SECURE_NO_WARNINGS 1
#include"ListNode.h"
void test()
{
	ListNode* phead = ListNodeinit();
	ListNodepushback(phead, 1);
	ListNodeprint(phead);
	ListNodepushback(phead, 2);
	ListNodepushback(phead, 3);
	ListNodepushback(phead, 4);
	ListNodepushback(phead, 5);
	ListNodeprint(phead);
	ListNodepopfront(phead);
	ListNodeprint(phead);
	ListNode* pfind = ListNodefind(phead, 3);
	if (pfind != NULL)
	{
		printf("找到了");
	}
	printf("\n");
	ListNodepushpos(pfind, 100);
	ListNodeerasepos(pfind);
	ListNodeprint(phead);
	ListNodedestory(phead);
}
int main()
{
	test();
	return 0;
}

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
【优质项目推荐】 1、项目代码均经过严格本地测试,运行OK,确保功能稳定后才上传平台。可放心下载并立即投入使用,若遇到任何使用问题,随时欢迎私信反馈与沟通,博主会第一时间回复。 2、项目适用于计算机相关专业(如计科、信息安全、数据科学、人工智能、通信、物联网、自动化、电子信息等)的在校学生、专业教师,或企业员工,小白入门等都适用。 3、该项目不仅具有很高的学习借鉴价值,对于初学者来说,也是入门进阶的绝佳选择;当然也可以直接用于 毕设、课设、期末大作业或项目初期立项演示等。 3、开放创新:如果您有一定基础,且热爱探索钻研,可以在此代码基础上二次开发,进行修改、扩展,创造出属于自己的独特应用。 欢迎下载使用优质资源!欢迎借鉴使用,并欢迎学习交流,共同探索编程的无穷魅力! 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值