網站首頁 編程語言 正文
實現細節
1、帶一個哨兵位(哨兵節點,初始節點,不存儲有效數據,用來方便后期數據的存儲與查找)
2、與單向鏈表不同的是,雙向鏈表中每個數據節點包含兩個指針,分別指向前后兩個節點
3、雙向鏈表是循環的,其尾節點后不是空指針,而是與頭部的哨兵節點通過指針相連
輔助理解圖
具體實現代碼
1、對鏈表進行初始化
初始化:哨兵位的前后指針均指向哨兵節點本身
void ListInit(ListNode** pphead)
{
*pphead = (ListNode*)malloc(sizeof(ListNode));
if (*pphead == NULL)
{
perror("ListInit");
exit(-1);
}
(*pphead)->date = -1;
(*pphead)->next = *pphead;
(*pphead)->prev = *pphead;
}
2、任意位置前的插入
注意:插入位置前后節點中的前后指針要進行相應的更換
void Any_insert(ListNode* pos,Listtype date)
{
ListNode* Prev = pos->prev;
//建立新節點
ListNode* NewNode = (ListNode*)malloc(sizeof(ListNode));
if (NewNode == NULL)
{
perror("Any_insert");
exit(-1);
}
NewNode->date = date;
NewNode->next = pos;
pos->prev = NewNode;
Prev->next = NewNode;
NewNode->prev = Prev;
}
3、任意位置的刪除
細節點:當鏈表中沒有數據時,就不用刪除,因此需要建立一個函數進行判斷
bool Determine(ListNode* pphead)
{//判斷鏈表中有無元素
assert(pphead);
return pphead == pphead->next;
}
void Any_delet(ListNode* pos)
{
assert(!Determine(pos));
ListNode* Next = pos->next;
ListNode* Prev = pos->prev;
Next->prev = Prev;
Prev->next = Next;
free(pos);
}
4、頭插和尾刪
此處的插入和刪除,十分方便,即:對上面的任插和任刪進行套用
頭插如下:
void Head_insert(ListNode* pphead, Listtype date)
{
ListNode* NewNode = (ListNode*)malloc(sizeof(ListNode));
if (NewNode == NULL)
{
perror("Head_insert");
exit(-1);
}
//單獨實現
//NewNode->date = date;
//NewNode->prev = pphead;
//NewNode->next = pphead->next;
//pphead->next->prev = NewNode;
//pphead->next = NewNode;
//進行任插的復用
Any_insert(pphead->next ,date);
}
尾刪如下:
void Tail_delet(ListNode* pphead)
{
assert(pphead);
//單獨實現
//assert(Determine(pphead));
/*ListNode* tail = pphead->prev;
if (tail != pphead)
{
ListNode* tailprev = tail->prev;
tailprev->next = pphead;
pphead->prev = tailprev;
free(tail);
}*/
//尾刪的復用
Any_delet(pphead->prev);
}
完整代碼
頭文件
#pragma once
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
typedef int Listtype;
typedef struct ListNode
{
struct ListNode* prev;
Listtype date;
struct ListNode* next;
}ListNode;
void ListInit(ListNode** pphead); //鏈表初始化
void ListNode_ADD(ListNode* pphead, Listtype date); //尾插
void Head_insert(ListNode* pphead, Listtype date); //頭插
void ListNode_Print(ListNode* pphead); //鏈表打印
void Tail_delet(ListNode* pphead); //尾刪
bool Determine(ListNode* pphead); //判斷表中有無數據
void Any_insert(ListNode* pos, Listtype date); //任插
void Any_delet(ListNode* pos); //任刪
void List_Destory(ListNode* pos); //鏈表清空
具體函數
#define _CRT_SECURE_NO_WARNINGS 1
#include "List.h"
//鏈表打印
void ListNode_Print(ListNode* pphead)
{
assert(pphead);
ListNode* phead = pphead;
pphead = pphead->next;
for (; pphead != phead; pphead = pphead->next)
{
printf("%d ", pphead->date);
}
printf("\n");
}
bool Determine(ListNode* pphead)
{//判斷鏈表中有無元素
assert(pphead);
return pphead == pphead->next;
}
//鏈表初始化
void ListInit(ListNode** pphead)
{
*pphead = (ListNode*)malloc(sizeof(ListNode));
if (*pphead == NULL)
{
perror("ListInit");
exit(-1);
}
(*pphead)->date = -1;
(*pphead)->next = *pphead;
(*pphead)->prev = *pphead;
}
//尾插
void ListNode_ADD(ListNode* pphead,Listtype date)
{
//ListNode* NewNode = (ListNode*)malloc(sizeof(ListNode));
//if (NewNode == NULL)
//{
// perror("ADD_malloc");
// exit(-1);
//}
//NewNode->date = date;
//NewNode->prev = pphead->prev;
//pphead->prev->next = NewNode;
//pphead->prev = NewNode;
//NewNode->next = pphead;
//任插的復用
Any_insert(pphead, date);
}
void Head_insert(ListNode* pphead, Listtype date)
{
ListNode* NewNode = (ListNode*)malloc(sizeof(ListNode));
if (NewNode == NULL)
{
perror("Head_insert");
exit(-1);
}
//NewNode->date = date;
//NewNode->prev = pphead;
//NewNode->next = pphead->next;
//pphead->next->prev = NewNode;
//pphead->next = NewNode;
//進行任插的復用
Any_insert(pphead->next ,date);
}
void Tail_delet(ListNode* pphead)
{
assert(pphead);
//assert(Determine(pphead));
/*ListNode* tail = pphead->prev;
if (tail != pphead)
{
ListNode* tailprev = tail->prev;
tailprev->next = pphead;
pphead->prev = tailprev;
free(tail);
}*/
//尾刪的復用
Any_delet(pphead->prev);
}
//在任意位置前插入
void Any_insert(ListNode* pos,Listtype date)
{
ListNode* Prev = pos->prev;
ListNode* NewNode = (ListNode*)malloc(sizeof(ListNode));
if (NewNode == NULL)
{
perror("Any_insert");
exit(-1);
}
NewNode->date = date;
NewNode->next = pos;
pos->prev = NewNode;
Prev->next = NewNode;
NewNode->prev = Prev;
}
//任意位置刪除
void Any_delet(ListNode* pos)
{
assert(!Determine(pos));
ListNode* Next = pos->next;
ListNode* Prev = pos->prev;
Next->prev = Prev;
Prev->next = Next;
free(pos);
}
//鏈表清空
void List_Destory(ListNode* pos)
{
ListNode* head = pos,*Prev = pos->prev;
for (pos = pos->prev; head != pos;pos = Prev)
{
Prev = pos->prev;
Any_delet(pos);
}
printf("\n清空完成\n");
}
測試
#define _CRT_SECURE_NO_WARNINGS 1
#include "List.h"
void ListTest(ListNode** pphead)
{
ListInit(pphead);
Head_insert(*pphead, 60);
Head_insert(*pphead, 100);
Head_insert(*pphead, 60);
Head_insert(*pphead, 50);
ListNode_Print(*pphead);
Tail_delet(*pphead);
Tail_delet(*pphead);
Tail_delet(*pphead);
ListNode_Print(*pphead);
}
int main()
{
ListNode* pphead = NULL;
ListTest(&pphead);
return 0 ;
}
原文鏈接:https://blog.csdn.net/MT_125/article/details/125309201
相關推薦
- 2023-01-18 Android事件與手勢操作詳解_Android
- 2022-09-05 Go語言接口的用法詳解_Golang
- 2023-03-11 C/C++?-?從代碼到可執行程序的過程詳解_C 語言
- 2023-03-16 淺析Kotlin使用infix函數構建可讀語法流程講解_Android
- 2022-05-12 Kotlin flatMap 高級函數 操作數組的數組
- 2023-05-16 iOS開發藍牙技術應用增加無線連接功能_IOS
- 2021-12-02 Flutter將整個App變為灰色的簡單實現方法_Android
- 2023-07-13 uni-app 導航欄自定義圖標及圖標的點擊事件
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支