线性表之带头双向循环链表(数据结构)(VS)(C语言)(DoubleCircularGuardList)


前言

  这是我由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;
}

效果

在这里插入图片描述


看完给个关注,多谢了!!!

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值