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;
}