【数据结构第二章】- 带头双向循环链表
创始人
2025-05-30 05:06:24
0

目录

一、List.h

二、List.c

三、test.c



一、List.h

#pragma once#include // 带头双向循环链表
typedef int DataType;typedef struct ListNode
{DataType data;struct ListNode* prev;struct ListNode* next;
}ListNode, *LinkList;// 基本操作
ListNode* BuyLinkListNode(DataType e);  // 动态申请一个新节点// void LinkListInit(LinkList* pphead);  // 初始化(方法一)
ListNode* LinkListInit();  // 初始化(方法二)void LinkListPushBack(LinkList phead, DataType e);  // 尾插
void LinkListPopBack(LinkList phead);  // 尾删void LinkListPushFront(LinkList phead, DataType e);  // 头插
void LinkListPopFront(LinkList phead);  // 头删void LinkListInsert(ListNode* pos, DataType e);  // 在 pos 前面插入
void LinkListErase(ListNode* pos);  // 删除 pos 节点ListNode* LinkListFind(LinkList phead, DataType e);  // 查找void LinkListPrint(LinkList phead);  // 打印void LinkListDestroy(LinkList phead);  // 销毁


二、List.c

  1. 动态申请一个新节点

    ListNode* BuyLinkListNode(DataType e)
    {ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));if (NULL == newnode){perror("malloc failed!");exit(-1);}newnode->data = e;newnode->prev = NULL;newnode->next = NULL;return newnode;
    }
  2. 初始化

    法一

    void LinkListInit(LinkList* pphead)
    {assert(pphead); ListNode* newnode = BuyLinkListNode(0);  // 生成一个新结点作为头结点newnode->prev = newnode;newnode->next = newnode;*pphead = newnode;  // 将头指针指向头结点
    }

    法一通过传址(头指针的地址)的方式在函数内部将头指针指向头结点

    法二

    ListNode* LinkListInit()
    {ListNode* newnode = BuyLinkListNode(0);  // 生成一个新结点作为头结点newnode->prev = newnode;newnode->next = newnode;return newnode;  // 返回头结点
    }

    法二则需要在函数调用结束后,在外部主动地将头指针指向头结点,即 LinkList phead = LinkListInit()

  3. 尾插

    void LinkListPushBack(LinkList phead, DataType e)
    {assert(phead);ListNode* newnode = BuyLinkListNode(e);ListNode* tail = phead->prev;// 尾插phead->prev = newnode;newnode->next = phead;tail->next = newnode;newnode->prev = tail;
    }
  4. 尾删

    void LinkListPopBack(LinkList phead)
    {assert(phead);// 判断是否为空表if (phead->prev == phead){return;}// 尾删ListNode* tail = phead->prev;phead->prev = tail->prev;tail->prev->next = phead;free(tail);
    }
  5. 头插

    void LinkListPushFront(LinkList phead, DataType e)
    {assert(phead);ListNode* newnode = BuyLinkListNode(e);ListNode* first = phead->next;// 头插phead->next = newnode;newnode->prev = phead;first->prev = newnode;newnode->next = first;
    }
  6. 头删

    void LinkListPopFront(LinkList phead)
    {assert(phead);// 判断是否为空表if (phead->next == phead){return NULL;}// 头删ListNode* first = phead->next;phead->next = first->next;first->next->prev = phead;free(first);
    }
  7. pos 之前插入

    void LinkListInsert(ListNode* pos, DataType e)
    {assert(pos);ListNode* newnode = BuyLinkListNode(e);ListNode* pre = pos->prev;// 在 pos 之前插入pre->next = newnode;newnode->prev = pre;pos->prev = newnode;newnode->next = pos;
    }
  8. 删除 pos 节点

    void LinkListErase(ListNode* pos)
    {assert(pos);// 删除 pos 节点pos->prev->next = pos->next;pos->next->prev = pos->prev;free(pos);
    }
  9. 查找

    ListNode* LinkListFind(LinkList phead, DataType e)
    {assert(phead);ListNode* cur = phead->next;while (cur != phead){if (cur->data == e){return cur;}cur = cur->next;}return NULL;
    }
  10. 打印

    void LinkListPrint(LinkList phead)
    {assert(phead);printf("<=>head<=>");ListNode* cur = phead->next;while (cur != phead){printf("<=>%d<=>", cur->data);cur = cur->next;}printf("\n");
    }
  11. 销毁

    void LinkListDestroy(LinkList phead)
    {assert(phead);ListNode* cur = phead->next;while (cur != phead){ListNode* tmp = cur;cur = cur->next;free(tmp);}free(phead);
    }

LinkListInsert 函数中,当 pos == phead 时,该函数就相当于尾插;当 pos == phead->next 时,该函数就相当于头插,因此可以分别对 LinkListPushBackLinkListPushFront 函数做如下修改

void LinkListPushBack(LinkList phead, DataType e)
{assert(phead);LinkListInsert(phead, e); 
}
​
void LinkListPushFront(LinkList phead, DataType e)
{assert(phead);LinkListInsert(phead->next, e);
}

LinkListErase 函数中,当 pos == phead->prev 时,该函数就相当于尾删;当 pos == phead->next 时,该函数就相当于头删,因此可以分别对 LinkListPopBackLinkListPopFront 函数做如下修改

