列表之链表_C

数据结构(邓俊辉):列表及相关概念_listnodeposi-CSDN博客

#include <stdio.h>
#include <stdlib.h>// 定义Rank类型为int
typedef int Rank;// 定义ListNode结构体
typedef struct ListNode {int data;struct ListNode* pred;struct ListNode* succ;
} ListNode;// 定义List结构体
typedef struct List {int _size;ListNode* header;ListNode* trailer;
} List;// 链表初始化函数
void init(List* list) {list->header = (ListNode*)malloc(sizeof(ListNode));list->trailer = (ListNode*)malloc(sizeof(ListNode));list->header->succ = list->trailer;list->header->pred = NULL;list->trailer->pred = list->header;list->trailer->succ = NULL;list->_size = 0;
}// 查找函数
ListNode* find(List* list, int e, int n, ListNode* p) {while (0 < n--) {if (e == (p = p->pred)->data) {return p;}}return NULL;
}// 作为首节点插入函数
ListNode* insertAsFirst(List* list, int e) {list->_size++;return list->header->succ = list->header->insertAsSucc(e);
}// 作为末节点插入函数
ListNode* insertAsLast(List* list, int e) {list->_size++;return list->trailer->pred = list->trailer->insertAsPred(e);
}// 作为p的后继插入函数
ListNode* insertA(List* list, ListNode* p, int e) {list->_size++;return p->insertAsSucc(e);
}// 作为p的前驱插入函数
ListNode* insertB(List* list, ListNode* p, int e) {list->_size++;return p->insertAsPred(e);
}// 节点作为前驱插入函数
ListNode* insertAsPred(ListNode* p, int e) {ListNode* x = (ListNode*)malloc(sizeof(ListNode));x->data = e;x->pred = p->pred;x->succ = p;p->pred->succ = x;p->pred = x;return x;
}// 节点作为后继插入函数
ListNode* insertAsSucc(ListNode* p, int e) {ListNode* x = (ListNode*)malloc(sizeof(ListNode));x->data = e;x->pred = p;x->succ = p->succ;p->succ->pred = x;p->succ = x;return x;
}// 复制节点函数
void copyNOdes(List* list, ListNode* p, int n) {init(list);while (n--) {insertAsLast(list, p->data);p = p->succ;}
}// 删除节点函数
int removeNode(List* list, ListNode* p) {int e = p->data;p->pred->succ = p->succ;p->succ->pred = p->pred;free(p);list->_size--;return e;
}// 析构函数
void destroyList(List* list) {clear(list);free(list->header);free(list->trailer);
}// 清除所有节点函数
int clear(List* list) {int oldSize = list->_size;while (0 < list->_size) {removeNode(list, list->header->succ);}return oldSize;
}// 无序去重函数
int deduplicate(List* list) {if (list->_size < 2) {return 0;}int oldSize = list->_size;ListNode* p = list->header;Rank r = 0;while (list->trailer != (p = p->succ)) {ListNode* q = find(list, p->data, r, p);if (q) {removeNode(list, q);} else {r++;}}return oldSize - list->_size;
}// 有序去重函数
int uniquify(List* list) {if (list->_size < 2) {return 0;}int oldSize = list->_size;ListNode* p = list->header->succ;ListNode* q;while (list->trailer != (q = p->succ)) {if (p->data != q->data) {p = q;} else {removeNode(list, q);}}return oldSize - list->_size;
}// 遍历函数
void traverse(List* list, void (*visit)(int*)) {for (ListNode* p = list->header->succ; p != list->trailer; p = p->succ) {visit(&p->data);}
}// 查找函数(有序区间查找)
ListNode* search(List* list, int e, int n, ListNode* p) {while (0 <= n--) {if (((p = p->pred)->data) <= e) {break;}}return p;
}

调试

// 测试函数
void printData(int* data) {printf("%d ", *data);
}int main() {List list;init(&list);// 插入节点测试insertAsFirst(&list, 1);insertAsLast(&list, 3);insertA(&list, list.header->succ, 2);// 遍历测试traverse(&list, printData);printf("\n");// 查找测试ListNode* found = find(&list, 2, list._size, list.trailer);if (found) {printf("找到节点,值为:%d\n", found->data);} else {printf("未找到节点\n");}// 无序去重测试deduplicate(&list);traverse(&list, printData);printf("\n");// 有序去重测试insertAsLast(&list, 3);uniquify(&list);traverse(&list, printData);printf("\n");// 清除并销毁链表destroyList(&list);return 0;
}

