带头双向循环链表的实现
1.带头双向循环链表的功能API架构
带头双向循环链表的功能API架构:
//打印结点 void ListPrint(LTNode* phead); //初始化链表 LTNode* ListInit(); //创建结点 LTNode* BuyLTNode(LTDataType x); //尾插结点 void ListPushBack(LTNode* phead, LTDataType x); //尾删结点 void ListPopBack(LTNode* phead); //头插结点 void ListPushFront(LTNode* phead, LTDataType x); //头删结点 void ListPopFront(LTNode* phead); //查找数据 LTNode* ListFind(LTNode* phead, LTDataType x); // 在pos之前插入 void ListInsert(LTNode* pos, LTDataType x); // 删除pos位置的节点 void ListErase(LTNode* pos); //销毁链表 void ListDestory(LTNode* phead);
2.带头双向循环链表的功能API代码实现
0.带头双向循环链表的链表结构:
typedef int LTDataType; typedef struct ListNode { LTDataType data; struct ListNode* next; struct ListNode* prev; }LTNode;
1.创建结点:
LTNode* BuyLTNode(LTDataType x) { LTNode* newnode = (LTNode*)malloc(sizeof(LTNode)); if (newnode == NULL) { printf("malloc fail\n"); exit(-1); } newnode->data = x; newnode->next = NULL; newnode->prev = NULL; return newnode; }
2.打印结点:
void ListPrint(LTNode* phead) { assert(phead); printf("%d ", *phead); LTNode* cur = phead->next; while (cur != phead) { printf("%d ", cur->data); cur = cur->next; } printf("\n\n"); }
3.初始化结点:
LTNode* ListInit() { LTNode* phead = BuyLTNode(0); phead->next = phead; phead->prev = phead; return phead; }
4.插入节点:
void ListInsert(LTNode* pos, LTDataType x) { assert(pos); /*LTNode* newnode = BuyLTNode(x); pos->prev->next = newnode; newnode->prev = pos->prev; pos->prev = newnode; newnode->next = pos;*/ LTNode* newnode = BuyLTNode(x); LTNode* posPrev = pos->prev; newnode->next = pos; pos->prev = newnode; posPrev->next = newnode; newnode->prev = posPrev; }
5.删除结点:
void ListErase(LTNode* pos) { assert(pos); LTNode* prev = pos->prev; LTNode* next = pos->next; free(pos); pos = NULL; prev->next = next; next->prev = prev; }
6.头插结点:
void ListPushFront(LTNode* phead, LTDataType x) { assert(phead); ListInsert(phead, x); }
7.头删结点:
void ListPopFront(LTNode* phead) { assert(phead); assert(phead->next != phead); ListErase(phead->next); }
8.尾插结点:
void ListPushBack(LTNode* phead, LTDataType x) { assert(phead); //LTNode* tail = phead->prev; //LTNode* newnode = BuyLTNode(x); //tail->next = newnode; //newnode->prev = tail; //newnode->next = phead; //phead->prev = newnode; ListInsert(phead, x); }
9.尾删结点:
void ListPopBack(LTNode* phead) { assert(phead); // 链表为空 assert(phead->next != phead); /* LTNode* tail = phead->prev; LTNode* tailPrev = tail->prev; free(tail); tail = NULL; tailPrev->next = phead; phead->prev = tailPrev;*/ ListErase(phead->prev); }
10.查找数据:
LTNode* ListFind(LTNode* phead, LTDataType x) { assert(phead); LTNode* cur = phead->next; while (cur != phead) { if (cur->data == x) { printf("找到了目标结点\n\n"); return cur; } cur = cur->next; } return NULL; }
11.销毁结点:
void ListDestory(LTNode* phead) { assert(phead); LTNode* cur = phead->next; while (cur != phead) { LTNode* next = cur->next; //ListErase(cur); free(cur); cur = next; } free(phead); //phead = NULL; }
3.带头双向循环链表的功能API效果展示
4.带头双向循环链表的功能API源代码
List.h 头文件
#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
typedef int LTDataType;
typedef struct ListNode
{
LTDataType data;
struct ListNode* next;
struct ListNode* prev;
}LTNode;
//打印结点
void ListPrint(LTNode* phead);
//初始化链表
LTNode* ListInit();
//创建结点
LTNode* BuyLTNode(LTDataType x);
//尾插结点
void ListPushBack(LTNode* phead, LTDataType x);
//尾删结点
void ListPopBack(LTNode* phead);
//头插结点
void ListPushFront(LTNode* phead, LTDataType x);
//头删结点
void ListPopFront(LTNode* phead);
//查找数据
LTNode* ListFind(LTNode* phead, LTDataType x);
// 在pos之前插入
void ListInsert(LTNode* pos, LTDataType x);
// 删除pos位置的节点
void ListErase(LTNode* pos);
//销毁链表
void ListDestory(LTNode* phead);
List.c 源文件
#include"List.h"
LTNode* BuyLTNode(LTDataType x)
{
LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
if (newnode == NULL)
{
printf("malloc fail\n");
exit(-1);
}
newnode->data = x;
newnode->next = NULL;
newnode->prev = NULL;
return newnode;
}
void ListPrint(LTNode* phead)
{
assert(phead);
printf("%d ", *phead);
LTNode* cur = phead->next;
while (cur != phead)
{
printf("%d ", cur->data);
cur = cur->next;
}
printf("\n\n");
}
//void ListInit(LTNode** pphead)
//{
// assert(pphead);
// *pphead = BuyLTNode(0);
// (*pphead)->next = *pphead;
// (*pphead)->prev = *pphead;
//}
LTNode* ListInit()
{
LTNode* phead = BuyLTNode(0);
phead->next = phead;
phead->prev = phead;
return phead;
}
void ListPushBack(LTNode* phead, LTDataType x)
{
assert(phead);
//LTNode* tail = phead->prev;
//LTNode* newnode = BuyLTNode(x);
//tail->next = newnode;
//newnode->prev = tail;
//newnode->next = phead;
//phead->prev = newnode;
ListInsert(phead, x);
}
void ListPopBack(LTNode* phead)
{
assert(phead);
// 链表为空
assert(phead->next != phead);
/* LTNode* tail = phead->prev;
LTNode* tailPrev = tail->prev;
free(tail);
tail = NULL;
tailPrev->next = phead;
phead->prev = tailPrev;*/
ListErase(phead->prev);
}
void ListPopFront(LTNode* phead)
{
assert(phead);
assert(phead->next != phead);
ListErase(phead->next);
}
void ListPushFront(LTNode* phead, LTDataType x)
{
assert(phead);
ListInsert(phead, x);
}
LTNode* ListFind(LTNode* phead, LTDataType x)
{
assert(phead);
LTNode* cur = phead->next;
while (cur != phead)
{
if (cur->data == x)
{
printf("找到了目标结点\n\n");
return cur;
}
cur = cur->next;
}
return NULL;
}
void ListInsert(LTNode* pos, LTDataType x)
{
assert(pos);
/*LTNode* newnode = BuyLTNode(x);
pos->prev->next = newnode;
newnode->prev = pos->prev;
pos->prev = newnode;
newnode->next = pos;*/
LTNode* newnode = BuyLTNode(x);
LTNode* posPrev = pos->prev;
newnode->next = pos;
pos->prev = newnode;
posPrev->next = newnode;
newnode->prev = posPrev;
}
// 驼峰法
// 函数和类型所有单词首字母大写
// 变量:第一个单词小写后续单词首字母大写
void ListErase(LTNode* pos)
{
assert(pos);
LTNode* prev = pos->prev;
LTNode* next = pos->next;
free(pos);
pos = NULL;
prev->next = next;
next->prev = prev;
}
void ListDestory(LTNode* phead)
{
assert(phead);
LTNode* cur = phead->next;
while (cur != phead)
{
LTNode* next = cur->next;
//ListErase(cur);
free(cur);
cur = next;
}
free(phead);
//phead = NULL;
}
main.c 主函数源文件
#define _CRT_SECURE_NO_WARNINGS
#include "List.h"
void TestList0()
{
//LTNode* pList = NULL;
//ListInit(&pList);
LTNode* pList = ListInit();
ListPushBack(pList, 1);
ListPushBack(pList, 2);
ListPushBack(pList, 3);
ListPushBack(pList, 4);
ListPushBack(pList, 5);
ListPushBack(pList, 6);
ListPrint(pList);
ListPopBack(pList);
ListPopBack(pList);
ListPopBack(pList);
ListPopBack(pList);
ListPopBack(pList);
ListPopBack(pList);
//ListPopBack(pList);
ListPrint(pList);
}
void TestList1()
{
//LTNode* pList = NULL;
//ListInit(&pList);
LTNode* pList = ListInit();
ListPushBack(pList, 1);
ListPushBack(pList, 2);
ListPushBack(pList, 3);
ListPushBack(pList, 4);
ListPushBack(pList, 5);
ListPushBack(pList, 6);
ListPrint(pList);
LTNode* pos = ListFind(pList, 3);
if (pos)
{
ListInsert(pos, 30);
}
ListPrint(pList);
}
int main()
{
printf("测试尾插尾删:\n");
TestList0();
printf("测试头插 头删 查找:\n");
TestList1();
return 0;
}