1、双向链表的结构

注意:
这⾥的“带头”跟前⾯我们说的“头节点”是两个概念,实际前⾯的在单链表阶段称呼不严谨,但是为了同学们更好的理解就直接称为单链表的头节点。带头链表⾥的头节点,实际为“哨兵位”,哨兵位节点不存储任何有效元素,只是站在这⾥“放哨的”。
—
“哨兵位”存在的意义:
遍历循环链表避免死循环。
2、双向链表的实现
1) List.h ——文件
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int LTDataType;
typedef struct ListNode {
LTDataType data;
struct ListNode* next;
struct ListNode* prev;
}LTNode;
void LTInit(LTNode** pphead);
LTNode* LTInit2();
void LTprint(LTNode* phead);
void LTPushBack(LTNode* phead);
void LTPushFront(LTNode* phead);
void LTPopBack(LTNode* phead);
void LTPopFront(LTNode* phead);
LTNode* LTFind(LTNode* phead, LTDataType x);
void LTInsert(LTNode* pos, LTDataType x);
void LTErase(LTNode* phead);
void LTDestroy(LTNode* phead);
2) List.c ——文件
#include"List.h"
void LTInit(LTNode** pphead) {
*pphead = (LTNode*)malloc(sizeof(LTNode));
if (*pphead == NULL) {
perror("malloc error!");
return;
}
(*pphead)->data = -1;
(*pphead)->next = (*pphead)->prev = *pphead;
}
LTNode* LTInit2() {
LTNode* phead = (LTNode*)malloc(sizeof(LTNode));
if (phead == NULL) {
perror("malloc error!");
return;
}
phead->data = -1;
phead->next = phead->prev = phead;
return phead;
}
void LTprint(LTNode* phead) {
assert(phead);
LTNode* tmp = phead->next;
while (tmp != phead) {
printf("%d->", tmp->data);
tmp = tmp->next;
}
printf("\n");
}
LTNode* ListBuyNode(LTDataType x) {
LTNode* node = (LTNode*)malloc(sizeof(LTNode));
if (node == NULL) {
perror("newnode malloc error!");
return;
}
node->data = x;
node->next = node->prev = NULL;
return node;
}
void LTPushBack(LTNode* phead,LTDataType x) {
assert(phead);
LTNode* node = ListBuyNode(x);
node->next = phead;
node->prev = phead->prev;
phead->prev->next = node;
phead->prev = node;
}
void LTPushFront(LTNode* phead, LTDataType x) {
assert(phead);
LTNode* node = ListBuyNode(x);
node->next = phead->next;
node->prev = phead;
phead->next->prev = node;
phead->next = node;
}
void LTPopBack(LTNode* phead) {
assert(phead);
assert(phead->prev != phead);
LTNode* del = phead->prev;
del->prev->next = phead;
phead->prev = del->prev;
free(del);
del = NULL;
}
void LTPopFront(LTNode* phead) {
assert(phead);
assert(phead->next != phead);
LTNode* del = phead->next;
del->next->prev = phead;
phead->next = del->next;
free(del);
del = NULL;
}
LTNode* LTFind(LTNode* phead, LTDataType x) {
assert(phead);
assert(phead->next != phead);
LTNode* find = phead->next;
while (find != phead) {
if (find->data == x) {
return find;
}
find = find->next;
}
printf("所查找的数据不存在!\n");
return NULL;
}
void LTInsert(LTNode* pos, LTDataType x) {
assert(pos);
LTNode* node = ListBuyNode(x);
node->next = pos->next;
node->prev = pos;
pos->next->prev = node;
pos->next = node;
}
void LTErase(LTNode* pos) {
assert(pos);
LTNode* del = pos;
del->prev->next = del->next;
del->next->prev = del->prev;
free(del);
del = NULL;
}
void LTDestroy(LTNode** pphead) {
assert(pphead && *pphead);
LTNode* cur = (*pphead)->next;
while (cur != *pphead) {
LTNode* next = cur->next;
free(cur);
cur = next;
}
free(*pphead);
*pphead = NULL;
}
3) test.c ——文件
#include"List.h"
void testList() {
LTNode* plist = LTInit2();
LTPushBack(plist,1);
LTPushBack(plist,2);
LTPushBack(plist,3);
LTprint(plist);
LTPushFront(plist, 4);
LTPushFront(plist, 5);
LTPushFront(plist, 6);
LTprint(plist);
LTPopBack(plist);
LTprint(plist);
LTPopFront(plist);
LTprint(plist);
LTNode* pos = LTFind(plist, 1);
LTInsert(pos, 100);
LTprint(plist);
LTNode* pos2 = LTFind(plist, 4);
LTErase(pos2);
LTprint(plist);
LTDestroy(&plist);
}
int main()
{
testList();
return 0;
}