在链表相关的数据结构中,“succ” 是 “successor” 的缩写,意思是 “后继者、继任者” 。在链表节点的定义中,将指针命名为 succ 就是用来指向当前节点的下一个节点,即后继节点。

这里的 pred 是 “predecessor” 的缩写,表示 “前驱者、前一个” ,pred 指针指向当前节点的前一个节点;

  • header:即头哨兵节点,它处于链表的起始位置,但并不存储实际的数据。其主要用途是作为链表第一个有效节点的前驱节点,便于对链表的操作。
  • trailer:也就是尾哨兵节点,它位于链表的末尾,同样不存储实际的数据。它的作用是作为链表最后一个有效节点的后继节点。

数据结构(邓俊辉):列表及相关概念_listnodeposi-CSDN博客

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

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

相关文章

0401react中使用css-react-css-仿低代码平台项目

文章目录 1、普通方式-内联使用css2、引入css文件2.1、示例2.2、classnames 3、内联css与引入css文件对比3.1、内联css3.2、 外部 CSS 文件&#xff08;External CSS&#xff09; 4、css module5、sass6、classnames组合scss modules7、css-in-js7.1、CSS-in-JS 的核心特性7.2、…

鸿蒙开发者高级认证编程题库

题目一:跨设备分布式数据同步 需求描述 开发一个分布式待办事项应用,要求: 手机与平板登录同一华为账号时,自动同步任务列表任一设备修改任务状态(完成/删除),另一设备实时更新任务数据在设备离线时能本地存储,联网后自动同步实现方案 // 1. 定义分布式数据模型 imp…

stream流Collectors.toMap(),key值重复问题

文章目录 一、问题二、问题示例三、原因四、解决方法4.1、方案一 一、问题 发现Collectors.toMap的一个坑&#xff0c;若key值重复的时候会抛异常。如&#xff1a; IllegalStateException: Duplicate key 男 二、问题示例 报错示例如下&#xff1a; import lombok.AllArgsC…

未来 AI 发展趋势与挑战(AGI、数据安全、监管政策)

从 ChatGPT 的火爆到国内 DeepSeek、通义千问、百川智能等模型的兴起,AI 正以前所未有的速度走入各行各业。而下一阶段,AI 是否会发展出真正的“通用智能”(AGI)?数据隐私、技术伦理又该如何应对?本文将带你全面洞察未来 AI 的技术趋势与落地挑战。 一、AGI 的曙光:通用…

【微服务】SpringBoot整合LangChain4j 操作AI大模型实战详解

【微服务】SpringBoot整合LangChain4j 操作AI大模型实战详解 一、前言 随着人工智能技术的飞速发展&#xff0c;AI大模型已经在众多领域展现出强大的能力&#xff0c;为业务拓展和商业价值提升带来了新的机遇。SpringBoot作为一款广受欢迎的Java微服务框架&#xff0c;以其简…

一种单脉冲雷达多通道解卷积前视成像方法【论文阅读】

一种单脉冲雷达多通道解卷积前视成像方法-李悦丽-2007 1. 论文的研究目标与实际意义1.1 研究目标1.2 实际问题与产业意义2. 论文提出的思路、方法及模型2.1 多通道解卷积(MCD)技术的核心思想2.1.1 数学模型与公式推导2.1.2 针对单脉冲雷达的改进2.2 方法与传统技术的对比3. 实…

Codeforces Round 1016 (Div. 3)题解

题目地址 https://codeforces.com/contest/2093 锐评 在所有题意都理解正确的情况下&#xff0c;整体难度不算太难。但是偏偏存在F这么恶心的题意&#xff0c;样例都不带解释一下的&#xff0c;根本看不懂题。D题也恶心&#xff0c;在于递归过程的拆分&#xff0c;需要点数学…

【python读取并显示遥感影像】

在Python中读取并显示遥感影像&#xff0c;可以使用rasterio库读取影像数据&#xff0c;并结合matplotlib进行可视化。以下是一个完整的示例代码&#xff1a; import rasterio import matplotlib.pyplot as plt import numpy as np# 打开遥感影像文件 with rasterio.open(path…

怎样使用Python编写的Telegram聊天机器人

