双向链表的函数功能


注意事项 

1.双向链表还需要关注到前指针的指向

2.函数都需要判断逻辑

3.函数的增删都要关注到len的变化

4.函数的改查功能都需要遍历结束的标志NULL

5.注意p->next->prio时,p->next是否指向NULL

创建双向链表头节点

Node_ptr list_create()

函数功能:申请一个头结点初始化len

参数:无

返回值:头结点地址

    //指针接收申请的空间地址Node_ptr L=(Node_ptr)malloc(sizeof(Node));	//判断逻辑if(L==NULL){printf("申请空间失败\n");return NULL;}//初始化逻辑L->len=0;L->prio=NULL;L->next=NULL;//返回逻辑return L;

判空函数

int list_empty(Node_ptr head)

函数功能:判断双向链表是否为空
参数:头结点地址
返回值:链表为空返回1,非空返回0 

return L->next==NULL;

节点封装函数

Node_ptr list_node_apply(datatype e)

函数功能:申请一个新节点初始化数据域为e
参数:待封装的数据e
返回值:新节点地址

    //申请空间Node_ptr p=(Node_ptr)malloc(sizeof(Node));//判断逻辑if(p==NULL){printf("节点空间申请失败\n");return NULL;}//初始化逻辑p->data=e;p->prio=NULL;p->next=NULL;//返回逻辑return p;

头插函数

int list_insert_head(Node_ptr head, datatype e)

函数功能:在链表头部插入新节点
参数:头结点地址,待插入数据e
返回值:成功返回1,失败返回0

    //节点申请Node_ptr p=list_node_apply(e);//头插逻辑if(list_empty(L)){//链表为空L->next=p;p->prio=L;//长度自增L->len++;return 0;}else{    //链表不为空//先确定尾指针的指向p->next=L->next;L->next=p;//再确定头指针的指向p->prio=L;p->next->prio=p;//长度自增L->len++;//返回逻辑printf("头插成功\n");return 0;}

尾插函数 

int list_insert_tail(Node_ptr head,datatype e);

函数功能:在链表尾部插入新节点
参数:头结点地址,待插入数据e
返回值:成功返回1,失败返回0

    //节点申请Node_ptr p=list_node_apply(e);if(p==NULL){printf("尾插失败\n");return -1;}//遍历逻辑Node_ptr q=L->next;while(q->next!=NULL) //遍历到最后一个节点{q=q->next;}//插入逻辑p->next=q->next;q->next=p;p->prio=q;//长度自增L->len++;

 

遍历函数

void list_show(Node_ptr head)

函数功能:打印双向链表所有节点的数据
参数:头结点地址
返回值:无

按位置查找节点

Node_ptr list_search_post(Node_ptr head, int post)

函数功能:查找链表中指定位置的节点
参数:头结点地址,位置pos(从1开始)
返回值:找到返回节点地址,失败返回NULL

任意位置插入

int list_insert_post(Node_ptr head, int post, datatype e)

函数功能:在指定位置插入新节点
参数:头结点地址,位置post,待插入数据e
返回值:成功返回1,失败返回0

判断逻辑

申请空间

插入逻辑 

表长变化

返回逻辑

    //申请空间Node_ptr q=list_node_apply(e);if(q==NULL){printf("插入失败1\n");return -1;}//post位置查找Node_ptr post_ptr=list_search_post(L,post);//插入逻辑//继承post节点的指向q->prio=post_ptr->prio;q->prio->next=q;//完善链接q的指向q->next=post_ptr;post_ptr->prio=q;//表长变化L->len++;//返回逻辑return 0;	

头删函数

int list_delete_head(Node_ptr head)

函数功能:删除链表首元素节点
参数:头结点地址
返回值:成功返回1,失败返回0

    Node_ptr p=L->next;//删除逻辑L->next=p->next;if(L->next!=NULL)L->next->prio=L;//释放节点,置空free(p);p=NULL;//len自减逻辑L->len--;

尾删函数

 int list_delete_tail(Node_ptr L)

函数功能:删除链表尾元素节点
参数:头结点地址
返回值:成功返回1,失败返回0

    //遍历逻辑Node_ptr p=L->next;while(p->next!=NULL) //遍历到最后一个节点{p=p->next;}//删除逻辑p->prio->next=NULL; //倒数第二个节点置空//长度自减L->len--;

 

任意位置删除

int list_delete_post(Node_ptr head, int post)

