C语言实现双向链表的基本功能
1.尾插
2.尾删
3.头插
4.头删
5.查找指定元素的位置
6.在指定位置之前插入元素
7.在指定位置之后插入元素
8.删除指定位置的元素
9.删除指定值的元素
10.删除指定所有相同的元素
11.求链表的长度
12.判断链表是否为空
头文件
文件名dlinklist.h
#pragma once //防止头文件重复定义
#include<stdio.h>
#include<stdlib.h>
#include<stddef.h>
typedef char DLinktype;
typedef struct DLinkNode
{
DLinktype data; // 存放数据
struct DLinkNode* next; //定义后一个节点
struct DLinkNode* prev; //定义前一个节点
}DLinkNode;
//初始化函数
void DLinklistInit(DLinkNode** phead);
//链表尾插
DLinkNode* DLinklistPushback(DLinkNode* head, DLinktype value);
//链表尾删
void DLinklistPopback(DLinkNode* head);
//链表头插
void DLinklistPushfront(DLinkNode* head, DLinktype value);
//链表头删
void DLinklistPopfront(DLinkNode* head);
//查找指定元素的位置
DLinkNode* DLinklistFind(DLinkNode* head, DLinktype value);
// 在指定位置之前插入元素
void DLinklistInsert(DLinkNode* head, DLinkNode* pos, DLinktype value);
// 在指定位置之后插入元素
void DLinklistInsertafter(DLinkNode* head, DLinkNode* pos, DLinktype value);
//删除指定位置的元素
void DLinklistErase(DLinkNode*head, DLinkNode* to_delete);
//删除指定值的元素
void DLinklistRemove(DLinkNode* head, DLinktype to_remove);
//删除指定值的所有元素
void DLinklistRemoveall(DLinkNode* head, DLinktype to_remove);
//求链表的长度
size_t DLinklistSize(DLinkNode* head);
//判断链表是否为空
int DLinklistEmpty(DLinkNode* head);
功能实现
文件名 dlinklist.c
#include"dlinklist.h"
//创建新节点
DLinkNode* DLinkNodeCreat(DLinktype value)
{
DLinkNode* new = (DLinkNode*)malloc(sizeof(DLinkNode)); //创建节点申请空间
new->data = value; //
new->next = NULL;
new->prev = NULL;
return new;
}
//销毁节点
void DLinkNodeDestroy(DLinkNode* node)
{
free(node);
node = NULL;
}
//初始化函数
void DLinklistInit(DLinkNode** phead)
{
if (phead == NULL)
{
printf("非法输入");
return;
}
*phead = DLinkNodeCreat(0); //创建一个不具有实际意义的头节点,
(*phead)->next = *phead;
(*phead)->prev = *phead;
}
//链表尾插
DLinkNode* DLinklistPushback(DLinkNode* head, DLinktype value)
{
if (head == NULL)
{
printf("非法输入");
return NULL;
}
DLinkNode* new = DLinkNodeCreat(value);
DLinkNode* tail = head->prev;
//head 2-2 new
new->next = head;
head->prev = new;
//tail 2-2 new
tail->next = new;
new->prev = tail;
return new;
}
//链表尾删
void DLinklistPopback(DLinkNode* head)
{
if (head == NULL)
{
printf("非法输入");
return;
}
if (head->next == head || head->prev == head)
{
printf("空链表");
return;
}
DLinkNode* lastone = head->prev;
DLinkNode* lasttwo = lastone->prev;
lasttwo->next = head;
head->prev = lasttwo;
DLinkNodeDestroy(lastone);
}
//链表头插
void DLinklistPushfront(DLinkNode* head, DLinktype value)
{
if (head == NULL)
{
printf("非法输入");
return;
}
DLinkNode* new = DLinkNodeCreat(value);
DLinkNode* second = head->next;
// sencond new
new->next = second;
second->prev = new;
// head new
head->next = new;
new->prev = head;
}
//链表头删
void DLinklistPopfront(DLinkNode* head)
{
if (head == NULL)
{
printf("非法输入");
return;
}
if (head->next == head || head->prev == head)
{
printf("空链表");
return;
}
DLinkNode* second = head->next;
DLinkNode* third = second->next;
head->next = third;
third->prev = head;
DLinkNodeDestroy(second);
}
//查找指定元素的位置
DLinkNode* DLinklistFind(DLinkNode* head, DLinktype to_find)
{
if (head == NULL)
{
printf("非法输入");
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 || pos == NULL)
{
printf("非法输入");
return;
}
DLinkNode* pospre = pos->prev;
DLinkNode* new = DLinkNodeCreat(value);
//pospre new
new->prev = pospre;
pospre->next = new;
//new pos
new->next = pos;
pos->prev = new;
}
// 在指定位置之后插入元素
void DLinklistInsertafter(DLinkNode* head, DLinkNode* pos, DLinktype value)
{
if (head == NULL || pos == NULL)
{
printf("非法输入");
return;
}
DLinkNode* new = DLinkNodeCreat(value);
DLinkNode* posafter = pos->next;
// pos new
pos->next = new;
new->prev = pos;
//new posafter
new->next = posafter;
posafter->prev = new;
}
//删除指定位置的元素
void DLinklistErase(DLinkNode*head, DLinkNode* to_delete)
{
if (head == NULL || to_delete == NULL)
{
printf("非法输入");
return;
}
DLinkNode* after = to_delete->next;
DLinkNode* before = to_delete->prev;
before->next=after;
after->prev = before;
DLinkNodeDestroy(to_delete);
}
//删除指定值的元素
void DLinklistRemove(DLinkNode* head, DLinktype to_remove)
{
if (head == NULL )
{
printf("非法输入");
return;
}
DLinkNode* pos = DLinklistFind(head, to_remove);
DLinklistErase(head, pos);
}
//删除指定值的所有元素
void DLinklistRemoveall(DLinkNode* head, DLinktype value)
{
if (head == NULL)
{
printf("非法输入");
return;
}
DLinkNode* cur = head->next;
while (cur != head)
{
if (cur->data == value)
{
DLinkNode* before = cur->prev;
DLinkNode* after = cur->next;
before->next = after;
after->prev = before;
DLinkNode* tmp = cur;
DLinkNodeDestroy(tmp);
cur = before;
}
cur = cur->next;
}
}
//求链表的长度
size_t DLinklistSize(DLinkNode* head)
{
if (head == NULL)
{
printf("非法输入");
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 -1;
}
if (head->next == head){
return 1;
}
return 0;
}
测试代码
文件名test.c
#include"linknode.h"
#define FUNCTION() printf("****** %s ***********\n",__FUNCTION__) ;
void Printchar(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");
//逆序打印
DLinkNode* ret = head->prev;
while (ret != head)
{
printf("[%c|%p]", ret->data, ret);
ret = ret->prev;
}
printf("\n");
}
void TestDInit()
{
FUNCTION();
DLinkNode* head;
DLinklistInit(&head);
}
void TestPushback()
{
FUNCTION();
DLinkNode* head;
DLinklistInit(&head);
DLinklistPushback(head, 'a');
DLinklistPushback(head, 'b');
DLinklistPushback(head, 'c');
DLinklistPushback(head, 'd');
Printchar(head, "尾插四个元素");
}
void TestPopback()
{
FUNCTION();
DLinkNode* head;
DLinklistInit(&head);
DLinklistPushback(head, 'a');
DLinklistPushback(head, 'b');
DLinklistPushback(head, 'c');
DLinklistPushback(head, 'd');
Printchar(head, "先插四个元素");
DLinklistPopback(head);
DLinklistPopback(head);
Printchar(head, "尾删两个元素");
DLinklistPopback(head);
DLinklistPopback(head);
Printchar(head, "再尾删两个元素");
DLinklistPopback(head);
Printchar(head, "尝试对空链表尾删");
}
void TestPushfront()
{
FUNCTION();
DLinkNode* head;
DLinklistInit(&head);
DLinklistPushfront(head, 'a');
DLinklistPushfront(head, 'b');
DLinklistPushfront(head, 'c');
DLinklistPushfront(head, 'd');
Printchar(head, "头插四个元素");
}
void TestPopfront()
{
FUNCTION();
DLinkNode* head;
DLinklistInit(&head);
DLinklistPushback(head, 'a');
DLinklistPushback(head, 'b');
DLinklistPushback(head, 'c');
DLinklistPushback(head, 'd');
Printchar(head, "尾插四个元素");
DLinklistPopfront(head);
DLinklistPopfront(head);
Printchar(head, "头删两个元素");
DLinklistPopfront(head);
DLinklistPopfront(head);
Printchar(head, "再头删两个元素");
DLinklistPopfront(head);
DLinklistPopfront(head);
Printchar(head, "尝试对空链表头删");
}
void TestFind()
{
FUNCTION();
DLinkNode* head;
DLinklistInit(&head);
DLinklistPushback(head, 'a');
DLinklistPushback(head, 'b');
DLinklistPushback(head, 'c');
DLinklistPushback(head, 'd');
Printchar(head, "尾插四个元素");
DLinkNode* cur = DLinklistFind(head, 'c');
printf("元素c的位置:%p\n", cur);
}
void TestInsert()
{
FUNCTION();
DLinkNode* head;
DLinklistInit(&head);
DLinklistPushback(head, 'a');
DLinklistPushback(head, 'b');
DLinklistPushback(head, 'c');
DLinklistPushback(head, 'd');
Printchar(head, "尾插四个元素");
DLinkNode* pos = DLinklistFind(head, 'c');
DLinklistInsert(head, pos, 'X');
Printchar(head, "C之前插入元素X");
}
void TestInsertafter()
{
FUNCTION();
DLinkNode* head;
DLinklistInit(&head);
DLinklistPushback(head, 'a');
DLinklistPushback(head, 'b');
DLinklistPushback(head, 'c');
DLinklistPushback(head, 'd');
Printchar(head, "尾插四个元素");
DLinkNode* pos = DLinklistFind(head, 'c');
DLinklistInsertafter(head, pos, 'Y');
Printchar(head, "C之后插入元素Y");
}
void TestErase()
{
FUNCTION();
DLinkNode* head;
DLinklistInit(&head);
DLinklistPushback(head, 'a');
DLinklistPushback(head, 'b');
DLinklistPushback(head, 'c');
DLinklistPushback(head, 'd');
Printchar(head, "尾插四个元素");
DLinkNode* pos = DLinklistFind(head, 'c');
DLinklistErase(head, pos);
Printchar(head, "删除元素c");
}
void TestRemove()
{
FUNCTION();
DLinkNode* head;
DLinklistInit(&head);
DLinklistPushback(head, 'a');
DLinklistPushback(head, 'b');
DLinklistPushback(head, 'c');
DLinklistPushback(head, 'd');
Printchar(head, "尾插四个元素");
DLinklistRemove(head, 'c');
Printchar(head, "删除元素c");
}
void TestRemoveall()
{
FUNCTION();
DLinkNode* head;
DLinklistInit(&head);
DLinklistPushback(head, 'a');
DLinklistPushback(head, 'b');
DLinklistPushback(head, 'c');
DLinklistPushback(head, 'd');
DLinklistPushback(head, 'c');
Printchar(head, "尾插五个元素");
DLinklistRemoveall(head, 'c');
Printchar(head, "删除元素c");
}
void TestSize()
{
FUNCTION();
DLinkNode* head;
DLinklistInit(&head);
DLinklistPushback(head, 'a');
DLinklistPushback(head, 'b');
DLinklistPushback(head, 'c');
DLinklistPushback(head, 'd');
Printchar(head, "尾插四个元素");
size_t count = DLinklistSize(head);
printf("链表的长度为:%lu\n", count);
}
void TestEmpty()
{
FUNCTION();
DLinkNode* head;
DLinklistInit(&head);
DLinklistPushback(head, 'a');
DLinklistPushback(head, 'b');
DLinklistPushback(head, 'c');
DLinklistPushback(head, 'd');
Printchar(head, "尾插四个元素");
int ret = DLinklistEmpty(head);
printf("expect result is 0,actual is %d\n", ret);
}
int main()
{
TestPushback();
TestPopback();
TestPushfront();
TestPopfront();
TestFind();
TestInsert();
TestInsertafter();
TestErase();
TestRemove();
TestRemoveall();
TestSize();
TestEmpty();
return 0;
}