.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");
}
}