怎样使用Python编写的Telegram聊天机器人 代码直接运行可用 以下是对这段代码的详细解释: 1. 导入必要的库 import loggingfrom telegram import Update from telegram.ext import ApplicationBuilder, ContextTypes, CommandHandler, filters, MessageHandler import log…

moviepy学习使用笔记

目录 1. moviepy安装版本选择安装命令2. 使用文档1.0.3文档中文文档写的比较好的学习博客2.x文档1.0.3到2.x快速上手3. 可能遇到的问题3.1 依赖问题3.2 中文显示问题4. 特效示例中文显示的问题1. moviepy安装 版本选择 moviepy有两个主流版本: 1.0.3 和 2.x 目前2.x版本称不…

docker各种清空缓存命令,下载jdk包总失败,执行完好了

清理未使用的镜像&#xff08;推荐&#xff0c;最常用&#xff09;&#xff1a; docker image prune -a 清理所有未使用的数据&#xff08;包括镜像、容器、网络和构建缓存&#xff09;&#xff1a; docker system prune -a 清理所有未使用的数据&#xff0c;包括未使用的卷…

NO.78十六届蓝桥杯备战|数据结构-并查集|双亲表示法|初始化|查询|合并|判断|亲戚|Lake Counting|程序自动分析(C++)

双亲表⽰法 接下来要学习到的并查集&#xff0c;本质上就是⽤双亲表⽰法实现的森林。因此&#xff0c;我们先认识⼀下双亲表⽰法。 在学习树这个数据结构的时&#xff0c;讲到树的存储⽅式有很多种&#xff1a;孩⼦表⽰法&#xff0c;双亲表⽰法、孩⼦双亲表⽰法以及孩⼦兄弟表…

Ubuntu挂载HDD迁移存储PostgreSQL数据

关联博客&#xff1a;windows通用网线连接ubuntu实现ssh登录、桌面控制、文件共享 背景&#xff1a; 在个人ubuntu机器上安装了pgsql&#xff0c;新建了一张表插入了2000w数据用于模拟大批量数据分页查询用&#xff0c;但是发现查询也不慢&#xff08;在公司测试环境查询1700…

Spring MVC与Spring Boot文件上传配置项对比

Spring MVC与Spring Boot文件上传配置项对比 一、Spring MVC配置项&#xff08;基于不同MultipartResolver实现&#xff09; 1. 使用 CommonsMultipartResolver&#xff08;Apache Commons FileUpload&#xff09; Bean public MultipartResolver multipartResolver() {Common…

Android 学习之 Navigation导航

1. Navigation 介绍 Navigation 组件 是 Android Jetpack 的一部分&#xff0c;用于简化应用内导航逻辑&#xff0c;支持 Fragment、Activity 和 Compose 之间的跳转。核心优势&#xff1a; 单 Activity 架构&#xff1a;减少 Activity 冗余&#xff0c;通过 Fragment 或 Com…

Docker Compose 部署Nginx反向代理 tomcat

Nginx 、Tomcat (默认端口8080)》》compose services:nginx:image: nginx:latestcontainer_name: nginxrestart: alwaysports:- 80:80- 8080:8080volumes:# 文件夹会自动创建&#xff0c;但nginx.conf是文件&#xff0c;需要提前创建&#xff0c;否则 会自动创建nginx.conf文件…

数据库7(数据定义语句,视图,索引)

1.数据定义语句 SQL数据定义语言&#xff08;DDL&#xff09;用于定义和管理数据库结构&#xff0c;包括创建、修改和删除 数据库对象。常见的DDL语句包括CREATE、DROP和ALTER。 它的操作的是对象&#xff0c;区分操作数据的语句&#xff1a;INSERT,DELETE,UPDATE 示例&#x…

QML面试笔记--UI设计篇02布局控件

1. QML 中常用的布局控件 1.1. Row1.2. Column1.3. Grid1.4. RowLayout1.5. ColumnLayout1.6. GridLayout1.7. 总结 1. QML 中常用的布局控件 1.1. Row 背景知识&#xff1a;Row 布局用于将子元素水平排列&#xff0c;适合简单的线性布局&#xff0c;如工具栏按钮或表单输入…

Compose组件转换XML布局1.0

文章目录 学习JetPack Compose资源前言&#xff1a;预览界面的实现Compose组件的布局管理一、Row和Colum组件&#xff08;LinearLayout&#xff09;LinearLayout&#xff08;垂直方向 → Column&#xff09;LinearLayout&#xff08;水平方向 → Row&#xff09; 二、相对布局 …