第三集喽!
依旧还是声明部分list.h:
需要注意的是我们不能再结构体里面使用重命名node,只能使用全称,这是因为编译器在当前上下文中并不知道 node
是什么类型,重命名宏类似的也会在预编译阶段被替换成全称
#pragma once
#include <stdio.h>
#include <stdlib.h>
typedef int ListDataType;
typedef struct ListNode
{
struct ListNode* prev; // 前一个指针,使用 struct ListNode*
struct ListNode* next; // 后一个指针,使用 struct ListNode*
ListDataType data; // 数据域
} node;
// 函数声明
void ListInit(node* guard);
void ListDestroy(node* guard);
void ListPrint(node* guard);
void ListPushBack(node* guard, ListDataType x);
node* ListFind(node* guard, ListDataType x);
void ListInsert(node* pos, ListDataType x);
void ListPopFront(node* guard);
void ListPopBack(node* guard);
void ListErase(node* pos);
函数实现部分list.c:
今天的函数实现和昨天第二集很相似所以注释少了些许
初始化函数:
void ListInit(node* guard)
{
guard->data = -1; // 哨兵节点的数据,通常是无效数据
guard->next = guard; // 循环链表的哨兵节点,指向自己
guard->prev = guard;
}
添加节点函数:
void ListDestroy(node* guard)
{
assert(guard);
node* cur = guard->next;
while (cur != guard)
{
node* next = cur->next; // 先保存下一个节点的指针
free(cur); // 释放当前节点
cur = next; // 移动到下一个节点
}
// 最后释放哨兵节点
free(guard);
}
打印函数:
void ListPrint(node* guard)
{
assert(guard);
//和删除逻辑一样
node* cur = guard->next;
while (cur != guard)
{
printf("%d", cur->data);
cur = cur->next;
}
}
添加节点函数:
void ListDestroy(node* guard)
{
assert(guard);
node* cur = guard->next;
while (cur != guard)
{
node* next = cur->next; // 先保存下一个节点的指针
free(cur); // 释放当前节点
cur = next; // 移动到下一个节点
}
// 最后释放哨兵节点
free(guard);
}
销毁函数:
node* AddNode(ListDataType x)
{
node* newnode = (node*)malloc(sizeof(node));
if (newnode == NULL)
{
perror("malloc fail");
exit(-1);
}
newnode->data = x;
newnode->prev = NULL;
newnode->next = NULL;
return newnode;
}
尾插函数:
void ListPushBack(node* guard, ListDataType x)
{
assert(guard);
node* newnode = AddNode(x);
node* tail = guard->prev;
//新节点和头节点进行双向链接
newnode->next = guard;
guard->prev = newnode;
//和尾节点双向链接
tail->next = newnode;
newnode->prev = tail;
}
查找函数:
node* ListFind(node* guard, ListDataType x)
{
assert(guard);
node* cur = guard->next;
while (cur != guard)
{
if (cur->data == x)
return cur;
cur = cur->next;
}
return NULL;
}
插入函数:
void ListInsert(node* pos, ListDataType x)
{
assert(pos);
node* before = pos->prev;
node* newnode = AddNode(x);
//和前面节点进行双向链接
before->next = newnode;
newnode->prev = before;
//和后面节点进行双向链接
newnode->next = pos;
pos->prev = newnode;
}
尾删函数:
void ListPopFront(node* guard)
{
assert(guard);
assert(guard->next != guard);//确保不是只有哨兵节点
node* front = guard->next;
node* newfront = front->next;
guard->next = newfront;
newfront->prev = guard;
free(front);
}
头删函数:
void ListPopBack(node* guard)
{
assert(guard);
//判断是否为空
assert(guard->next != guard);
node* tail = guard->prev;
node* newtail = tail->prev;
newtail->next = guard;
guard->prev = newtail;
free(tail);
}
消除函数:
void ListErase(node* pos)
{
assert(pos);
node* before = pos->prev;
node* after = pos->next;
before->next = after;
after->prev = before;
free(pos);
}
全体实现代码:
#define _CRT_SECURE_NO_WARNINGS
#include "list.h"
#include <assert.h>
node* AddNode(ListDataType x)
{
node* newnode = (node*)malloc(sizeof(node));
if (newnode == NULL)
{
perror("malloc fail");
exit(-1);
}
newnode->data = x;
newnode->prev = NULL;
newnode->next = NULL;
return newnode;
}
void ListInit(node* guard)
{
guard->data = -1; // 哨兵节点的数据,通常是无效数据
guard->next = guard; // 循环链表的哨兵节点,指向自己
guard->prev = guard;
}
void ListDestroy(node* guard)
{
assert(guard);
node* cur = guard->next;
while (cur != guard)
{
node* next = cur->next; // 先保存下一个节点的指针
free(cur); // 释放当前节点
cur = next; // 移动到下一个节点
}
// 最后释放哨兵节点
free(guard);
}
void ListPrint(node* guard)
{
assert(guard);
//和删除逻辑一样
node* cur = guard->next;
while (cur != guard)
{
printf("%d", cur->data);
cur = cur->next;
}
}
void ListPushBack(node* guard, ListDataType x)
{
assert(guard);
node* newnode = AddNode(x);
node* tail = guard->prev;
//新节点和头节点进行双向链接
newnode->next = guard;
guard->prev = newnode;
//和尾节点双向链接
tail->next = newnode;
newnode->prev = tail;
}
node* ListFind(node* guard, ListDataType x)
{
assert(guard);
node* cur = guard->next;
while (cur != guard)
{
if (cur->data == x)
return cur;
cur = cur->next;
}
return NULL;
}
void ListInsert(node* pos, ListDataType x)
{
assert(pos);
node* before = pos->prev;
node* newnode = AddNode(x);
//和前面节点进行双向链接
before->next = newnode;
newnode->prev = before;
//和后面节点进行双向链接
newnode->next = pos;
pos->prev = newnode;
}
void ListPopFront(node* guard)
{
assert(guard);
assert(guard->next != guard);//确保不是只有哨兵节点
node* front = guard->next;
node* newfront = front->next;
guard->next = newfront;
newfront->prev = guard;
free(front);
}
void ListPopBack(node* guard)
{
assert(guard);
//判断是否为空
assert(guard->next != guard);
node* tail = guard->prev;
node* newtail = tail->prev;
newtail->next = guard;
guard->prev = newtail;
free(tail);
}
void ListErase(node* pos)
{
assert(pos);
node* before = pos->prev;
node* after = pos->next;
before->next = after;
after->prev = before;
free(pos);
}
测试部分:
#define _CRT_SECURE_NO_WARNINGS
#include "list.h"
int main()
{
node guard;
ListInit(&guard);
ListPushBack(&guard, 1);
ListPushBack(&guard, 2);
ListPushBack(&guard, 3);
ListPushBack(&guard, 4);
ListPopBack(&guard);
ListPrint(&guard);
ListDestroy(&guard);
return 0;
}
感谢看到这里,谢谢┗|`O′|┛ 嗷~~