双向循环链表
序言
之前我写了一篇博客是单向不带头的链表
现在我要介绍的是双向带头循环链表,介绍之前我们了解一些东西
- 无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。
- 带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而
简单了
大致是这样的,虽然结构较复杂,但是对于增删查改是真的简单!
还是老样子
这是List.h的代码 函数的声明
#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int LTDataType;
typedef struct ListNode
{
LTDataType data;
struct ListNode* prev;
struct ListNode* next;
}LTN;
LTN* ListInit();//双向链表的初始化
LTN* ListBuyNode(LTDataType x);//创建一个结点
void Listprint(LTN* phead);//双向链表的打印
void PushBack(LTN* phead, LTDataType x);//尾插
void PuchFront(LTN* phead, LTDataType x);//头插
void ListInsert(LTN* pos, LTDataType x);//在pos之前插入
void ListErase(LTN* pos);//删除pos位置的结点
void PopFront(LTN* phead);//头删
void PopBack(LTN* phead);//尾删
LTN* ListFind(LTN* phead, LTDataType x);//查找x的位置
首先是要先写一个创造一个结点的函数
这样才能方便接下来的操作
LTN* ListBuyNode(LTDataType x)//创建一个结点
{
LTN* newnode = (LTN*)malloc(sizeof(LTN));
if (newnode == NULL)
{
printf("malloc fail\n");
exit(-1);
}
newnode->data = x;
newnode->next = NULL;
newnode->prev = NULL;
return newnode;
}
然后便是链表的初始化
LTN* ListInit()//双向链表的初始化
{
LTN* ret = ListBuyNode(0);
ret->next = ret;
ret->prev = ret;
return ret;
}
链表的打印
void Listprint(LTN* phead)//双向链表的打印
{
assert(phead);
LTN* cur = phead->next;
while (cur != phead)
{
printf("%d ", cur->data);
cur = cur->next;
}
printf("\n\n");
}
由于没有什么难度,要注意的东西在前面的顺序表和单链表都已经提过了
所以都是直接上代码
增
头插,尾插,在pos之前插入
我们只需要掌握最后一个函数——即在pos之前插入这个函数即可,其他两个函数都是直接调用第三个函数的
void ListInsert(LTN* pos, LTDataType x)//在pos之前插入
{
assert(pos);
LTN* ret = ListBuyNode(x);
ret->next = pos;
ret->prev = pos->prev;
pos->prev->next = ret;
pos->prev = ret;
}
void PushBack(LTN* phead, LTDataType x)//尾插
{
assert(phead);
ListInsert(phead, x);
}
void PuchFront(LTN* phead, LTDataType x)//头插
{
assert(phead);
ListInsert(phead->next, x);
}
删
头删 尾删 删除pos位置
同理 主要掌握第三个函数即可
void ListErase(LTN* pos)//删除pos位置的结点
{
assert(pos);
LTN* prev = pos->prev;
LTN* next = pos->next;
prev->next = next;
next->prev = prev;
/*pos->next->prev = pos->prev;
pos->prev->next = pos->next;*///这两种都是可以的
free(pos);
pos = NULL;
}
void PopFront(LTN* phead)//头删
{
assert(phead);
ListErase(phead->next);
}
void PopBack(LTN* phead)//尾删
{
assert(phead);
ListErase(phead->prev);
}
查
查找这边只是按照数值查找,按照地址查找的话也是一样的
LTN* ListFind(LTN* phead, LTDataType x)//查找x的位置
{
assert(phead);
LTN* cur = phead->next;
while (cur != phead)
{
if (cur->data == x)
return cur;
else
cur = cur->next;
}
return NULL;
}
同志们,双向链表就到这了