void LinkListPopBack(LinkList phead)
{assert(phead);// 判断是否为空表if (phead->prev == phead){return;}// 尾删LinkListErase(phead->prev);
}
​
void LinkListPopFront(LinkList phead)
{assert(phead);// 判断是否为空表if (phead->next == phead){return NULL;}// 头删LinkListErase(phead->next);
}


三、test.c

#include "list.h"// 尾插和尾删
void test1()
{LinkList phead;  // 头指针// LinkListInit(&phead);  // 初始化(方法一)phead = LinkListInit();  // 初始化(写法二)// 尾插LinkListPushBack(phead, 1);LinkListPushBack(phead, 2);LinkListPushBack(phead, 3);LinkListPushBack(phead, 4); LinkListPrint(phead);  // <=>head<=><=>1<=><=>2<=><=>3<=><=>4<=>// 尾删LinkListPopBack(phead);LinkListPrint(phead);  // <=>head<=><=>1<=><=>2<=><=>3<=>LinkListPopBack(phead);LinkListPrint(phead);  // <=>head<=><=>1<=><=>2<=>LinkListPopBack(phead);LinkListPrint(phead);  // <=>head<=><=>1<=>LinkListPopBack(phead);LinkListPrint(phead);  // <=>head<=>// 销毁LinkListDestroy(phead);phead = NULL;
}// 头插和头删
void test2()
{LinkList phead = LinkListInit();  // 初始化// 头插LinkListPushFront(phead, 1);LinkListPushFront(phead, 2);LinkListPushFront(phead, 3);LinkListPushFront(phead, 4);LinkListPrint(phead);  // <=>head<=><=>4<=><=>3<=><=>2<=><=>1<=>// 头删LinkListPopFront(phead);LinkListPrint(phead);  // <=>head<=><=>3<=><=>2<=><=>1<=>LinkListPopFront(phead);LinkListPrint(phead);  // <=>head<=><=>2<=><=>1<=>LinkListPopFront(phead);LinkListPrint(phead);  // <=>head<=><=>1<=>LinkListPopFront(phead);LinkListPrint(phead);  // <=>head<=>// 销毁LinkListDestroy(phead);phead = NULL;
}int main()
{// test1();test2();return 0;
}

相关内容

热门资讯

jspweb综合分类信息发布系... 网站前台功能详细介绍: 注册会员:通过该模块完成用户注册操作࿰...
学生课外活动方案 学生课外活动方案(通用18篇)  为了确保事情或工作能无误进行,通常会被要求事先制定方案,方案是有很...
幼儿园六一儿童节的活动方案 幼儿园六一儿童节的活动方案(通用20篇)  为了确保事情或工作得以顺利进行,就常常需要事先准备方案,...
五一工会团建活动方案 五一工会团建活动方案(精选8篇)  为了确定活动的圆满进行,往往需要预先制定好活动方案,活动方案是为...
庆五一活动方案 庆五一活动方案(通用19篇)  为了确保活动能有条不紊地开展,时常需要预先开展活动方案准备工作,活动...
数据平民化之路(三)— 低代码... 随着多云战略的崛起,多云策略在企业中也越来越受欢迎。IBM公司最近发布的一份调查报告表...
vue中的生命周期 前言 很多时候我们希望能在 vue 生命周期的过程中执行一些操作,生命周期钩子函数也...
年度销售计划书 年度销售计划书  年度销售计划书怎么写?以下为大家分享的是年度销售计划书格式,希望对大家有所帮助。如...
幼儿园主题活动方案 幼儿园主题活动方案  为保障事情或工作顺利开展,常常需要提前进行细致的方案准备工作,方案指的是为某一...
5.15国际家庭日活动方案 5.15国际家庭日活动方案  为了确保事情或工作能无误进行,常常需要提前制定一份优秀的方案,方案是计...
开展法制宣传活动方案 开展法制宣传活动方案  为有力保证活动开展的质量水平,就常常需要事先准备活动方案,活动方案是阐明活动...
数据分享 | 全球7.77亿建... 022年5月17日,微软必应地图团队发布包含涵了776712641个建筑物轮廓数据的全球建筑物轮廓数...
老胡的周刊(第083期) 老胡的信息周刊,记录这周我看到的有价值的信息,主要针对计算机领域...
k8s etcd 文章目录一、etcd1.重新搭建集群环境2.备份3.恢复 一、etcd 官方网址:h...
外国语学校6.1儿童节活动方...   每年的6月1日是国际儿童节,这一天为了表示对孩子们的祝贺,小编特地准备了以下外国语学校6.1儿童...
手机营销活动方案 手机营销活动方案(10篇)  为保障事情或工作顺利开展,常常要根据具体情况预先制定方案,方案指的是为...
阳光冬季长跑活动方案 阳光冬季长跑活动方案范文(精选7篇)  为了确保活动有序有力开展,常常需要预先准备活动方案,活动方案...
学雷锋活动月主题活动方案 学雷锋活动月主题活动方案(精选22篇)  为了确保活动能成功举办,通常会被要求事先制定活动方案,活动...
自然语言处理基础任务(FMMB... 中文分词背景词语的概念:词语(word)是最小独立使用的音义结合体&#x...
第5章 设计模式 5.1 设计模式介绍? 5.1.1 设计模式是什么?   设计模式是指在...