一、概念与结构
带头双向循环链表
next :指向下一个结点(后继结点)
prev :指向前一个结点(前驱结点)
二、实现双向链表
项目创建的时候,要创建一个头文件(.h)List.h ,两个源文件(.c)List.c ,test.c 。List.h 用于定义结构体和声明函数;List.c 用于实现函数;test.c 用于测试函数,每实现一个函数要进行相应的测试。编写代码过程中要勤测试,避免写出大量代码后再测试,如果出现问题,问题无从定位。
1、List.h
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
//定义双向链表的结构
typedef int DataType;
typedef struct ListNode
{
DataType data;
struct ListNode* next;
struct ListNode* prev;
}ListNode;
//申请一个新节点
ListNode* buy_Node(DataType x);
//双向链表的初始化,申请一个头结点
ListNode* init_List(void);
//打印双向链表
void print_List(ListNode* head);
//尾插一个结点
void pushback_Node(ListNode* head, DataType x);
//头插一个结点
void pushfront_Node(ListNode* head, DataType x);
//判断链表是否为空链表
bool empty_List(ListNode* head);
//尾删一个结点
void popback_Node(ListNode* head);
//头删一个结点
void popfront_Node(ListNode* head);
//查找指定结点
ListNode* find_Node(ListNode* head, DataType x);
//在 pos 位置之后插入一个结点
void insert_Node(ListNode* pos, DataType x);
//删除指定 pos 位置的结点
void erase_Node(ListNode* pos);
//销毁双向链表
void destory_List(ListNode* head);
2、List.c
#include"List.h"
//申请一个新节点
ListNode* buy_Node(DataType x)
{
ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
if (!newnode)
{
perror("malloc fail!");
exit(1);
}
newnode->data = x;
newnode->next = newnode->prev = newnode;
return newnode;
}
//双向链表的初始化,申请一个头结点
ListNode* init_List(void)
{
ListNode* plist = buy_Node(-1);
return plist;
}
//打印双向链表
void print_List(ListNode* head)
{
ListNode* pcur = head->next;
while (pcur != head)
{
printf("%d -> ", pcur->data);
pcur = pcur->next;
}
printf("\n");
}
//判断链表是否为空链表
bool empty_List(ListNode* head)
{
assert(head);
return head->next != head;
}
//尾插一个结点
void pushback_Node(ListNode* head, DataType x)
{
assert(head);
ListNode* newnode = buy_Node(x);
newnode->next = head;
newnode->prev = head->prev;
head->prev->next = newnode;
head->prev = newnode;
}
//头插一个结点
void pushfront_Node(ListNode* head, DataType x)
{
assert(head);
ListNode* newnode = buy_Node(x);
newnode->next = head->next;
newnode->prev = head;
head->next->prev = newnode;
head->next = newnode;
}
//尾删一个结点
void popback_Node(ListNode* head)
{
assert(empty_List(head));
ListNode* del = head->prev;
head->prev = del->prev;
del->prev->next = head;
free(del);
del = NULL;
}
//头删一个结点
void popfront_Node(ListNode* head)
{
assert(empty_List(head));
ListNode* del = head->next;
del->next->prev = head;
head->next = del->next;
free(del);
del = NULL;
}
//查找指定结点
ListNode* find_Node(ListNode* head, DataType x)
{
assert(head);
ListNode* pcur = head->next;
while (pcur != head)
{
if (pcur->data == x)
return pcur;
pcur = pcur->next;
}
return NULL;
}
//在 pos 位置之后插入一个结点
void insert_Node(ListNode* pos, DataType x)
{
assert(pos);
ListNode* newnode = buy_Node(x);
newnode->next = pos->next;
newnode->prev = pos;
pos->next->prev = newnode;
pos->next = newnode;
}
//删除指定 pos 位置的结点
void erase_Node(ListNode* pos)
{
assert(pos);
pos->next->prev = pos->prev;
pos->prev->next = pos->next;
free(pos);
pos = NULL;
}
//销毁双向链表
void destory_List(ListNode** head)
{
ListNode* pcur = (*head)->next;
while (pcur != *head)
{
ListNode* next = pcur->next;
free(pcur);
pcur = next;
}
free(*head);
*head = NULL;
}
test.c自行测试,这里不予提供。