目录
之前写少了一个东西——哨兵位,它是先建立一个节点,然后next指向空,之后在next指向的位置开始插入,也就是next = newhead,哨兵位用在尾插上是比较合适的。
进入正题
学了单链表后,双向循环链表就会变得简单。虽然结构稍复杂一点,但实际操作轻松不少。
双向链表.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <stdbool.h>
typedef int LTDataType;
typedef struct ListNode
{
struct ListNode* prev;
struct ListNode* next;
LTDataType data;
}LTNode;
LTNode* BuyListNode(LTDataType x);
LTNode* LTInit();
void LTPrint(LTNode* phead);
//尾插尾删
void LTPushBack(LTNode* phead, LTDataType x);
void LTPopBack(LTNode* phead);
//头插头删
void LTPushFront(LTNode* phead, LTDataType x);
void LTPopFront(LTNode* phead);
LTNode* LTFind(LTNode* phead, LTDataType x);
//在pos之前插入
void LTInsert(LTNode* pos, LTDataType x);
//删除pos位置
void LTErase(LTNode* pos);
bool LTEmpty(LTNode* phead);
size_t LTSize(LTNode* phead);
void LTDestroy(LTNode* phead);
双向链表.c
LTNode* BuyListNode(LTDataType x)
{
LTNode* node = (LTNode*)malloc(sizeof(LTNode));
if (node == NULL)
{
perror("malloc fail");
exit(-1);
}
node->data = x;
node->next = NULL;
node->prev = NULL;
return node;
}
LTNode* LTInit()
{
LTNode* phead = BuyListNode(-1);
phead->next = phead;
phead->prev = phead;
return phead;
}
void LTPrint(LTNode* phead)
{
assert(phead);
LTNode* cur = phead->next;
while (cur != phead)
{
printf("%d ", cur->data);
cur = cur->next;
}
printf("\n");
}
void LTPushBack(LTNode* phead, LTDataType x)
{
assert(phead);
/*LTNode* newnode = BuyListNode(x);
LTNode* tail = phead->prev;
tail->next = newnode;
newnode->prev = tail;
newnode->next = phead;
phead->prev = newnode;*/
LTInsert(phead, x);
}
void LTPopBack(LTNode* phead)
{
assert(phead);
assert(phead->next != phead); // 空
//LTNode* tail = phead->prev;
//LTNode* tailPrev = tail->prev;
//tailPrev->next = phead;
//phead->prev = tailPrev;
//free(tail);
LTErase(phead->prev);
}
void LTPushFront(LTNode* phead, LTDataType x)
{
assert(phead);
/*LTNode* newnode = BuyListNode(x);
newnode->next = phead->next;
phead->next->prev = newnode;
phead->next = newnode;
newnode->prev = phead;*/
//LTNode* newnode = BuyListNode(x);
//LTNode* first = phead->next;
phead newnode first
顺序无关
//phead->next = newnode;
//newnode->prev = phead;
//newnode->next = first;
//first->prev = newnode;
LTInsert(phead->next, x);
}
void LTPopFront(LTNode* phead)
{
assert(phead);
assert(phead->next != phead); // 空
/*LTNode* first = phead->next;
LTNode* second = first->next;
free(first);
phead->next = second;
second->prev = phead;*/
LTErase(phead->next);
}
LTNode* LTFind(LTNode* phead, LTDataType x)
{
assert(phead);
LTNode* cur = phead->next;
while (cur != phead)
{
if (cur->data == x)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
// 在pos之前插入x
void LTInsert(LTNode* pos, LTDataType x)
{
assert(pos);
LTNode* prev = pos->prev;
LTNode* newnode = BuyListNode(x);
// prev newnode pos
prev->next = newnode;
newnode->prev = prev;
newnode->next = pos;
pos->prev = newnode;
}
// 删除pos位置
void LTErase(LTNode* pos)
{
assert(pos);
LTNode* prev = pos->prev;
LTNode* next = pos->next;
free(pos);
prev->next = next;
next->prev = prev;
}
bool LTEmpty(LTNode* phead)
{
assert(phead);
/*if (phead->next == phead)
{
return true;
}
else
{
return false;
}*/
return phead->next == phead;
}
size_t LTSize(LTNode* phead)
{
assert(phead);
size_t size = 0;
LTNode* cur = phead->next;
while (cur != phead)
{
++size;
cur = cur->next;
}
return size;
}
void LTDestroy(LTNode* phead)
{
assert(phead);
LTNode* cur = phead->next;
while (cur != phead)
{
LTNode* next = cur->next;
free(cur);
cur = next;
}
free(phead);
//phead = NULL;
}
test.c
void TestList1()
{
LTNode* phead = BuyListNode(-1);
phead->prev = phead;
phead->next = phead;
//没有办法LTNode* phead = LTInit(phead), 总是在说使用未初始化的变量,嗯,毛病太多了
LTPushBack(phead, 1);
LTPushBack(phead, 2);
LTPushBack(phead, 3);
LTPushBack(phead, 4);
LTPrint(phead);
LTPopBack(phead);
LTPrint(phead);
LTPopBack(phead);
LTPrint(phead);
LTPopBack(phead);
LTPrint(phead);
LTPopBack(phead);
LTPrint(phead);
}
void TestList2()
{
LTNode* phead = BuyListNode(-1);
phead->prev = phead;
phead->next = phead;
LTPushFront(phead, 1);
LTPushFront(phead, 2);
LTPushFront(phead, 3);
LTPushFront(phead, 4);
LTPrint(phead);
LTPopFront(phead);
LTPrint(phead);
LTPopFront(phead);
LTPrint(phead);
LTPopFront(phead);
LTPrint(phead);
LTPopFront(phead);
LTPrint(phead);
}
void TestList3()
{
LTNode* phead = BuyListNode(-1);
phead->prev = phead;
phead->next = phead;
LTPushFront(phead, 1);
LTPushFront(phead, 2);
LTPushFront(phead, 3);
LTPushFront(phead, 4);
LTPrint(phead);
LTNode* pos = LTFind(phead, 3);
if (pos)
{
pos->data *= 10;
}
LTPrint(phead);
LTDestroy(phead);
phead = NULL;
}
int main()
{
TestList3();
return 0;
}
其实是觉得没什么细讲的,就只发了代码。
结束。