如有错误欢迎指正
文章目录
前言
本文是带头双向循环的双链表
一、头文件List.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
typedef int LTDataType;
typedef struct ListNode
{
LTDataType data;
struct ListNode* next;
struct ListNode* prev;
}ListNode;
// 创建返回链表的结点.
ListNode* ListCreate();
//初始化
ListNode* LTInit();
// 双向链表销毁
void ListDestory(ListNode* plist);
//检查链表是否为空
bool LTEmpty(ListNode* plist);
// 双向链表打印
void ListPrint(ListNode* plist);
// 双向链表尾插
void ListPushBack(ListNode* plist, LTDataType x);
// 双向链表尾删
void ListPopBack(ListNode* plist);
// 双向链表头插
void ListPushFront(ListNode* plist, LTDataType x);
// 双向链表头删
void ListPopFront(ListNode* plist);
// 双向链表查找
ListNode* ListFind(ListNode* plist, LTDataType x);
// 双向链表在pos的前面进行插入
void ListInsert(ListNode* pos, LTDataType x);
// 双向链表删除pos位置的结点
void ListErase(ListNode* pos);
二、List.c
1.创建链表的结点
代码如下(示例):
#include"List.h"
// 创建链表的结点.
ListNode* ListCreate(LTDataType x)
{
ListNode* node = (ListNode*)malloc(sizeof(ListNode));
if (node == NULL)
{
perror("malloc fail");
exit(-1);
}
node->data = x;
node->next = node->prev = NULL;
return node;
}
2.初始化,创建头节点
代码如下(示例):
ListNode* LTInit()
{
ListNode* head = ListCreate(-1);
head->next = head;
head->prev = head;
return head;
}
3.双向链表销毁
void ListDestory(ListNode* plist)
{
assert(plist);
ListNode* cur = plist->next;
while (cur != plist)
{
ListNode* next = cur->next;
free(cur);
cur = next;
}
free(plist);
plist = NULL;
}
4.检查链表是否为空
bool LTEmpty(ListNode* plist)
{
assert(plist);
return plist->next == plist;
}
5.双向链表打印
void ListPrint(ListNode* plist)
{
assert(plist);
printf("head<=>");
ListNode* cur = plist->next;
while (cur != plist)
{
printf("%d<=>", cur->data);
cur = cur->next;
}
printf("\n");
}
6.双向链表尾插
void ListPushBack(ListNode* plist, LTDataType x)
{
assert(plist);ListNode* newnode = ListCreate(x);
ListNode* tail = plist->prev;
tail->next = newnode;
newnode->prev = tail;
newnode->next = plist;
plist->prev = newnode;
}
7.双向链表尾删
void ListPopBack(ListNode* plist)
{
assert(plist);
assert(!LTEmpty(plist));
ListNode* newtail = plist->prev->prev;
ListNode* cur = plist->prev;
free(cur);
cur = NULL;
plist->prev = newtail;
newtail->next = plist;
}
8.双向链表头插
void ListPushFront(ListNode* plist, LTDataType x)
{
assert(plist);
ListNode* newnode = ListCreate(x);
ListNode* cur = plist->next;
newnode->next = cur;
plist->next = newnode;
cur->prev = newnode;
newnode->prev = plist;
}
9. 双向链表头删
void ListPopFront(ListNode* plist)
{
assert(plist);
assert(!LTEmpty(plist));
ListNode* cur = plist->next->next;
ListNode* del = plist->next;
plist->next = cur;
cur->prev = plist;
free(del);
del = NULL;
}
10. 双向链表查找
ListNode* ListFind(ListNode* plist, LTDataType x)
{
assert(plist);
ListNode* cur = plist->next;
while (cur != plist)
{
if (cur->data == x)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
11. 双向链表在pos的前面进行插入
void ListInsert(ListNode* pos, LTDataType x)
{
assert(pos);
ListNode* cur = pos->prev;
ListNode* newnode = ListCreate(x);
cur->next = newnode;
newnode->next = pos;
pos->prev = newnode;
newnode->prev = cur;}
12.双向链表删除pos位置的结点
void ListErase(ListNode* pos)
{
assert(pos);
ListNode* pre = pos->prev;
ListNode* net = pos->next;
pre->next = net;
net->prev = pre;
free(pos);
pos = NULL;
}
总结
双链表结构听起来复杂,其实实现要比单链表简单。
链表和顺序表各有好处:顺序表主要应用于元素高效存储+频繁访问,链表主要应用在任意位置插入和删除频繁