带头双向循环链表
前言
这是我由C语言写的带头双向循环链表,希望对大家有帮助。
1.DoubleCircularGuardList.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
//_CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <assert.h>
// 带头双向循环链表的结构体的定义
typedef int LTDataType;
typedef struct DoubleCircularGuardListNode
{
LTDataType data;
struct DoubleCircularGuardListNode* next;
struct DoubleCircularGuardListNode* prev;
}DLGH, DLN;
// 初始化链表
void DListInit(DLGH** ppNULL);
// 创建返回链表的头结点
DLGH* DListCreate();
// 双向链表销毁
void DListDestory(DLGH* pguard);
// 带头双向循环链表打印
void DListPrint(const DLGH* pguard);
// 双向链表尾插
void DListPushBack(DLGH* pguard, const LTDataType x);
// 双向链表头插
void DListPushFront(DLGH* pguard, const LTDataType x);
// 判断链表是否为空
bool DListEmpty(DLGH* pguard);
// 双向链表尾删
void DListPopBack(DLGH* pguard);
// 双向链表头删
void DListPopFront(DLGH* pguard);
// 返回链表中的数据个数
size_t DListSize(DLGH* pguard);
// 双向链表查找
DLN* DListFind(const DLGH* pguard, const LTDataType x);
// 双向链表在pos的前面进行插入
void DListInsert(DLN* pnode, const LTDataType x);
// 双向链表删除pos位置的节点
void DListErase(DLN* pnode);
2.DoubleCircularGuardList.c
#include "DoubleCircularGuardList.h"
// 创建返回链表的头结点
static DLN* BuyDListNode(const LTDataType x)
{
DLGH* new_node = (DLGH*)malloc(sizeof(DLN));
if (!new_node)
{
perror("DListCreate");
exit(-1);
}
new_node->data = x;
new_node->next = new_node->prev = NULL;
return new_node;
}
// 初始化链表
void DListInit(DLGH** ppguard)
{
assert(ppguard);
DLGH* guard = (DLGH*)malloc(sizeof(DLN));
if (!guard)
{
perror("DListInit");
exit(-1);
}
guard->next = guard;
guard->prev = guard;
*ppguard = guard;
}
// 创建返回链表的头结点
DLGH* DListCreate()
{
DLGH* guard = (DLGH*)malloc(sizeof(DLN));
if (!guard)
{
perror("DListCreate");
exit(-1);
}
guard->next = guard;
guard->prev = guard;
return guard;
}
// 双向链表销毁
void DListDestory(DLGH* pguard)
{
assert(pguard);
DLN* node = pguard->next;
while ((node = node->next) != pguard)
free(node->prev);
free(node->prev);
free(pguard);
}
// 带头双向循环链表打印
void DListPrint(const DLGH* pguard)
{
assert(pguard);
DLN* node = (DLN*)pguard;
printf("list_guard_head<=>");
while ((node = node->next) != pguard)
printf("%d<=>", node->data);
printf("list_guard_head\n");
}
// 双向链表尾插
void DListPushBack(DLGH* pguard, const LTDataType x)
{
assert(pguard);
#if false//这也是可以的。
DListPushFront(pguard->prev, x);
#else
DLGH* new_node = BuyDListNode(x);
new_node->prev = pguard->prev;
new_node->next = pguard;
pguard->prev->next = new_node;
pguard->prev = new_node;
#endif
}
// 双向链表头插
void DListPushFront(DLGH* pguard, const LTDataType x)
{
assert(pguard);
#if false//这也是可以的。
DListPushBack(pguard->next,x);
#else
DLGH* new_node = BuyDListNode(x);
new_node->next = pguard->next;
new_node->prev = pguard;
pguard->next = new_node;
new_node->next->prev = new_node;
#endif
}
// 判断链表是否为空
bool DListEmpty(DLGH* pguard)
{
assert(pguard);
return pguard->next == pguard;
}
// 双向链表尾删
void DListPopBack(DLGH* pguard)
{
assert(!DListEmpty(pguard));
#if false//这也是可以的。
DListPopFront(pguard->prev->prev);
#else
pguard->prev = pguard->prev->prev;
free(pguard->prev->next);
pguard->prev->next = pguard;
#endif
}
// 双向链表头删
void DListPopFront(DLGH* pguard)
{
assert(!DListEmpty(pguard));
#if false//这也是可以的。
DListPopBack(pguard->next->next);
#else
pguard->next = pguard->next->next;
free(pguard->next->prev);
pguard->next->prev = pguard;
#endif
}
// 返回链表中的数据个数
size_t DListSize(DLGH* pguard)
{
assert(pguard);
DLN* node = pguard;
size_t sum = 0;
while ((node = node->next) != pguard)
sum++;
return sum;
}
// 双向链表查找
DLN* DListFind(const DLGH* pguard, const LTDataType x)
{
assert(pguard);
DLN* node = (DLN*)pguard;
while ((node = node->next) != pguard)
if (node->data == x)
return node;
return NULL;
}
// 双向链表在pos的前面进行插入
void DListInsert(DLN* pnode, const LTDataType x)
{
assert(pnode);//这也是可以的。
DListPushFront(pnode,x);
}
// 双向链表删除pos位置的节点
void DListErase(DLN* pnode)
{
assert(pnode);
#if false//这也是可以的。
DListPopBack(pnode->next);
#else//这也是可以的。
DListPopFront(pnode->prev);
#endif
}
3.DoubleCircularGuardListMain.c
#include "DoubleCircularGuardList.h"
// 测试:创建返回链表的头结点 初始化链表 创建返回链表的头结点 带头双向循环链表打印 双向链表尾插 双向链表头插 判断链表是否为空 双向链表尾删 双向链表头删 双向链表销毁
void DLTest1()
{
printf("l2:\n");
DLGH* l2;
// 初始化链表
DListInit(&l2);
printf("双向链表尾插1\n");
DListPushBack(l2, 1);
printf("带头双向循环链表打印\n");
DListPrint(l2);
printf("双向链表尾删\n");
DListPopBack(l2);
printf("带头双向循环链表打印\n");
DListPrint(l2);
printf("双向链表头插1\n");
DListPushFront(l2, 1);
printf("带头双向循环链表打印\n");
DListPrint(l2);
printf("双向链表头删\n");
DListPopFront(l2);
printf("带头双向循环链表打印\n");
DListPrint(l2);
printf("l1:\n");
printf("创建返回链表的头结点\n");
DLGH* l1 = DListCreate();
printf("双向链表尾插1\n");
DListPushBack(l1, 1);
printf("带头双向循环链表打印\n");
DListPrint(l1);
printf("双向链表尾插2\n");
DListPushBack(l1, 2);
printf("带头双向循环链表打印\n");
DListPrint(l1);
printf("双向链表尾插3\n");
DListPushBack(l1, 3);
printf("带头双向循环链表打印\n");
DListPrint(l1);
printf("双向链表尾插4\n");
DListPushBack(l1, 4);
printf("带头双向循环链表打印\n");
DListPrint(l1);
printf("双向链表头插1\n");
DListPushFront(l1, 1);
printf("带头双向循环链表打印\n");
DListPrint(l1);
printf("双向链表头插2\n");
DListPushFront(l1, 2);
printf("带头双向循环链表打印\n");
DListPrint(l1);
printf("双向链表头插3\n");
DListPushFront(l1, 3);
printf("带头双向循环链表打印\n");
DListPrint(l1);
printf("双向链表头插4\n");
DListPushFront(l1, 4);
printf("带头双向循环链表打印\n");
DListPrint(l1);
printf("双向链表尾删\n");
DListPopBack(l1);
printf("带头双向循环链表打印\n");
DListPrint(l1);
printf("双向链表尾删\n");
DListPopBack(l1);
printf("带头双向循环链表打印\n");
DListPrint(l1);
printf("双向链表头删\n");
DListPopFront(l1);
printf("带头双向循环链表打印\n");
DListPrint(l1);
printf("双向链表头删\n");
DListPopFront(l1);
printf("带头双向循环链表打印\n");
DListPrint(l1);
printf("\n");
printf("双向链表销毁\n");
DListDestory(l1);
l1 = NULL;
}
// 测试:判断链表是否为空 返回链表中的数据个数 双向链表查找
void DLTest2()
{
printf("创建返回链表的头结点\n");
DLGH* l1 = DListCreate();
printf("判断链表是否为空\n");
if (DListEmpty(l1))
printf("链表为空。\n");
else
printf("链表不为空。\n");
printf("双向链表尾插1,2,3,4\n");
DListPushBack(l1, 1);
DListPushBack(l1, 2);
DListPushBack(l1, 3);
DListPushBack(l1, 4);
printf("带头双向循环链表打印\n");
DListPrint(l1);
printf("打印出链表的数据个数\n");
printf("链表的数据个数为%u个。\n", DListSize(l1));
printf("双向链表查找1\n");
if (DListFind(l1, 1))
printf("找到%d了。\n", DListFind(l1, 1)->data);
else
printf("找不到。\n");
printf("双向链表查找5\n");
if (DListFind(l1, 5))
printf("找到%d了。\n", DListFind(l1, 1)->data);
else
printf("找不到。\n");
printf("双向链表销毁\n");
DListDestory(l1);
l1 = NULL;
}
// 测试:双向链表在pos的前面进行插入 双向链表删除pos位置的节点
void DLTest3()
{
printf("创建返回链表的头结点\n");
DLGH* l1 = DListCreate();
printf("判断链表是否为空\n");
if (DListEmpty(l1))
printf("链表为空。\n");
else
printf("链表不为空。\n");
printf("双向链表尾插1,2,3,4\n");
DListPushBack(l1, 1);
DListPushBack(l1, 2);
DListPushBack(l1, 3);
DListPushBack(l1, 4);
printf("带头双向循环链表打印\n");
DListPrint(l1);
printf("双向链表在pos->data = 3的前面进行插入100\n");
DLN* pos = DListFind(l1, 3);
if (pos)
DListInsert(pos, 100);
printf("带头双向循环链表打印\n");
DListPrint(l1);
printf("双向链表删除pos->data = 100位置的节点\n");
if (pos = DListFind(l1, 100))
DListErase(pos);
printf("带头双向循环链表打印\n");
DListPrint(l1);
printf("双向链表销毁\n");
DListDestory(l1);
l1 = NULL;
}
int main(void)
{
printf("测试:创建返回链表的头结点 初始化链表 创建返回链表的头结点 带头双向循环链表打印 双向链表尾插 双向链表头插 判断链表是否为空 双向链表尾删 双向链表头删 双向链表销毁\n");
DLTest1();
printf("测试:判断链表是否为空 返回链表中的数据个数 双向链表查找\n");
DLTest2();
printf("测试:双向链表在pos的前面进行插入 双向链表删除pos位置的节点\n");
DLTest3();
return 0;
}