函数功能:删除指定位置的节点
参数:头结点地址,位置pos
返回值:成功返回1,失败返回0

    //查找逻辑Node_ptr p=list_search_post(L,post);//删除逻辑//最后一个节点只执行一条p->prio->next=p->next;if(p->next!=NULL){   //如果不为最后一个节点p->next->prio=p->prio;}//自减L->len--;//释放节点,置空free(p);p=NULL;

任意位置修改

int list_updata_post(Node_ptr head, int post, datatype e)

函数功能:修改指定位置节点的数据
参数:头结点地址,位置pos,新数据e
返回值:成功返回1,失败返回0

    //查找逻辑Node_ptr p=list_search_post(L,post);//修改逻辑p->data=e;

销毁链表

int list_free(Node_ptr head)

函数功能:释放双向链表所有节点内存
参数:头结点地址
返回值:成功返回1,失败返回0

    //删除逻辑//结点删除 Node_ptr p=L->next;while(!list_empty(L)){list_delete_head(L);	}//头节点删除free(L);L=NULL;

链表与顺序表的比较

存储:1.顺序表是一段连续空间存储,链表不一定连续的空间

           2.顺序表是静态分配空间,链表是动态分配空间        (创建时体现)

           3.顺序表存在存满的情况,链表不存在

           4.顺序表需要提前预估空间,链表不需要

时间复杂度
增删改查
顺序表O(n)      其他数据元素后移O(1)        对应的元素修改即可
链表           O(1)      只需改变指针指向O(n)        需要遍历到其位置

因此:增删链表,改查顺序表

完整代码

Dlink.h

#ifndef _Dlink_H
#define _Dlink_H
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef char datatype;//定义数据类型
//双向链表
typedef struct Node
{   //数据域union{datatype data;int len;};//指针域struct Node *prio;   //前指针struct Node *next;   //后指针
}Node,*Node_ptr;   //创建双向链表头节点
Node_ptr list_create();//判空
int list_empty(Node_ptr );//节点封装函数
Node_ptr list_node_apply(datatype e);//头插
int list_insert_head(Node_ptr ,datatype );//尾插
int list_insert_tail(Node_ptr,datatype);
//遍历
void list_show(Node_ptr );//按位置查找返回节点(位置从1开始)
Node_ptr list_search_post(Node_ptr ,int);//任意位置插入数据
int list_insert_post(Node_ptr ,int ,datatype);//头删
int list_delete_head(Node_ptr );
//尾删
int list_delete_tail(Node_ptr );
//任意位置删除
int list_delete_post(Node_ptr ,int );//任意位置修改
int list_updata_post(Node_ptr ,int ,datatype);//销毁双向链表
int list_free(Node_ptr );
#endif

Dlink.c

