当我们在写单链表时,常常因为它不能通过一个节点访问前一个节点而烦恼,今天,我就来给大家介绍介绍它的超级无敌plus版本-------带头双向循环链表(自带音响。
完成一个链表就需要有一些它的基本功能,所以接下来,我将尽可能地向大家讲解它的增删查改,那么话不多说,我们开始吧!
目录
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;
}
人类的力量是有限的,所以,我不做人啦!!!
本文含有隐藏内容,请 开通VIP 后查看