当前位置: 首页 > news >正文

【数据结构】双向链表的接口实现(附图解和源码)

双向链表的接口实现(附图解和源码)


文章目录

  • 双向链表的接口实现(附图解和源码)
  • 前言
  • 一、定义结构体
  • 二、接口实现(附图解+源码)
    • 1.初始化双向链表
    • 2.开辟新空间
    • 3.尾插数据
    • 4.尾删数据
    • 5.打印双向链表中数据
    • 6.头插数据
    • 7.头删数据
    • 8.查找结点位置
    • 9.在pos位置之前插入
    • 10.删除pos位置
    • 11.销毁双向链表
  • 三、源代码展示
    • 1.test.c(测试+主函数)
    • 2.List.h(接口函数的声明)
    • 3.List.c(接口函数的实现)
  • 总结


前言

本文主要介绍双向链表中增删查改等接口实现,结尾附总源码


一、定义结构体

在这里插入图片描述

代码如下(示例):

typedef int LTDataType;
typedef struct ListNode
{LTDataType data;struct ListNode* prev;struct ListNode* next;
}ListNode;

二、接口实现(附图解+源码)

在这里插入图片描述

这里一共10个接口,我会我都会一 一为大家讲解(图解+源码


1.初始化双向链表

初始化出一个哨兵位的头结点(用malloc开辟),next和prev都指向自己。具体如下图!
在这里插入图片描述
在这里插入图片描述

代码如下(示例):

ListNode* ListInit()
{ListNode* p = (ListNode*)malloc(sizeof(ListNode));if (p == NULL){perror(errno);}ListNode* phead = p;phead->next = phead;phead->prev = phead;return phead;
}

2.开辟新空间

(1)开辟一个链表类型的动态空间,将地址给newnode;
(2)将值放入 newnode 的 data 数据内;
(3)将 newnode 的 next 和 prev 都置为NULL;
注意:1.将malloc开辟空间存到 newnode 里面时,参数为结构体所占的字节大小!2.对 newnode 进行 NULL 判断!

代码如下(示例):

ListNode* BuyListNode(LTDataType x)
{ListNode* p = (ListNode*)malloc(sizeof(ListNode));if (p == NULL){perror(errno);}ListNode* newNode = p;newNode->data = x;newNode->next = NULL;newNode->prev = NULL;return newNode;
}

3.尾插数据

在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


代码如下(示例):

void ListPushBack(ListNode* phead, LTDataType x)//尾插数据
{ListNode* tail = phead->prev;ListNode* newnode = BuyListNode(x);//第一个链接tail->next = newnode;newnode->prev = tail;//第二个链接phead->prev = newnode;newnode->next = phead;
}

4.尾删数据

这里需要两次进行断言:
在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


代码如下(示例):

void ListPopBack(ListNode* phead)//尾删
{assert(phead);assert(phead->next != phead);ListNode* tail = phead->prev;ListNode* tailprev = tail->prev;free(tail);//连接tailprev->next = phead;phead->prev = tailprev;
}

5.打印双向链表中数据

在这里插入图片描述


代码如下(示例):

void ListPrint(ListNode* phead)//打印数据
{assert(phead);ListNode* cur = phead->next;while (cur != phead){printf("%d ", cur->data);cur = cur->next;}printf("\n");
}

6.头插数据

头插数据也是很简单的一个接口,链接两次即可,如下图
在这里插入图片描述


代码如下(示例):

void ListPushFront(ListNode* phead, LTDataType x)//头插
{assert(phead);ListNode* newNode = BuyListNode(x);ListNode* next = phead->next;phead->next = newNode;newNode->prev = phead;newNode->next = next;next->prev = newNode;
}

7.头删数据

在头删数据时和尾删数据一样都需要进行两次断言如下图!
在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


代码如下(示例):

void ListPopFront(ListNode* phead)//头删
{assert(phead);assert(phead->next != phead);ListNode* next = phead->next;ListNode* nextNext = next->next;phead->next = nextNext;nextNext->prev = phead;free(next);
}

8.查找结点位置

这个比较简单,和单链表一样,直接用cur遍历即可,直接上代码

代码如下(示例):

ListNode* ListFind(ListNode* phead, LTDataType x)
{assert(phead);ListNode* cur = phead->next;while (cur != phead){if (cur->data == x){return cur;}cur = cur->next;}return NULL;
}

9.在pos位置之前插入

在这里插入图片描述


在这里插入图片描述


代码如下(示例):

void ListInsert(ListNode* pos, LTDataType x)//pos位置之前插入
{assert(pos);ListNode* newNode = BuyListNode(x);ListNode* posPrev = pos->prev;// posPrev  newnode posposPrev->next = newNode;newNode->prev = posPrev;newNode->next = pos;pos->prev = newNode;
}

根据ListInsert接口我们可以把头插和尾插进行改版,如下图!
在这里插入图片描述


在这里插入图片描述


10.删除pos位置

在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


代码如下(示例):

void ListErase(ListNode* pos)//删除pos位置
{assert(pos);ListNode* prev = pos->prev;ListNode* next = pos->next;free(pos);pos = NULL;prev->next = next;next->prev = prev;
}

11.销毁双向链表

在这里插入图片描述


在这里插入图片描述


代码如下(示例):

void ListDestory(ListNode* phead)
{assert(phead);ListNode* cur = phead->next;while (cur != phead){ListNode* next = cur->next;free(cur);cur = next;}free(phead);phead = NULL;
}

三、源代码展示

1.test.c(测试+主函数)

代码如下(示例):

#include "list.h"
void Testlist1()
{ListNode* n1 = ListInit();ListPushBack(n1, 1);//尾插ListPushBack(n1, 2);//尾插//ListPushBack(n1, 3);//尾插//ListPushBack(n1, 4);//尾插//ListPushBack(n1, 5);//尾插//ListPopFront(n1);//头删//ListPopBack(n1);//尾删//ListPushFront(n1, 0);//头插ListPrint(n1);
}
void Testlist2()
{ListNode* n1 = ListInit();ListPushBack(n1, 1);//尾插ListPushBack(n1, 2);//尾插ListPushBack(n1, 3);//尾插ListPushBack(n1, 4);//尾插ListPushBack(n1, 5);//尾插ListNode* p = ListFind(n1, 5);printf("%d \n", p->data);
}
void Testlist3()
{ListNode* n1 = ListInit();ListPushBack(n1, 1);//尾插ListPushBack(n1, 2);//尾插ListPushBack(n1, 3);//尾插ListPushBack(n1, 4);//尾插ListPushBack(n1, 5);//尾插//ListNode* p = ListFind(n1, 5);//ListInsert(p, 0);ListDestory(n1);ListPrint(n1);
}
int main()
{//Testlist1();//Testlist2();Testlist3();return 0;
}

2.List.h(接口函数的声明)

代码如下(示例):

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
typedef int LTDataType;
typedef struct ListNode
{LTDataType data;struct ListNode* prev;struct ListNode* next;
}ListNode;
ListNode* ListInit();//初始化双向链表
void ListPushBack(ListNode* phead, LTDataType x);//尾插
void ListPopBack(ListNode* phead);//尾删
void ListPushFront(ListNode* phead, LTDataType x);//头插
void ListPopFront(ListNode* phead);//头删
void ListPrint(ListNode* phead);//打印
ListNode* ListFind(ListNode* phead, LTDataType x);//查找数据
void ListInsert(ListNode* pos, LTDataType x);//pos位置之前插入
void ListErase(ListNode* pos);//删除pos位置
void ListDestory(ListNode* phead);//销毁双向链表

3.List.c(接口函数的实现)

代码如下(示例):

#include "list.h"
ListNode* ListInit()
{ListNode* p = (ListNode*)malloc(sizeof(ListNode));if (p == NULL){perror(errno);}ListNode* phead = p;phead->next = phead;phead->prev = phead;return phead;
}
ListNode* BuyListNode(LTDataType x)
{ListNode* p = (ListNode*)malloc(sizeof(ListNode));if (p == NULL){perror(errno);}ListNode* newNode = p;newNode->data = x;newNode->next = NULL;newNode->prev = NULL;return newNode;
}
void ListPushBack(ListNode* phead, LTDataType x)//尾插数据
{ListNode* tail = phead->prev;ListNode* newnode = BuyListNode(x);//第一个链接tail->next = newnode;newnode->prev = tail;//第二个链接phead->prev = newnode;newnode->next = phead;//ListInsert(phead, x);
}
void ListPrint(ListNode* phead)//打印数据
{assert(phead);ListNode* cur = phead->next;while (cur != phead){printf("%d ", cur->data);cur = cur->next;}printf("\n");
}
void ListPopBack(ListNode* phead)//尾删
{assert(phead);assert(phead->next != phead);ListNode* tail = phead->prev;ListNode* tailprev = tail->prev;free(tail);//连接tailprev->next = phead;phead->prev = tailprev;
}
void ListPushFront(ListNode* phead, LTDataType x)//头插
{assert(phead);ListNode* newNode = BuyListNode(x);ListNode* next = phead->next;phead->next = newNode;newNode->prev = phead;newNode->next = next;next->prev = newNode;//ListInsert(phead->next, x);
}
void ListPopFront(ListNode* phead)//头删
{assert(phead);assert(phead->next != phead);ListNode* next = phead->next;ListNode* nextNext = next->next;phead->next = nextNext;nextNext->prev = phead;free(next);
}
ListNode* ListFind(ListNode* phead, LTDataType x)
{assert(phead);ListNode* cur = phead->next;while (cur != phead){if (cur->data == x){return cur;}cur = cur->next;}return NULL;
}
void ListInsert(ListNode* pos, LTDataType x)//pos位置之前插入
{assert(pos);ListNode* newNode = BuyListNode(x);ListNode* posPrev = pos->prev;// posPrev  newnode posposPrev->next = newNode;newNode->prev = posPrev;newNode->next = pos;pos->prev = newNode;
}
void ListErase(ListNode* pos)//删除pos位置
{assert(pos);ListNode* prev = pos->prev;ListNode* next = pos->next;free(pos);pos = NULL;prev->next = next;next->prev = prev;
}
void ListDestory(ListNode* phead)
{assert(phead);ListNode* cur = phead->next;while (cur != phead){ListNode* next = cur->next;free(cur);cur = next;}free(phead);phead = NULL;
}

总结

以上就是今天要讲的内容,本文介绍双向链表的接口实现(附图解和源码)。
如果我的博客对你有所帮助记得三连支持一下,感谢大家的支持!
在这里插入图片描述

http://www.lryc.cn/news/20272.html

相关文章:

  • 数据结构与算法之[把数字翻译成字符串]动态规划
  • java 面向对象三大特性之多态 万字详解(超详细)
  • git push origin master 情况
  • ElasticSearch查询优化routing
  • 【HashMap 1.7和1.8】
  • 【Zabbix实战之故障处理篇】Zabbix监控中文乱码问题解决方法
  • 学习(mianshi)必备-ClickHouse高性能查询/写入和常见注意事项(五)
  • 在Kotlin中探索 Activity Results API 极简的解决方案
  • 样式冲突太多,记一次前端CSS升级
  • 如何解决报考PMP的那些问题?
  • 数据结构栈的经典OJ题【leetcode最小栈问题大剖析】【leetcode有效的括号问题大剖析】
  • 数据结构与算法之打家劫舍(一)动态规划思想
  • 无人驾驶路径规划论文简要
  • C++ sort()函数和priority_queue容器中比较函数的区别
  • STM32开发(14)----CubeMX配置ADC
  • Simple RNN、LSTM、GRU序列模型原理
  • 【原创】java+swing+mysql生肖星座查询系统设计与实现
  • CentOS 环境 OpneSIPS 3.1 版本安装及使用
  • SQL95 从 Products 表中检索所有的产品名称以及对应的销售总数
  • 平时技术积累很少,面试时又会问很多这个难题怎么破?别慌,没事看看这份Java面试指南,解决你的小烦恼!
  • SQL Server 数据库的备份
  • NCNN Conv量化详解1
  • Redis大key多key拆分方案
  • python的类如何使用?兔c同学一篇关于python类的博文概述
  • Day60 动态规划总结
  • UVM仿真环境搭建
  • Azure AI基础到实战(C#2022)-认知服务(1)
  • 光栅化Triangles(笔记)
  • 【Oarcle】如何显示日本年号的日期格式 ?
  • 57_Pandas中的json_normalize将字典列表转换为DataFrame