以下是有关双向链表的一些简单操作,例如增删查改。
link.h
#pragma once
#include <stdio.h>
#define TITLE printf("\n========================%s======================\n",__FUNCTION__);
typedef char DLinkType;
typedef struct DLinkNode
{
DLinkType data;
struct DLinkNode* next;
struct DLinkNode* prev;
}DLinkNode;
DLinkNode* CreateNode(DLinkType value); //创建结点
void DestroyNode(DLinkNode** to_delete);//销毁结点
void DLinkListInit(DLinkNode** head); //初始化
void DLinkListPrint(DLinkNode* head,const char *msg); //链表打印
void DLinkListPushBack(DLinkNode* head, DLinkType value);//尾插一个元素
void DLinkListPopBack(DLinkNode* head);//尾删
void DLinkListPushFront(DLinkNode* head, DLinkType value);//头插一个元素
void DLinkListPopFront(DLinkNode* head);//头删
DLinkNode* DLinkListFind(DLinkNode* head, DLinkType to_find);//查找元素
void DLinkListInsert(DLinkNode*head,DLinkNode* pos, DLinkType value);//指定位置前插入一个元素
void DLinkListInsertAfter(DLinkNode*head,DLinkNode* pos, DLinkType value);//指定位置后插入一个元素
void DLinkListErase(DLinkNode* head,DLinkNode* pos);//删除结点pos
void DLinkListRemove(DLinkNode* head,DLinkType value);//删除指定元素结点
void DLinkListRemoveAll(DLinkNode* head,DLinkType value);//删除指定元素所有结点
size_t DLinkListSize(DLinkNode* head);//返回链表结点数
int DLinkListEmpty(DLinkNode* head);//判断链表是否为空,链表为空返回0,链表不为空返回1
link.c
#include "link.h"
#include <stdlib.h>
#include <stddef.h>
DLinkNode* CreateNode(DLinkType value)
{
DLinkNode* new_node = (DLinkNode*)malloc(sizeof(DLinkNode));
new_node->data = value;
new_node->next = new_node;
new_node->prev = new_node;
return new_node;
}
void DestroyNode(DLinkNode** to_delete)
{
free(*to_delete);
}
void DLinkListPrint(DLinkNode* head,const char* msg)
{
printf("[%s]:\n",msg);
if(head == NULL)
{
return;
}
DLinkNode* cur = head->next;
while(cur != head)
{
printf("[%c|%p] ",cur->data,cur);
cur = cur->next;
}
printf("\n");
cur = head->prev;
while(cur != head)
{
printf("[%c|%p] ",cur->data,cur);
cur = cur->prev;
}
printf("\n");
}
void DLinkListInit(DLinkNode** head)
{
if(head == NULL)
{
//非法输入
return;
}
*head = CreateNode(0);
}
void DLinkListPushBack(DLinkNode* head, DLinkType value)
{
if(head == NULL)
{
//非法输入
return;
}
DLinkNode* tail = head->prev;
DLinkNode* new_node = CreateNode(value);
//tail vs new_node
tail->next = new_node;
new_node->prev = tail;
//head vs new_node
new_node->next = head;
head->prev = new_node;
return;
}
void DLinkListPopBack(DLinkNode* head)
{
if(head == NULL)
{
//非法输入
return;
}
if(head->next == head)
{
DestroyNode(&head);
return;
}
DLinkNode* tail = head->prev;
DLinkNode* Prev = tail->prev;
//Prev vs head
Prev->next = head;
head->prev = Prev;
}
void DLinkListPushFront(DLinkNode* head, DLinkType value)
{
if(head == NULL)
{
return;
}
DLinkNode* new_node = CreateNode(value);
DLinkNode* Prev = head->next;
//new_node vs Prev
new_node->next = Prev;
Prev->prev = new_node;
//new_node vs head
head->next = new_node;
new_node->prev = head;
return;
}
void DLinkListPopFront(DLinkNode* head)
{
if(head == NULL)
{
return;
}
if(head->next == head)
{
DestroyNode(&head);
return;
}
DLinkNode* to_delete = head->next;
DLinkNode* next = to_delete->next;
head->next = next;
next->prev = head;
DestroyNode(&to_delete);
return;
}
DLinkNode* DLinkListFind(DLinkNode* head, DLinkType to_find)
{
if(head == NULL)
{
return NULL;
}
DLinkNode* cur = head->next;
while(cur != head)
{
if(cur->data == to_find)
return cur;
cur = cur->next;
}
return NULL;
}
void DLinkListInsert(DLinkNode*head,DLinkNode* pos, DLinkType value)
{
if(head == NULL)
{
return;
}
if(pos == NULL)
{
return;
}
DLinkNode* new_node = CreateNode(value);
DLinkNode* pos_prev = pos->prev;
//new_node vs pos_prev
pos_prev->next = new_node;
new_node->prev = pos_prev;
//new_node vs pos
new_node->next = pos;
pos->prev = new_node;
}
void DLinkListInsertAfter(DLinkNode*head,DLinkNode* pos, DLinkType value)
{
if(head == NULL)
{
return;
}
if(pos == NULL)
{
return;
}
DLinkNode* new_node = CreateNode(value);
DLinkNode* pos_next = pos->next;
//new_node vs pos
pos->next = new_node;
new_node->prev = pos;
//new_node vs pos->next
new_node->next = pos_next;
pos_next->prev = new_node;
}
void DLinkListErase(DLinkNode* head,DLinkNode* pos)
{
if(head == NULL)
{
return;
}
if(pos == NULL)
{
return;
}
DLinkNode* next = pos->next;
DLinkNode* prev = pos->prev;
//prev vs next
prev->next = next;
next->prev = prev;
DestroyNode(&pos);
return;
}
void DLinkListRemove(DLinkNode* head,DLinkType value)
{
if(head == NULL)
{
return;
}
DLinkNode* cur = head->next;
while(cur != head)
{
if(cur->data == value)
{
DLinkNode* prev = cur->prev;
DLinkNode* next = cur->next;
prev->next = next;
next->prev = prev;
DestroyNode(&cur);
return;
}
cur = cur->next;
}
return;
}
void DLinkListRemoveAll(DLinkNode* head,DLinkType value)
{
if(head == NULL)
{
return;
}
DLinkNode* cur = head->next;
while(cur != head)
{
if(cur->data == value)
{
DLinkNode* prev = cur->prev;
DLinkNode* next = cur->next;
prev->next = next;
next->prev = prev;
DLinkNode* to_delete = cur;
DestroyNode(&to_delete);
cur = prev;
}
cur = cur->next;
}
}
size_t DLinkListSize(DLinkNode* head)
{
if(head == NULL)
{
return 0;
}
size_t count = 0;
DLinkNode* cur = head->next;
while(cur != head)
{
count++;
cur = cur->next;
}
return count;
}
int DLinkListEmpty(DLinkNode* head)
{
if(head == NULL)
{
return 0;
}
if(head->next == head && head->prev == head)
{
return 0;
}
else
{
return 1;
}
}
// 以下为测试代码 //
void TestInit()
{
TITLE;
DLinkNode* head;
DLinkListInit(&head);
DLinkListPrint(head,"打印空链表");
}
void TestDLinkListPushBack()
{
TITLE;
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushBack(head,'a');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'c');
DLinkListPushBack(head,'d');
DLinkListPrint(head,"尾插4个元素");
}
void TestDLinkListPopBack()
{
TITLE;
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushBack(head,'a');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'c');
DLinkListPushBack(head,'d');
DLinkListPrint(head,"尾插4个元素");
DLinkListPopBack(head);
DLinkListPopBack(head);
DLinkListPrint(head,"尾删2个元素");
DLinkListPopBack(head);
DLinkListPopBack(head);
DLinkListPrint(head,"再尾删2个元素");
DLinkListPrint(head,"对空链表进行尾删");
}
void TestDLinkListPushFront()
{
TITLE;
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushFront(head,'a');
DLinkListPushFront(head,'b');
DLinkListPushFront(head,'c');
DLinkListPushFront(head,'d');
DLinkListPrint(head,"头插4个元素");
}
void TestDLinkListPopFront()
{
TITLE;
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushFront(head,'a');
DLinkListPushFront(head,'b');
DLinkListPushFront(head,'c');
DLinkListPushFront(head,'d');
DLinkListPrint(head,"头插4个元素");
DLinkListPopFront(head);
DLinkListPopFront(head);
DLinkListPrint(head,"头删2个元素");
DLinkListPopFront(head);
DLinkListPopFront(head);
DLinkListPrint(head,"再头删2个元素");
DLinkListPrint(head,"头删空链表");
}
void TestDLinkListFind()
{
TITLE;
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushBack(head,'a');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'c');
DLinkListPushBack(head,'d');
DLinkListPrint(head,"尾插4个元素");
DLinkNode* find = DLinkListFind(head,'x');
printf("[查找元素x]:%p\n",find);
find = DLinkListFind(head,'c');
printf("[查找元素c]:%p\n",find);
}
void TestDLinkListInsert()
{
TITLE;
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushBack(head,'a');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'c');
DLinkListPushBack(head,'d');
DLinkListPrint(head,"尾插4个元素");
DLinkNode* pos_a = DLinkListFind(head,'a');
DLinkListInsert(head,pos_a,'x');
DLinkListPrint(head,"元素a之前插入x");
DLinkNode* pos_c = DLinkListFind(head,'c');
DLinkListInsert(head,pos_c,'h');
DLinkListPrint(head,"元素c之前插入h");
}
void TestDLinkListInsertAfter()
{
TITLE
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushBack(head,'a');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'c');
DLinkListPushBack(head,'d');
DLinkListPrint(head,"尾插4个元素");
DLinkNode* pos_a = DLinkListFind(head,'a');
DLinkListInsertAfter(head,pos_a,'x');
DLinkListPrint(head,"元素a之后插入x");
DLinkNode* pos_d = DLinkListFind(head,'d');
DLinkListInsertAfter(head,pos_d,'h');
DLinkListPrint(head,"元素d之后插入h");
}
void TestDLinkListErase()
{
TITLE
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushBack(head,'a');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'c');
DLinkListPushBack(head,'d');
DLinkListPrint(head,"尾插4个元素");
DLinkNode* pos_b = DLinkListFind(head,'b');
DLinkListErase(head,pos_b);
DLinkListPrint(head,"删除结点b");
}
void TestDLinkListRemove()
{
TITLE
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushBack(head,'a');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'c');
DLinkListPushBack(head,'d');
DLinkListPrint(head,"尾插4个元素");
DLinkListRemove(head,'b');
DLinkListPrint(head,"删除元素b结点");
}
void TestDLinkListRemoveAll()
{
TITLE
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushBack(head,'a');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'c');
DLinkListPushBack(head,'d');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'b');
DLinkListPrint(head,"尾插4个元素");
DLinkListRemoveAll(head,'b');
DLinkListPrint(head,"删除所有元素b结点");
}
void TestDLinkListSize()
{
TITLE
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushBack(head,'a');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'c');
DLinkListPushBack(head,'d');
DLinkListPrint(head,"尾插4个元素");
int t = DLinkListSize(head);
printf("[链表长度为]:\nexpect is 4,actul is %d\n",t);
}
void TestDLinkListEmpty()
{
TITLE
DLinkNode* head;
DLinkListInit(&head);
int t = DLinkListEmpty(head);
printf("[链表是否为空]:\nexpect is 0,actul is %d\n",t);
DLinkListPushBack(head,'a');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'c');
DLinkListPushBack(head,'d');
DLinkListPrint(head,"尾插4个元素");
t = DLinkListEmpty(head);
printf("[链表是否为空]:\nexpect is 1,actul is %d\n",t);
}
int main()
{
TestInit();
TestDLinkListPushBack();
TestDLinkListPopBack();
TestDLinkListPushFront();
TestDLinkListPopFront();
TestDLinkListFind();
TestDLinkListInsert();
TestDLinkListInsertAfter();
TestDLinkListErase();
TestDLinkListRemove();
TestDLinkListRemoveAll();
TestDLinkListSize();
TestDLinkListEmpty();
return 0;
}
以下为程序运行结果:
![](https://i-blog.csdnimg.cn/blog_migrate/4297cc305004802dcd18b650164a1b63.png)
![](https://i-blog.csdnimg.cn/blog_migrate/21e469c2270e8d2c5ab93f91297564b7.png)