#include"Dlink.h"//创建双向链表
Node_ptr list_create()
{   //指针接收申请的空间地址Node_ptr L=(Node_ptr)malloc(sizeof(Node));	//判断逻辑if(L==NULL){printf("申请空间失败\n");return NULL;}//初始化逻辑L->len=0;L->prio=NULL;L->next=NULL;//返回逻辑return L;
}
//判空
//空返回1,非空返回0,非法返回-1
int list_empty(Node_ptr L)
{   //判断逻辑if(L==NULL){printf("非法地址\n");return -1;}return L->next==NULL;
}
//节点封装函数
Node_ptr list_node_apply(datatype e)
{//申请空间Node_ptr p=(Node_ptr)malloc(sizeof(Node));//判断逻辑if(p==NULL){printf("节点空间申请失败\n");return NULL;}//初始化逻辑p->data=e;p->prio=NULL;p->next=NULL;//返回逻辑return p;
}//头插
//成功返回0,失败返回-1
int list_insert_head(Node_ptr L,datatype e)
{//判断逻辑if(L==NULL){printf("非法地址\n");return -1;}//节点申请Node_ptr p=list_node_apply(e);//头插逻辑if(list_empty(L)){//链表为空L->next=p;p->prio=L;printf("插入成功\n");//长度自增L->len++;return 0;}else{//先确定尾指针的指向p->next=L->next;L->next=p;//再确定头指针的指向p->prio=L;p->next->prio=p;//长度自增L->len++;//返回逻辑printf("头插成功\n");return 0;}
}
//尾插
int list_insert_tail(Node_ptr L,datatype e)
{//判断逻辑if(L==NULL){printf("尾插失败\n");return -1;}//节点申请Node_ptr p=list_node_apply(e);if(p==NULL){printf("尾插失败\n");return -1;}//遍历逻辑Node_ptr q=L->next;while(q->next!=NULL) //遍历到最后一个节点{q=q->next;}//插入逻辑p->next=q->next;q->next=p;p->prio=q;//长度自增L->len++;//返回逻辑return 0;
}//遍历
void list_show(Node_ptr L)
{//判断逻辑if(L==NULL){printf("非法地址\n");}//遍历逻辑Node_ptr p=L->next; //定义遍历指针while(p!=NULL){printf("%-4c",p->data); //访问数据域p=p->next;//指针移到下一个节点}putchar(10);
}//按位置查找返回节点(位置从1开始)
Node_ptr list_search_post(Node_ptr L,int post)
{//判断逻辑if(list_empty(L)||post<1||post>L->len){printf("post不合理\n");return NULL;}//查找逻辑Node_ptr p=L->next;for (int i=1; i<post; i++){p=p->next;}return p;
}
//任意位置插入数据
int list_insert_post(Node_ptr L,int post,datatype e)
{//判断逻辑if(post<1||post>L->len+1){printf("插入位置不合理\n");return -1;}//申请空间Node_ptr q=list_node_apply(e);if(q==NULL){printf("插入失败1\n");return -1;}//post位置查找Node_ptr post_ptr=list_search_post(L,post);//插入逻辑//继承post节点的指向q->prio=post_ptr->prio;q->prio->next=q;//完善链接q的指向q->next=post_ptr;post_ptr->prio=q;//表长变化L->len++;//返回逻辑return 0;		
}//头删
int list_delete_head(Node_ptr L)
{//判断逻辑if(list_empty(L)){printf("头删失败\n");return -1;}Node_ptr p=L->next;//删除逻辑L->next=p->next;if(L->next!=NULL)L->next->prio=L;//释放节点,置空free(p);p=NULL;//len自减逻辑L->len--;//返回逻辑return 0;
}
//尾删
int list_delete_tail(Node_ptr L)
{//判断逻辑if(L==NULL||list_empty(L)){printf("尾删失败\n");return -1;}//遍历逻辑Node_ptr p=L->next;while(p->next!=NULL) //遍历到最后一个节点{p=p->next;}//删除逻辑p->prio->next=NULL; //倒数第二个节点置空//长度自减L->len--;//返回逻辑printf("尾删成功\n");return 0;}
//任意位置删除
int list_delete_post(Node_ptr L,int post )
{//判断逻辑if(list_empty(L)||post<1||post>L->len){printf("位置删除失败\n");return -1;}//查找逻辑Node_ptr p=list_search_post(L,post);//删除逻辑//最后一个节点只执行一条p->prio->next=p->next;if(p->next!=NULL){   //如果不为最后一个节点p->next->prio=p->prio;}//自减L->len--;//释放节点,置空free(p);p=NULL;//返回逻辑return 0;
}
//任意位置修改
int list_updata_post(Node_ptr L ,int post ,datatype e)
{//判断逻辑if(list_empty(L)||post<1||post>L->len){printf("修改位置不合理\n");return -1;}//查找逻辑Node_ptr p=list_search_post(L,post);//修改逻辑p->data=e;//返回逻辑return 0;
}
//销毁双向链表
int list_free(Node_ptr L)
{//判断逻辑if(L==NULL){printf("销毁失败\n");return -1;}//删除逻辑//结点删除 Node_ptr p=L->next;while(!list_empty(L)){list_delete_head(L);	}//头节点删除free(L);L=NULL;//返回逻辑printf("销毁成功\n");return 0;
}

 Dmain.c

#include"Dlink.h"
int main(int argc, const char *argv[])
{		//接收申请的空间Node_ptr x=list_create();if(x==NULL){printf("申请失败\n");return -1;}printf("申请成功\n");//头插printf("-----------头插-----------\n");list_insert_head(x,'a');list_insert_head(x,'b');list_insert_head(x,'c');list_insert_head(x,'d');list_insert_head(x,'e');list_insert_head(x,'f');list_insert_head(x,'p');list_insert_head(x,'q');printf("-----------遍历------------\n");list_show(x);printf("------按位置查找-----------\n");Node_ptr q=list_search_post(x,3);printf("%c\n",q->data);//按位置插入printf("--------位置插入-----------\n");list_insert_post(x,3,'x');list_insert_post(x,x->len,'z');list_show(x);//头删printf("----------头删-------------\n");list_delete_head(x);list_delete_head(x);list_show(x);//尾删printf("----------尾删-------------\n");list_delete_tail(x);list_delete_tail(x);list_show(x);//尾插printf("----------尾插-------------\n");list_insert_tail(x,'D');list_insert_tail(x,'O');list_show(x);//任意位置删除printf("-------位置删除------------\n");list_delete_post(x,x->len);list_delete_post(x,2);list_show(x);//任意位置修改printf("-------位置修改------------\n");list_updata_post(x,x->len,'G');list_show(x);printf("-------链表销毁------------\n");list_free(x);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/90618.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/90618.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/90618.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[Rust 基础课程]猜数字游戏-获取用户输入并打印

创建项目 按照之前的章节讲的创建一个 Cargo 项目的方法&#xff0c;自己创建一个名为 guessing_game 的 cargo 项目并执行&#xff0c;确保能成功打印出 Hello World。 编写代码 使用 RustRover 打开项目&#xff0c;打开 src/main.rs 文件&#xff0c;我们将在这个文件中编写…

重读《人件》Peopleware -(22)Ⅲ 适当人选 Ⅵ 乐在其中(上)

本章以一个小测验开始&#xff1a;问题1&#xff1a;在过去几年里&#xff0c;你们组织的年员工流失率是多少&#xff1f; 问题2&#xff1a;替换一个离职员工平均需要多少成本&#xff1f;评分标准如下&#xff1a;如果你对这两个问题有任何答案&#xff0c;则通过&#xff1b…

Go、Node.js、Python、PHP、Java五种语言的直播推流RTMP协议技术实施方案和思路-优雅草卓伊凡

Go、Node.js、Python、PHP、Java五种语言的直播推流RTMP协议技术实施方案和思路-优雅草卓伊凡既然我们甲方要做直播私有化&#xff0c;既然我们做了这么多年系统&#xff0c;我们对直播的理解很深&#xff0c;那么我们2025年就应该用更先进的技术栈&#xff0c;不然怎么让我们的…

SpringBoot 集成Mybatis Plus

一、为什么SpringBoot不推荐使用MybatisSpring Boot 不推荐使用 MyBatis&#xff0c;主要源于二者在设计理念、生态融合和开发风格上的差异。Spring Boot 强调“约定优于配置”&#xff0c;追求高效的开发体验和统一的框架风格。它通过自动配置和依赖注入&#xff0c;将复杂的基…

PI 思维升级 PI设计的典范转移:从阻抗思维到谐振控制

们先来回想一件事&#xff0c;根据欧姆定律&#xff0c;阻抗是不是越低越好&#xff1f; 代表即使有很大的瞬时电流&#xff0c;瞬间的电压降也不会超过某个极限&#xff01;理论上是&#xff01; 可是这其实忽略了两个关键的要素&#xff1a;PDN阻抗有谐振&#xff1a;谐振代表…

如何制定企业级服务器安全策略(Security Policy)

制定一套**企业级服务器安全策略&#xff08;Security Policy&#xff09;**对于保护服务器资源、数据安全和业务连续性至关重要。以下是制定安全策略的详细指南&#xff0c;包括安全策略的核心要素、实施步骤和具体措施&#xff0c;帮助企业构建全面的服务器安全防护体系。1. …

n1 armbian docker compose 部署aipan mysql

apt update apt install docker-compose-plugin -y #安装docker compose docker compose version Docker Compose version v2.38.2 sudo mkdir -p /sda1/data/mysql/conf.d sudo chown -R 999:999 /sda1/data/mysql # MySQL 用户 UID 通常为 999 cat docker-compose.yml vers…

RAG情境化分段向量模型voyage-context-3,聚焦分段细节,融入全局文档上下文

最近看到一个有意思的工作&#xff0c;原文来自&#xff1a; https://blog.voyageai.com/2025/07/23/voyage-context-3/?utm_sourceTWITTER&utm_mediumORGANIC_SOCIAL voyage-context-3&#xff1a;聚焦分段细节&#xff0c;融入全局文档上下文 概要&#xff1a; Voyage A…

计算机体系结构中的中断服务程序ISR是什么?

计算机体系结构中的中断服务程序ISR是什么&#xff1f; 在计算机体系结构中&#xff0c;中断服务程序&#xff08;Interrupt Service Routine, ISR&#xff09; 是操作系统或硬件直接调用的关键代码模块&#xff0c;用于响应来自硬件设备、软件异常或系统事件的中断信号。其核心…

开源项目XBuilder前端框架

spx-gui/ 配置文件package.json 项目依赖和脚本配置vite.config.ts Vite构建工具配置tsconfig.json TS项目配置主文件tsconfig.app.json 应用程序的TS配置tsconfig.node.json Node.js环境的TS配置index.html 应用入口HTML文件src/ 源码目录main.ts 应用入口文件&#xff0c;初始…

0723 单项链表

Part 1.完成单向链表&#xff0c;并完成下面功能1.单链表节点创建链表是物理空间上不连续的一个结构&#xff0c;需要创建一个next作为指向下一个节点的指针&#xff0c;所以需要建立一个结构体包含数据域&#xff0c;next指针域&#xff0c;记录长度的数据域。因为长度只有头节…

基于 ASP.NET Web 应用程序(.NET Framework)的花店系统

1.1功能模块实现1.1.1整体结构界面由两部分组成&#xff1a;左侧导航栏、右侧内容展示区。使用了 Bootstrap 5 的样式库&#xff0c;并结合了 ASP.NET MVC 的 Html.ActionLink 和 Razor 条件判断语句来动态生成菜单项。1.1.2导航栏功能模块导航栏基础结构导航栏基础结构使用 Bo…

C++ Qt6 CMake qml文件启动方式说明

在Qt6之后,Qt程序默认使用CMake进行构建,当然也可以使用qmake, 本篇博客介绍Qt6.8之前和Qt6.8版本中QtQuick程序的启动方式。 在QtQuick程序main.cpp里qml的文件启动分为两种:(1)直接加载qml文件,(2)加载qml模块,下面分别介绍这两种启动方式。 方式1:直接启动qml文…

字符串 “asdasjkfkasgfgshaahsfaf” 经过哈夫曼编码之后存储比特数是多少?

要计算字符串 “asdasjkfkasgfgshaahsfaf” 经过哈夫曼编码后的存储比特数&#xff0c;需按以下步骤进行&#xff1a;步骤 1&#xff1a;统计字符出现频率先统计字符串中每个字符的出现次数&#xff1a;a&#xff1a;出现 6 次s&#xff1a;出现 6 次d&#xff1a;出现 1 次j&a…

什么是游戏盾(高防版)?

随着网络游戏产业的快速发展&#xff0c;游戏服务器的安全问题日益受到关注。DDoS攻击、CC攻击等网络威胁常常导致游戏卡顿、断线甚至服务器宕机&#xff0c;严重影响玩家体验。游戏盾&#xff08;高防版&#xff09;是一种专为游戏业务设计的网络安全防护服务&#xff0c;集成…

openGauss数据库在CentOS 7 中的单机部署与配置

部署 版本选择 通过openGuass官网下载地址 &#xff0c;我们可以看到它支持x86_64与Aarch64两种平台&#xff0c;又分成openEuler 22、openEuler 20、Centos 7以及Docker 版本。 进入CentOS 7标签&#xff0c;看到又分成企业版、轻量版、极简版与分布式镜像版。 本文只讨论…

HTTP响应状态码详解

HTTP 响应状态码&#xff08;HTTP Status Code&#xff09;是服务器在响应客户端请求时返回的 3 位数字代码&#xff0c;用于表示请求的处理状态。以下是常见的 HTTP 状态码及其含义&#xff1a; 1xx&#xff08;信息性状态码&#xff09; 表示请求已被接收&#xff0c;需要继…

Pytorch中register_buffer和torch.nn.Parameter的异同

说下register_buffer和Parameter的异同 相同点方面描述追踪都会被加入 state_dict&#xff08;模型保存时会保存下来&#xff09;。与 Module 的绑定都会随着模型移动到 cuda / cpu / float() 等而自动迁移。都是 nn.Module 的一部分都可以通过模块属性访问&#xff0c;如 self…

吉吉巳资源整站源码完整打包,适用于搭建资源聚合/整合类站点,全网独家,拿来就用

想要搭建一个资源整合站点&#xff0c;如影视聚合类站点、资讯聚合类站点、图集聚合类站点等&#xff0c;需要花费大量的时间来查找合适的系统或源码。然后要去测试&#xff0c;修复bug&#xff0c;一直到能够正常的运营使用&#xff0c;花费的时间绝对不短&#xff0c;今天分享…

嵌入式学习的第三十五天-进程间通信-HTTP

TCP/IP协议模型&#xff1a;应用层&#xff1a;HTTP;传输层&#xff1a;TCP UDP;网络层&#xff1a;IPv4 IPv6网络接口层一、HTTP协议1. 万维网WWW(World Wide Web) 世界范围内的&#xff0c;联机式的信息储藏所。 万维网解决了获取互联网上的数据时需要解决的以下问题&#x…