双链表(纯代码)

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;
}
相关推荐
芯思路5 分钟前
STM32开发学习笔记之十【AI部署】
笔记·stm32·学习
江屿风42 分钟前
【Plain Language Large Model】【从浏览器到全栈:一课精通Node.js三剑客】流食般投喂
笔记·前端框架·npm·node.js·js·npx
一只大鸽子1 小时前
游戏开发笔记0-Godot启动
笔记·游戏引擎·godot
UIU1141 小时前
P16237 [蓝桥杯 2026 省 B] 应急布线
数据结构·c++·算法·蓝桥杯
Nuanyt1 小时前
LeetCode Hot 100 链表专题2 3 题 (Java)
java·笔记·算法·leetcode·链表
asaotomo1 小时前
截图识题、AI 讲解、笔记沉淀:Chrome 扩展体验
前端·chrome·笔记
熊猫钓鱼>_>2 小时前
鸿蒙PC高分屏与键鼠交互适配:DPI缩放、右键菜单一次讲清
开发语言·笔记·华为·ai编程·harmonyos·鸿蒙·鸿蒙心迹
H_BB2 小时前
面试笔记:数据加密和心跳机制
笔记·面试·职场和发展
海绵宝宝转agent2 小时前
LeetCodehot100题解
java·笔记·学习·算法·leetcode·深度优先
2601_961146203 小时前
实验室等离子表面处理设备安全整改记录:通风、UV、接地三项
笔记·安全·uv