带头双向循环链表增删查改实现(c语言)

        当我们在写单链表时,常常因为它不能通过一个节点访问前一个节点而烦恼,今天,我就来给大家介绍介绍它的超级无敌plus版本-------带头双向循环链表(自带音响。

        完成一个链表就需要有一些它的基本功能,所以接下来,我将尽可能地向大家讲解它的增删查改,那么话不多说,我们开始吧!

目录

        1.图示

        2.基本结构体

         3.向内存申请新节点的空间--函数

        4.判断链表是否为空(后面也需要经常用到)

        5.初始化

        6.增删查改

        1.图示

        2.基本结构体

typedef int Type; //储存数据的类型

typedef struct ListNode
{
	struct ListNode* prev; //指向前节点
	struct ListNode* next; //指向后节点
	Type data;			   //储存数据
}List;

         3.向内存申请新节点的空间--函数

            因为在后面会多次创建新的节点,所以我把它分装成了一个函数,并将其放在前面。

List* Buy_Node(Type x)
{
	List* node = (List*)malloc(sizeof(List));//malloc申请空间
	if (node == NULL)
	{
		perror("malloc");
		exit(-1);
	}
	//将新的节点初始化
	node->prev = NULL;
	node->next = NULL;
	node->data = x;

	return node;
}

        4.判断链表是否为空(后面也需要经常用到)

bool ListEmpty(List* phead)
{
	assert(phead);
	return phead->next == phead;//当phead->next == phead时,链表为空
}

        5.初始化

//初始化
List* List_Init()
{
	List* guard = Buy_Node(0);
	guard->prev = guard;
	guard->next = guard;

	return guard;
}

        6.增删查改

 (1)头插

             

//头插
void Push_front(List* phead, Type x)
{
	assert(phead);//断言phead是否为空指针
	assert(!ListEmpty(phead));//断言链表是否为空
	List* newNode = Buy_Node(x);
	List* first = phead->next;

	newNode->next = first;
	first->prev = newNode;
	phead->next = newNode;
	newNode->prev = phead;
}

(2)尾插(对于双向链表而言,尾插某种意义上也是头插)

//尾插
void Push_back(List* phead, Type x)
{
	assert(phead);
    assert(!ListEmpty(phead));
	List* newNode = Buy_Node(x);
	List* tail = phead->prev;

	tail->next = newNode;
	newNode->prev = tail;
	newNode->next = phead;
	phead->prev = newNode;
}

 (3)尾删

//尾删
void Pop_back(List* phead)
{
	assert(phead);
	assert(!ListEmpty(phead));
	List* tail = phead->prev;
	List* prev = tail->prev;

	prev->next = phead;
	phead->prev = prev;
	free(tail);
	tail = NULL;
}

(4)头删

//头删
void Pop_front(List* phead)
{
	assert(phead);
	List* cur = phead->next;
	
	cur->next->prev = phead;
	phead->next = cur->next;
	free(cur);
	cur = NULL;
}

(5)查找

//查找
List* List_find(List* phead, Type x)
{
	assert(phead);
	List* cur = phead->next;
	while (cur != phead)//当cur == phead时,链表遍历
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

        7.销毁

//销毁
void List_destroy(List* phead)
{
	assert(phead);
	assert(!ListEmpty(phead));
	
	//释放tail节点
	while ((phead->prev) != phead)
	{
		List* tail = phead->prev;
		List* prev = tail->prev;
		prev->next = phead;
		phead->prev = prev;
		free(tail);
		tail = NULL;
	}
}

最后,为了方便调试,可以写一个打印函数。

8.打印

//打印
void List_print(List* phead)
{
	assert(phead);
	List* cur = phead->next;
	printf("phead<=>");
	while (cur != phead)
	{
		printf("%d<=>", cur->data);
		cur = cur->next;
	}
	printf("\n");
}

 以上就是今天的主要内容啦!因为是晚上写的,可能会有部分错误,欢迎大家斧正。

那我就将我写的源码放在下面吧。编译器:vs2022

List.h 

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

typedef int Type;

typedef struct ListNode
{
	struct ListNode* prev; //指向前节点
	struct ListNode* next; //指向后节点
	Type data;			   //储存数据
}List;

//初始化
List* List_Init();
//头插头删,尾插尾删
void Push_back(List* phead,Type x);
void Pop_back(List* phead);
void Push_front(List* phead,Type x);
void Pop_front(List* phead);
//查找
List* List_find(List* phead, Type x);
//打印
void List_print(List* phead);
//销毁
void List_destroy(List* phead);

//判断空
bool ListEmpty(List* phead);

List.c

#include"List.h"

List* Buy_Node(Type x)
{
	List* node = (List*)malloc(sizeof(List));//malloc申请空间
	if (node == NULL)
	{
		perror("malloc");
		exit(-1);
	}
	//将新的节点初始化
	node->prev = NULL;
	node->next = NULL;
	node->data = x;

	return node;
}
bool ListEmpty(List* phead)
{
	assert(phead);
	return phead->next == phead;//当phead->next == phead时,链表为空
}
//初始化
List* List_Init()
{
	List* guard = Buy_Node(0);
	guard->prev = guard;
	guard->next = guard;

	return guard;
}
//尾插
void Push_back(List* phead, Type x)
{
	assert(phead);
	assert(!ListEmpty(phead));
	List* newNode = Buy_Node(x);
	List* tail = phead->prev;

	tail->next = newNode;
	newNode->prev = tail;
	newNode->next = phead;
	phead->prev = newNode;
}
//打印
void List_print(List* phead)
{
	assert(phead);
	List* cur = phead->next;
	printf("phead<=>");
	while (cur != phead)
	{
		printf("%d<=>", cur->data);
		cur = cur->next;
	}
	printf("\n");
}
//尾删
void Pop_back(List* phead)
{
	assert(phead);
	assert(!ListEmpty(phead));
	List* tail = phead->prev;
	List* prev = tail->prev;

	prev->next = phead;
	phead->prev = prev;
	free(tail);
	tail = NULL;
}
//头插
void Push_front(List* phead, Type x)
{
	assert(phead);
	assert(!ListEmpty(phead));
	List* newNode = Buy_Node(x);
	List* first = phead->next;

	newNode->next = first;
	first->prev = newNode;
	phead->next = newNode;
	newNode->prev = phead;
}
//头删
void Pop_front(List* phead)
{
	assert(phead);
	List* cur = phead->next;
	
	cur->next->prev = phead;
	phead->next = cur->next;
	free(cur);
	cur = NULL;
}
//查找
List* List_find(List* phead, Type x)
{
	assert(phead);
	List* cur = phead->next;
	while (cur != phead)//当cur == phead时,链表遍历
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

//销毁
void List_destroy(List* phead)
{
	assert(phead);
	assert(!ListEmpty(phead));
	
	//释放tail节点
	while ((phead->prev) != phead)
	{
		List* tail = phead->prev;
		List* prev = tail->prev;
		prev->next = phead;
		phead->prev = prev;
		free(tail);
		tail = NULL;
	}
}


test.c

#include"List.h"


int main()
{
	List* plist = List_Init();

	Push_back(plist, 1);
	Push_back(plist, 2);
	Push_back(plist, 3);
	Push_back(plist, 4);
	Push_front(plist, 10);
	
	//List_print(plist);
	//Pop_back(plist);
	//Pop_front(plist);
	//List_print(plist);
	//List_destroy(plist);
	List_print(plist);
	printf("%d\n", List_find(plist, 3)->data);
	return 0;
}

 人类的力量是有限的,所以,我不做人啦!!!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值