首先需要借助三个文件 test.c list.h list.c
目录
list.h
list.c
test.c
list.h
用于声明函数及创建结构体、包含头文件
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>typedef int LTDataType;
typedef struct ListNode
{struct ListNode* next;struct ListNode* prev;LTDataType data;
}LTNode;LTNode* LTInit();
void LTPrint(LTNode* phead);bool LTEmpty(LTNode* phead);
void LTPushBack(LTNode* phead, LTDataType x);
void LTPushFront(LTNode* phead, LTDataType x);
void LTPopBack(LTNode* phead);
void LTPopFront(LTNode* phead);LTNode* LTFind(LTNode* phead, LTDataType x); //查找要返回指针// 在pos之前插入
void LTInsert(LTNode* pos, LTDataType x); //插入要传指针
// 删除pos位置的值
void LTErase(LTNode* pos); //删除要传指针
void LTDestroy(LTNode* phead); //需要人为置空
list.c
用于函数功能的实现
#include"List.h"LTNode* BuyLTNode(LTDataType x)
{LTNode* newnode = (LTNode*)malloc(sizeof(LTNode)); //开辟if (newnode == NULL) //判断{perror("malloc fail");return NULL;}newnode->data = x;newnode->next = NULL; //置空newnode->prev = NULL; //置空return newnode; //返回新节点的地址
}LTNode* LTInit() //初始化
{LTNode* phead = BuyLTNode(-1); //指针接收新开辟的空间phead->next = phead;phead->prev = phead;return phead;
}void LTPrint(LTNode* phead)
{assert(phead);printf("guard<==>");LTNode* cur = phead->next; //遍历节点,cur都是从有效节点开始。while (cur != phead){printf("%d<==>", cur->data);cur = cur->next;}printf("\n");
}bool LTEmpty(LTNode* phead)
{assert(phead);return phead->next == phead; //为空return真
}//1.链接尾 2.成环 void LTPushBack(LTNode* phead, LTDataType x) //目的是尾插,尾节点可以直接找到!
{assert(phead);LTInsert(phead, x); //在哨兵位之前插入//LTNode* tail = phead->prev; //找尾指针//LTNode* newnode = BuyLTNode(x); //接收新建的节点//链接“尾”和新节点//tail->next = newnode; //newnode->prev = tail;//成环//newnode->next = phead; //尾的下一个是头//phead->prev = newnode; //头的上一个是尾
}//void LTPushFront(LTNode* phead, LTDataType x)
//{
// assert(phead);
// LTNode* newnode = BuyLTNode(x);
//
// newnode->next = phead->next;
// phead->next->prev = newnode;
//
// phead->next = newnode;
// newnode->prev = phead;
//}//不用管有没有有效节点void LTPushFront(LTNode* phead, LTDataType x)
{/*assert(phead);LTNode* newnode = BuyLTNode(x);//当只有哨兵位时,phead->next 与 phead->prev 就是 pheadLTNode* first = phead->next; //防止找不到下一个,先记录他!(原来的首节点)phead->next = newnode;newnode->prev = phead;newnode->next = first;first->prev = newnode;*/LTInsert(phead->next, x); //第一个有效节点之前插入
}
void LTPopBack(LTNode* phead) //所有删除都需要判断有没有有效节点
{assert(phead);assert(!LTEmpty(phead)); //判断有没有有效节点。 (!真 就是 假)LTErase(phead->prev);/*LTNode* tail = phead->prev; //找尾LTNode* tailPrev = tail->prev; //找prevfree(tail); //free//链接tailPrev->next = phead; phead->prev = tailPrev;*/}//void LTPopFront(LTNode* phead)
//{
// assert(phead);
// assert(!LTEmpty(phead));
//
// LTNode* next = phead->next;
//
// /*phead->next = next->next;
// phead->next->prev = phead;
// free(next);*/
//
// phead->next = next->next;
// next->next->prev = phead;
// free(next);
//}void LTPopFront(LTNode* phead)
{assert(phead);assert(!LTEmpty(phead)); //一定要有一个节点! LTErase(phead->next);//LTNode* first = phead->next; //借助first 和 second 表示节点//LTNode* second = first->next;//链接//phead->next = second;//second->prev = phead;//释放//free(first);
}LTNode* LTFind(LTNode* phead, LTDataType x) //查找绑定修改、插入
{assert(phead);LTNode* cur = phead->next; //从有效节点开始查找while (cur != phead) //遍历所有{if (cur->data == x){return cur; //返回指针}cur = cur->next;}return NULL; //找不到返回空
}// 在 pos 之前插入, 传pos指针
void LTInsert(LTNode* pos, LTDataType x) //插入(头插、尾插复用insert)
{assert(pos);LTNode* prev = pos->prev;LTNode* newnode = BuyLTNode(x); //开空间// prev newnode posprev->next = newnode;newnode->prev = prev;newnode->next = pos;pos->prev = newnode;
}// 删除 pos 位置 的值
void LTErase(LTNode* pos) //要么传phead,检查不能删除phead,要么再检查
{assert(pos);LTNode* posPrev = pos->prev;LTNode* posNext = pos->next;posPrev->next = posNext;posNext->prev = posPrev;free(pos); //free空间
}void LTDestroy(LTNode* phead)
{assert(phead);LTNode* cur = phead->next; //头节点开始while (cur != phead) //!= 哨兵位{LTNode* next = cur->next; //建立一个next,指向下一个节点!free(cur);cur = next; //通过cur = next改变cur迭代}free(phead); //释放哨兵位//没必要置空phead,形参改变不会影响实参。如果想置空,则要传二级指针!
}
test.c
用于测试函数功能
注意点
此链表的强大之处在于:当只有一个有效节点时,仍能按照一种情况完成所有增删查改!