目录
1 功能介绍
- 双向链表销毁
- 双向链表打印
- 双向链表尾插
- 双向链表尾删
- 双向链表头插
- 双向链表头删
- 双向链表查找
- 双向链表在pos位置前插入元素
- 双向链表删除pos位置结点
2 头文件内容
#ifndef _DList_H
#define _DList_H
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int LTDataType;
typedef struct ListNode
{
LTDataType _data;
struct ListNode* next; // 指向下一个结点
struct ListNode* prev; // 指向前一个结点
}ListNode;
//初始化
void ListInit(ListNode** head);
//双向链表销毁
void ListDestory(ListNode* plist);
//双向链表打印
void ListPrint(ListNode* plist);
//双向链表大小
int ListSize(ListNode* head);
//双向链表判空
int ListEmpty(ListNode* head);
//双向链表尾插
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);
#endif
3 头文件内容实现
#include"DList.h"
//创建新结点
ListNode* BuyListNode(LTDataType x)
{
ListNode* newNode = (ListNode*)malloc(sizeof(LTDataType));
if (NULL == newNode){
printf("开辟新结点失败\n");
return NULL;
}
newNode->_data = x;
newNode->next = NULL;
newNode->prev = NULL;
return newNode;
}
//初始化
void ListInit(ListNode** head)
{
if (head == NULL){
return;
}
*head = BuyListNode(0);
(*head)->next = *head;//让头节点的指向循环起来
(*head)->prev = *head;
}
//双向链表销毁
void ListDestory(ListNode* head){
//创造创建新节点位于链表起始位置,准备遍历链表清空节点
ListNode* cur = head->next;
//清空链表中节点
while (cur != head){
head->next = cur->next;//保存下一位节点
free(cur);//释放该节点
cur = cur->next;
}
//清理头节点
free(head);
head = NULL;
}
//双向链表打印
void ListPrint(ListNode* head){
//创造创建新节点位于链表起始位置,准备遍历链表打印节点
ListNode* cur = head->next;
//打印链表中节点
while (cur != head){
printf("%d ", cur->_data);
cur = cur->next;
}
}
//双向链表大小
int ListSize(ListNode* head){
//创建新节点和计数器位于链表起始位置,准备遍历链表进行计数
ListNode* cur = head->next;
int count = 0;
//遍历链表
while (cur != head){
cur = cur->next;
count++;
}
//遍历完成之后返回计数器
return count;
}
//双向链表判空
int ListEmpty(ListNode* head){
assert(head);
// 若头节点指向自身说明链表中不存在内容,即链表为空返回1
return head->next == head;
}
//双向链表尾插
void ListPushBack(ListNode* head, LTDataType x){
//链表的尾插就相当于头节点之前插入元素
ListInsert(head, x);
}
//双向链表尾删
void ListPopBack(ListNode* head){
//保证链表不为空方可尾删
if (ListEmpty(head)){
return;
}
//链表的首元素是头节点的下一位指向
ListErase(head->next);
}
//双向链表头插
void ListPushFront(ListNode* head, LTDataType x){
//链表头插就相当于在头节点的后一个节点前插入元素
ListInsert(head->next, x);
}
//双向链表头删
void ListPopFront(ListNode* head){
//保证链表不为空方可头删
if (ListEmpty(head)){
return;
}
//链表的首元素是头节点的上一位指向
ListErase(head->prev);
}
//双向链表查找
ListNode* ListFind(ListNode* head, LTDataType x){
//创建新节点位于链表起始位置,准备遍历链表查找元素
ListNode* cur = head->next;
//遍历链表
while (cur != head){
if (cur->_data == x){
return cur;
}
cur = cur->next;
}
//遍历未返回元素则节点中不存在元素x
return NULL;
}
//双向链表在pos位置前插入元素
void ListInsert(ListNode* pos, LTDataType x){
//判断插入位置pos的合法性
if (pos == NULL){
return;
}
//1.根据插入元素x创建新节点
ListNode* newNode = BuyListNode(x);
//2.先将新节点连接到pos之前(防止节点丢失)
newNode->next = pos;
newNode->prev = pos->prev;
//3.断开原两节点之间的连接
newNode->prev->next = newNode;
pos->prev = newNode;
}
//双向链表删除pos位置结点
void ListErase(ListNode* pos){
//判断删除位置pos的合法性
if (pos == NULL){
return;
}
//1.让pos位置的前后节点互相指向
pos->prev->next = pos->next;
pos->next->prev = pos->prev;
//2.释放资源
free(pos);
}
4 测试用主函数
int main()
{
ListNode* head = NULL;
ListInit(&head);
if (ListEmpty(head) == 1){
printf("链表为空\n");
}
ListPushFront(head, 1);
ListPushFront(head, 2);
ListPushFront(head, 3);
ListPrint(head);
printf("\n");
printf("Size==%d\n", ListSize(head));
ListPushBack(head, 4);
ListPushBack(head, 5);
ListPushBack(head, 6);
ListPrint(head);
printf("\n");
printf("Size==%d\n", ListSize(head));
return 0;
}