文章目录
先看看头文件
根据头文件来写出各个函数
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
typedef int LTDataType;
typedef struct ListNode
{
LTDataType data;
struct ListNode* next;
struct ListNode* pre;
}ListNode;
//初始化
ListNode* InitListNode();
//创建一个节点
ListNode* BuyListNode(LTDataType x);
//尾插
void ListPushBack(ListNode* phead,LTDataType x);
//尾删
void ListPopBack(ListNode* phead);
//头插
void ListPushFront(ListNode* phead,LTDataType x);
//头删
void ListPopFront(ListNode* phead);
//查找
ListNode* ListFind(ListNode* phead, LTDataType x);
//删除pos位置的值
void ListErase(ListNode* phead, ListNode* pos);
//在pos位置前添加元素
void ListInsertFront(ListNode* phead, ListNode* pos, LTDataType x);
//打印
void Listprint(ListNode* phead);
看完之后大家之后肯定有一个疑惑?这个头插头删尾插尾删为什么传的都是一级指针?
这里涉及的是带头(带哨兵位)和不带头两种情况
看图的解释:
初始化和创建节点
ListNode* BuyListNode(LTDataType x)
{
ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
if (newnode == NULL)
{
printf("创建节点失败\n");
exit(-1);
}
newnode->data = x;
newnode->next = NULL;
newnode->pre = NULL;
return newnode;
}
ListNode* InitListNode()
{
ListNode* phead = BuyListNode(0);
phead->next = phead;
phead->pre = phead;
return phead;
}
只有头(初始化)
尾插/尾删
void ListPushBack(ListNode* phead, LTDataType x)
{
ListNode* newnode = BuyListNode(x);
ListNode* tail = phead->pre; //找到尾
tail->next = newnode; //先连接尾和newnode
newnode->pre = tail;
newnode->next = phead; //在连接头和newndoe
phead->pre = newnode;
}
void ListPopBack(ListNode* phead)
{
assert(phead);
if (phead->next == phead)
{
printf("没有节点可以删除\n");
return;
}
ListNode* tail = phead->pre; //找尾
ListNode* pretail = tail->pre; //找尾的前一个
pretail->next = phead; /将尾的前一个和头连接
phead->pre = pretail;
free(tail);
}
头插和头删
void ListPushFront(ListNode* phead, LTDataType x)
{
//头插
assert(phead);
ListNode* newnode = BuyListNode(x);
ListNode* save = phead->next; //保存还没插入时的第一个节点
newnode->next = save; //要插入的接点和第一个连接
save->pre = newnode;
phead->next = newnode; //要插入的节点和头连接
newnode->pre = phead;
}
void ListPopFront(ListNode* phead)
{
assert(phead);
if (phead->next == phead)
{
printf("没有可以的删除的元素啦\n");
return;
}
ListNode* save = phead->next; //第一个节点,要删除的节点
phead->next = save->next; //连接头和第二个节点==》》就是删除第一个节点
save->next->pre = phead;
free(save);
}
查找pos
ListNode* ListFind(ListNode* phead, LTDataType x)
{
assert(phead);
ListNode* cur = phead->next;
while (cur != phead) //cur等于头的时候就是找完了
{
if (cur->data == x)
return cur;
cur = cur->next;
}
printf("找不到\n");
}
删除pos位置的节点
void ListErase(ListNode* phead, ListNode* pos)
{
assert(phead && pos);
ListNode* prepos = pos->pre; //记录pos位置的前一个和后一个节点
ListNode* nextpos = pos->next;
prepos->next = nextpos; //将pos的前一个和后一个连接---》》就是删除pos了
nextpos->pre = prepos;
free(pos);
}
在pos位置前插入元素
void ListInsertFront(ListNode* phead, ListNode* pos, LTDataType x)
{
assert(phead && pos);
ListNode* newnode = BuyListNode(x);
ListNode* prepos = pos->pre; //记录一下pos前一个节点
newnode->next = pos; //连接要插入的节点和pos位置的节点
pos->pre = newnode;
prepos->next = newnode; //连接要插入的和pos前一个节点
newnode->pre = prepos;
}