双链表(纯代码)

list.h

cpp 复制代码
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>

typedef int LTDatatype;
//定义双向链表的结构
typedef struct ListNode
{
	LTDatatype data;
	struct ListNode* next;
	struct ListNode* prev;
}LTN;

//初始化
void LTInit(LTN** pphead);

//尾插
void LTPushback(LTN* phead,LTDatatype x);

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

//头插
LTPPushFront(LTN* phead, LTDatatype x);

//尾删
void LTPopBack(LTN* phead);

//头删
void LTPopFront(LTN* phead);

//查找数据
LTN* LTFind(LTN* phead, LTDatatype x);

//在指定位置后插入数据 若要改成指定位置之前直接传pos->prev即可
void LTInsert(LTN* pos, LTDatatype x);

//删除指定节点
void LTErase(LTN* pos);

//链表的销毁
void LTDestory(LTN* phead);

list.c

cpp 复制代码
#include"list.h"

//申请节点
LTN* LTBuyNode(LTDatatype x)
{
	LTN* node = (LTN*)malloc(sizeof(LTN));
	if (node == NULL)
	{
		perror("malloc fail!");
		exit(1);
	}
	node->data = x;
	node->next = node->prev = node;
	return node;
}
//初始化
void LTInit(LTN** pphead)
{
	//给双向链表创建一个哨兵卫
	*pphead = LTBuyNode(-1);
}
//打印
void LTPrint(LTN* phead)
{
	LTN* pcur = phead->next;
	while (pcur != phead)
	{
		printf("%d->", pcur->data);
		pcur = pcur->next;
	}
	printf("\n");
}


//尾插
void LTPushback(LTN* phead,LTDatatype x)
{
	assert(phead);
	LTN* newnode = LTBuyNode(x);
	newnode->prev = phead->prev;
	newnode->next = phead;
	phead->prev->next= newnode;
	phead->prev = newnode;
}

//头插
LTPPushFront(LTN* phead, LTDatatype x)
{
	assert(phead);
	LTN* newnode = LTBuyNode(x);
	newnode->next = phead->next;
	newnode->prev = phead;
	phead->next->prev = newnode;
	phead->next = newnode;
}

//尾删
void LTPopBack(LTN* phead)
{
	//链表必须有效且不能为空
	//只有哨兵卫说明是空链表 phead->next=phead;
   //哨兵卫为空说明这不是一个有效的双向链表
	assert(phead && phead->next != phead);
	LTN* del = phead->prev;
	del->prev->next = phead;
	phead->prev = del->prev;
	//删除del节点
	free(del);
	del = NULL;
}
//头删
void LTPopFront(LTN* phead)
{
	assert(phead && phead->next != phead);
	LTN* del = phead->next;
	phead->next = del->next;
	del->next->prev = phead;
	//删除del节点
	free(del);
	del = NULL;
}

//查找数据
LTN* LTFind(LTN* phead, LTDatatype x)
{
	LTN* pcur = phead->next;
	while (pcur != phead)
	{
		if (pcur->data == x)
		{
			printf("找到啦!\n");
			return pcur;
		}
		pcur = pcur->next;
	}
	//没有找到
	printf("没找到。\n");
	return NULL;
}

//在指定位置后插入数据
void LTInsert(LTN* pos, LTDatatype x)
{
	assert(pos);
	LTN* newnode = LTBuyNode(x);
	newnode->next = pos->next;
	newnode->prev = pos;
	pos->next->prev = newnode;
	pos->next = newnode;
}

//删除指定节点
void LTErase(LTN* pos)
{
	//理论上来说不能为phead,但是没有参数phead,无法增加校验
	assert(pos);
	pos->next->prev = pos->prev;
	pos->prev->next = pos->next;
	free(pos);
	pos = NULL;
}

//链表的销毁
void LTDestory(LTN* phead)
{
	assert(phead);
	LTN* pcur = phead->next;
	while (pcur != phead)
	{
		LTN* next = pcur->next;
		free(pcur);
		pcur = next;
	}
	//此时pcur指向的是phead,但是phead还没有被销毁
	free(phead);
	phead = NULL;
}

test.c

cpp 复制代码
#include"list.h"
void listtest01(void)
{
	LTN*plist=NULL;
	LTInit(&plist);
	LTPushback(plist, 3);
	LTPushback(plist, 4);
	LTPPushFront(plist, 5);
	LTPopBack(plist);
	LTPopFront(plist);
	LTN*ret=LTFind(plist, 3);
	LTInsert(ret, 99);
	LTPrint(plist);
	LTErase(ret);
	ret = NULL;
	LTPrint(plist);
	LTDestory(plist);
	plist = NULL;
}

int main(void)
{
	listtest01();
	
	return 0;
}
相关推荐
大胡子大叔2 分钟前
【与身俱能】机械臂训练(学习笔记)
笔记·学习
码以致用26 分钟前
docker-compose笔记
笔记·docker·容器
谈笑也风生1 小时前
经典算法题详解之切分数组(一)
数据结构·算法·leetcode
松涛和鸣1 小时前
28、Linux文件IO与标准IO详解:从概念到实战
linux·网络·数据结构·算法·链表·list
南_山无梅落1 小时前
4-Python3输入输出学习笔记:input()与print()的灵活使用
笔记·python·学习·input·print
凌盛羽1 小时前
在STM32G030xx的HAL库中使用DMA采集ADC多通达数据并开启DMA开启全满和半满中断
数据结构·stm32·单片机·嵌入式硬件·链表·嵌入式实时数据库
遗憾是什么.1 小时前
数据结构 -- 链表
数据结构·链表
hweiyu002 小时前
数据结构:无向图
数据结构
alan07212 小时前
【mysql存储引擎为什么选择B+树】
数据结构
小龙报2 小时前
【算法通关指南:算法基础篇(四)】二维差分专题:1.【模板】差分 2.地毯
c语言·数据结构·c++·深度学习·神经网络·算法·自然语言处理