.h文件
#pragma once
typedef char DLinkType;
typedef struct DLinkNode
{
DLinkType data;
struct DLinkNode* prev;
struct DLinkNode* next;
}DLinkNode;
void DLinkListInit(DLinkNode** phead) ;//初始化
void DLinkListPushBack(DLinkNode* head,DLinkType value);//尾插
void DLinkListPopBack(DLinkNode* head);//尾删
void DLinkListPushFront(DLinkNode* head,DLinkType value);//头插
void DLinkListPopFront(DLinkNode* head);//头删
void DLinkListInsert(DLinkNode* head,DLinkNode* pos,DLinkType value);//在pos前插入;
void DLinkListInsertAfter(DLinkNode* head,DLinkNode* pos,DLinkType value);//在pos后插
DLinkNode* DLinkListFind(DLinkNode* head,DLinkType to_find);//给定一个值查找位置
void DLinkListErase(DLinkNode* head,DLinkNode* to_delete);//删除某个位置上的元素
void DLinkListRemove(DLinkNode* head,DLinkType to_delete_value);//删除第一个值为to_delete_value的元素
void DLinkListRemoveAll(DLinkNode* head,DLinkType to_delete_value);//删除所有值为to_delete_value的元素
void DLinkListDestroy(DLinkNode** phead);//销毁整个链表
size_t DLinkListSize(DLinkNode* head);//求链表元素个数
int DLinkListEmpty(DLinkNode* head);//判断链表是否为空
.c文件
#include"DLinkList.h"
#include <stdio.h>
#include<stdlib.h>
#include<stddef.h>
创建和销毁节点
DLinkNode* CreateDLinkNode(DLinkType value)
{
DLinkNode* new_node = (DLinkNode*)malloc(sizeof(DLinkNode));
new_node->data = value;
new_node->prev = new_node;
new_node->next = new_node;
return new_node;
}
void DestroyDLinkNode(DLinkNode* pos)
{
free(pos);
}
打印链表
void DLinkListPrintChar(DLinkNode* head,const char* msg)
{
printf("[%s]\n",msg);
DLinkNode* cur = head->next;
//先正向打印
for(;cur != head;cur = cur->next )
{
printf("[%c|%p]",cur->data,cur);
}
printf("\n");
//再反向打印
for(cur = head->prev;cur != head;cur = cur->prev )
{
printf("[%c|%p]",cur->data,cur);
}
printf("\n");
return;
}
1.链表的初始化与测试函数
void DLinkListInit(DLinkNode** head)
{
if(head == NULL)
{
//非法输入
return;
}
*head = CreateDLinkNode(0);
}
void TestInit()
{
TEST_HEADER;
DLinkNode* head;
DLinkListInit(&head);
printf("head expected not NULL, actual %p\n",head);
printf("data expect 0,actual %d\n",(int)head->data);
}
2.尾插一个元素
void DLinkListPushBack(DLinkNode* head,DLinkType value)
{
if(head == NULL)
{
//非法输入
return;
}
DLinkNode* tail = head->prev;
//先创建一个值为value的新节点
DLinkNode* new_node = CreateDLinkNode(value);
//head vs new_node
//设置新节点的next值和head的prev值
new_node->next = head;
head->prev = new_node;
//tail vs new_node
//设置最初的尾节点的next值为新节点
//新节点的prev为最初的尾节点
tail->next = new_node;
new_node->prev = tail;
return;
}
void TestPushBack()
{
TEST_HEADER;
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushBack(head,'a');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'c');
DLinkListPushBack(head,'d');
DLinkListPrintChar(head,"尾插四个元素");
}
3.尾删一个元素
void DLinkListPopBack(DLinkNode* head)
{
if(head == NULL)
{
//非法输入
return;
}
if(head->next == head)
{
//空链表
return;
}
DLinkNode* to_delete = head->prev;
DLinkNode* prev = to_delete->prev;
//只需要将倒数第二个元素的next和head的prev进行修改
prev->next = head;
head->prev = prev;
DestroyDLinkNode(to_delete);
return;
}
void TestPopBack()
{
TEST_HEADER;
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushBack(head,'a');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'c');
DLinkListPushBack(head,'d');
DLinkListPrintChar(head,"尾插四个元素");
DLinkListPopBack(head);
DLinkListPopBack(head);
DLinkListPrintChar(head,"尾删两个元素");
DLinkListPopBack(head);
DLinkListPopBack(head);
DLinkListPrintChar(head,"再尾删两个元素");
DLinkListPopBack(head);
DLinkListPrintChar(head,"尝试对空链表进行删除");
}
4.头插一个元素
void DLinkListPushFront(DLinkNode* head,DLinkType value)
{
if(head == NULL)
{
//非法输入
return;
}
DLinkNode* new_node = CreateDLinkNode(value);
DLinkNode* next_node = head->next;
//head vs new_node
//将新节点插入到head后
//修改head的next
//设置新节点的prev为head
head->next = new_node;
new_node->prev = head;
//new_node vs next_node
//设置新节点的next值为原head后的节点
//修改原head后的节点的prev为新节点
new_node->next = next_node;
next_node->prev = new_node;
return;
}
void TestPushFront()
{
TEST_HEADER;
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushFront(head,'a');
DLinkListPushFront(head,'b');
DLinkListPushFront(head,'c');
DLinkListPushFront(head,'d');
DLinkListPrintChar(head,"头插四个元素");
}
5.头删一个元素
void DLinkListPopFront(DLinkNode* head)
{
if(head == NULL)
{
//非法输入
return;
}
if(head->next == head)
{
//空链表
return;
}
DLinkNode* to_delete = head->next;
DLinkNode* next_node = to_delete->next;
//修改head的next值为原第二个元素
head->next = next_node;
//修改原第二个元素的prev为head
next_node->prev = head;
DestroyDLinkNode(to_delete);
return;
}
void TestPopFront()
{
TEST_HEADER;
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushFront(head,'a');
DLinkListPushFront(head,'b');
DLinkListPushFront(head,'c');
DLinkListPushFront(head,'d');
DLinkListPrintChar(head,"头插四个元素");
DLinkListPopFront(head);
DLinkListPopFront(head);
DLinkListPrintChar(head,"头删两个元素");
DLinkListPopFront(head);
DLinkListPopFront(head);
DLinkListPrintChar(head,"再头删两个元素");
DLinkListPopFront(head);
DLinkListPrintChar(head,"尝试对空链表进行头删");
}
6.在pos前插入一个元素
void DLinkListInsert(DLinkNode* head,DLinkNode* pos,DLinkType value)//在pos前插入
{
if(head == NULL || pos == NULL)
{
//非法输入
return;
}
DLinkNode* new_node = CreateDLinkNode(value);
DLinkNode* prev = pos->prev;
//pos vs new_node
//修改pos的prev为新节点
//设置新节点的next值为pos
pos->prev = new_node;
new_node->next = pos;
//prev vs new_node
//修改原pos前一个节点的next值为新节点
//设置新节点的prev为原pos的前一个节点
prev->next = new_node;
new_node->prev = prev;
return;
}
void TestInsert()
{
TEST_HEADER;
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushBack(head,'a');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'c');
DLinkListPushBack(head,'d');
DLinkListInsert(head,head->next->next,'x');
DLinkListPrintChar(head,"在 b 元素之前插入x元素");
}
7.在pos后插入一个元素
void DLinkListInsertAfter(DLinkNode* head,DLinkNode* pos,DLinkType value)
{
if(head == NULL || pos == NULL)
{
//非法输入
return;
}
DLinkNode* new_node = CreateDLinkNode(value);
DLinkNode* next_node = pos->next;
//new_node vs pos
//修改pos的next值为新节点
//设置新节点的prev为pos
pos->next = new_node;
new_node->prev = pos;
//next_node vs next_node
//修改原pos后节点的prev值
//设置新节点的next值为原pos后的节点
next_node->prev = new_node;
new_node->next = next_node;
return;
}
void TestInsertAfter()
{
TEST_HEADER;
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushBack(head,'a');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'c');
DLinkListPushBack(head,'d');
DLinkListInsertAfter(head,head->next->next,'x');
DLinkListPrintChar(head,"在 b 元素之后插入x元素");
}
8.给定一个值查找位置
DLinkNode* DLinkListFind(DLinkNode* head,DLinkType to_find)
{
if(head == NULL)
{
//非法输入
return NULL;
}
DLinkNode* cur = head->next;
for(;cur != head;cur = cur->next)
{
if(cur->data == to_find)//如果cur节点对应的值和我们要找的值相等,则返回该节点
{
return cur;
}
}
return NULL;
}
void TestFind()
{
TEST_HEADER;
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushBack(head,'a');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'c');
DLinkListPushBack(head,'d');
DLinkNode* pos1 = DLinkListFind(head,'b');
printf("pos1 : expected %p ,actual %p \n",head->next->next,pos1);
DLinkNode* pos2 = DLinkListFind(head,'x');
printf("pos2 : expected NULL, actual %p \n",pos2);
}
9.删除某个位置上的元素
void DLinkListErase(DLinkNode* head,DLinkNode* to_delete)
{
if(head == NULL || to_delete == NULL)
{
//非法输入
return;
}
if(head == to_delete)
{
//非法输入,head指向的元素是不能被释放的,除非在销毁整个链表的时候
return;
}
DLinkNode* prev_node = to_delete->prev;//找到要删除节点的前一个节点
DLinkNode* next_node = to_delete->next;//找到要删除节点的后一个节点
//修改前一个节点的next和后一个节点的prev
prev_node->next = next_node;
next_node->prev = prev_node;
DestroyDLinkNode(to_delete);
return;
}
void TestErase()
{
TEST_HEADER;
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushBack(head,'a');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'c');
DLinkListPushBack(head,'d');
DLinkListErase(head,head->next->next);
DLinkListPrintChar(head,"删除链表中的 b 元素");
}
10.删除第一个值为to_delete_value的元素
void DLinkListRemove(DLinkNode* head,DLinkType to_delete_value)
{
if(head == NULL)
{
//非法输入
return;
}
DLinkNode* cur = DLinkListFind(head,to_delete_value);
if(cur == NULL)//如果没有找到值为to_delete_value的元素直接返回不需要再删除
{
//没有
return;
}
DLinkListErase(head,cur);
}
void TestRemove()
{
TEST_HEADER;
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushBack(head,'a');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'c');
DLinkListPushBack(head,'d');
DLinkListRemove(head,'b');
DLinkListPrintChar(head,"删除链表中的第一个 b 元素");
}
11.删除所有值为to_delete_value的元素
void DLinkListRemoveAll(DLinkNode* head,DLinkType to_delete_value)
{
if(head == NULL)
{
//非法输入
return;
}
DLinkNode* cur = head->next;
while(cur != head)
{
if(cur->data == to_delete_value)
//如果cur指向的节点里的值和要删除元素的值相等,就删除该节点
{
DLinkListErase(head,cur);
}
cur = cur->next;
}
return;
}
void TestRemoveAll()
{
TEST_HEADER;
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushBack(head,'a');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'c');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'d');
DLinkListPushBack(head,'b');
DLinkListRemoveAll(head,'b');
DLinkListPrintChar(head,"删除链表中所有的 b 元素");
}
12.销毁整个链表
void DLinkListDestroy(DLinkNode** phead)
{
if(phead == NULL)
{
return;
}
DLinkNode* cur = (*phead)->next;
while(cur != *phead)//先删除除了head的其他节点
{
DLinkNode* next = cur->next;
DestroyDLinkNode(cur);
cur = next;
}
DestroyDLinkNode(*phead);//销毁头节点
*phead = NULL;//将头节点置空,若不置空就成了野指针
}
void TestDestroy()
{
TEST_HEADER;
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushBack(head,'a');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'c');
DLinkListPushBack(head,'d');
DLinkListDestroy(&head);
}
13.求链表中的元素个数
size_t DLinkListSize(DLinkNode* head)
{
if(head == NULL)
{
//非法输入
return 0;
}
DLinkNode* cur = head->next;
size_t i = 0;
//cur从head的next开始走,走一步i++,直到最后一个元素
for(;cur != head;cur = cur->next)
{
i++;
}
return i;
}
void TestSize()
{
TEST_HEADER;
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushBack(head,'a');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'a');
DLinkListPushBack(head,'c');
DLinkListPushBack(head,'a');
DLinkListPushBack(head,'d');
size_t i = DLinkListSize(head);
DLinkListPrintChar(head,"打印链表中的元素");
printf("size is :%d\n",i);
}
14.判断链表是否为空,若为空返回1,不为空返回2
int DLinkListEmpty(DLinkNode* head)
{
if(head == NULL)
{
//非法输入
return 0;
}
if(head->next == head)//如果head的next还是head的话该链表就没有元素
{
return 1;
}
return 2;
}
void TestEmpty()
{
TEST_HEADER;
DLinkNode* head1;
DLinkListInit(&head1);
int a = DLinkListEmpty(head1);
DLinkListPrintChar(head1,"打印链表中的元素");
if(a == 1)
{
printf("该链表为空\n");
}
else
{
printf("该链表不为空\n");
}
DLinkNode* head2;
DLinkListInit(&head2);
DLinkListPushBack(head2,'a');
DLinkListPushBack(head2,'b');
DLinkListPushBack(head2,'a');
DLinkListPushBack(head2,'c');
int b = DLinkListEmpty(head2);
DLinkListPrintChar(head2,"打印链表中的元素");
if(b == 1)
{
printf("该链表为空\n");
}
else
{
printf("该链表不为空\n");
}
}