双链表(纯代码)

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;
}
相关推荐
Logic1013 分钟前
C语言/数据结构贪心算法题解:字符串趋同——逐位统计最高频率求最小修改代价
c语言·数据结构·贪心算法·字符串·时间复杂度·频率统计·算法题
做运维的阿瑞31 分钟前
mysql数据库视图笔记:创建、修改、删除与适用场景
数据库·笔记·mysql
@Mike@41 分钟前
12-数据库学习笔记(五种连接算法)
数据库·笔记·学习
韩明君42 分钟前
alacrity学习笔记
笔记·学习
坤坤子吖1 小时前
Python基础语法学习:函数
开发语言·笔记·python·学习
91刘仁德1 小时前
HTTPS 加密原理与 CA 数字证书:从对称加密到完整通信流程
网络·笔记·网络协议·http·https
红豆诗人2 小时前
C++二叉搜索树:查找、插入和删除为什么这样写
数据结构·c++·算法
云杂项2 小时前
Adversarial Neural Network Inversion via Auxiliary Knowledge Alignment(个人笔记)
笔记
H.莓飛2 小时前
【数据结构】堆_OJ题
linux·数据结构·算法
一隅论数智2 小时前
给AI找对“富矿“:本体协同的六大应用模式与落地战法
大数据·人工智能·经验分享·笔记·学习·学习方法·政务