1.2 单链表定义及操作实现(链式结构)

1.单链表定义

链式存储:用一组任意的存储单元存储线性表中的数据元素。用这种方法存储的线性
表简称线性链表。
        为了正确表示结点间的逻辑关系,在存储每个结点值的同时,还必须存储指示其直接
后继结点的地址(或位置),称为指针( pointer )或链( link ),这两部分组成了链表中
的结点结构。
data :数据域,存放结点的值。
next :指针域,存放结点的直接后继的地址。
链表是通过每个结点的指针域将线性表的 n 个结点按其逻辑次序链接在一起的。
每一个结只包含一个指针域的链表,称为单链表。
注意:
1)存储链表中结点的一组任意的存储单元 可以是连续的, 也可以是不连续的,甚至是零散分布在内存中的任意位置上的。
2)链表中结点的逻辑顺序和物理顺序不一定相同。
3) 为操作方便 ,总是在链表的第一个结点之前 附设一个头结点(头指针)head 指向第一个结点 。头结点的数据域可以不存储任何信息(或链表长度等信息)。

2.结点的实现

typedef struct LNode {int data;//数据域struct LNode *next;//指针域
}LNode, *LinkList;
结点是通过动态分配和释放来的实现,即需要时分配,不需要时释放。实现时是分别
使用 C 语言提供的标准函数: malloc () , realloc (), sizeof () , free () 。
动态分配 p= LNode* malloc sizeof LNode ));

3.单链表操作

3.1.创建结点

LNode* node_create(int value, LNode* next) {LNode* node = (LNode*)malloc(sizeof(LNode));if (node != nullptr) {node->data = value;node->next = next;}return node;
}

3.2.创建链表

/*** 创建一个空链表,只包含头结点head*/
LinkList list_create() {return node_create(0, nullptr);//return head node
}
/*** 创建链表,并以形参列表初始化调用方法:LinkList list = list_create({1,2,3,4});*/
LinkList list_create(std::initializer_list<int> args) {LinkList list = node_create(0, nullptr);//create head nodeLNode* curr = list;for (int i : args) {curr->next = node_create(i, nullptr);curr = curr->next;}return list;
}/*** 释放链表占用内存空间*/
bool list_free(LinkList list) {if (list == nullptr) {return false;}for (LNode* curr = list; curr != nullptr; ) {LNode* next = curr->next;free(curr);curr = next;}return true;
}

3.3.查找元素

3.3.1.按序号查找

//查找第i(i>=1)个元素
int get_elem(LinkList list, int i) {if (list == nullptr || i < 1 || i > INT_MAX) {return INT_MIN;//return invalid value}int j = 1;LNode* cur = list->next;while (cur != nullptr && j < i) {cur = cur->next;j += 1;}return i == j ? cur->data : INT_MIN;
}

3.3.2.按值查找

/*** 按值查找* 按值查找是在链表中,查找是否有结点值等于给定值 key 的结点? 若有,则返回首次找到的值为 key 的结点的存储位置;否则返回 NULL	*/
LNode* node_locate(LinkList list, int key) {if (list == nullptr || list->next == nullptr) {return nullptr;}LNode* cur = list->next;for (; cur != nullptr && cur->data != key; cur = cur->next);return cur == nullptr || cur->data != key ? nullptr : cur;
}

3.4.插入元素

/*** 插入运算是将值为 e 的新结点插入到表的第 i 个结点的位置上,即插入到 ai-1 与 ai之间。*/
bool list_insert(LinkList list, int i, int e) {if (list == nullptr) {return false;}LNode* cur = list;//head nodefor (int j = 1; cur != nullptr && j < i; cur = cur->next)j += 1;if (cur == nullptr) {//cur point (i-1) nodereturn false;}LNode* node = node_create(e, cur->next);cur->next = node;return true;
}

3.5.删除元素

3.5.1.按序号删除

/*** 按序号删除* 删除单链表中的第 i 个结点* 时间复杂度也是 O(n)*/
bool list_delete(LinkList list, int i, int* e) {if (list == nullptr || list->next == nullptr) {return false;}LNode* cur = list;for (int j = 1; cur != nullptr && j++ < i; cur = cur->next);//cur结点指向a[i-2]结点if (cur == nullptr || cur->next == nullptr) {return false;}LNode* curi = cur->next;//curi结点指向a[i-1]结点,需要被删除if (e != nullptr) {*e = curi->data;}cur->next = curi->next;free(curi);return true;
}

3.5.2.按值删除

/*** 按值删除* 删除单链表中值为 key 的第一个结点。*/
bool list_delete(LinkList list, int key) {if (list == nullptr || list->next == nullptr) {return false;}LNode* prev = list,*curr = list->next;while(curr != nullptr && curr->data != key) {prev = curr;curr = curr->next;}if (curr == nullptr || curr->data != key) {//未找到,返回失败return false;}prev->next = curr->next;free(curr);//释放被删除元素的内存空间return true;
}

3.5.3.按值删除变形1

/*** 按值删除* 删除单链表中值为 key 的所有结点。*/
bool list_delete_all(LinkList list, int key) {if (list == nullptr || list->next == nullptr) {return false;}LNode *prev = list, *curr = list->next;while (curr != nullptr) {if (curr->data == key) {prev->next = curr->next;free(curr);curr = prev->next;}else {prev = curr;curr = curr->next;}}return true;
}

3.5.4.按值删除变形2

/*** 去重函数* 删除单链表中所有值重复的结点,使得所有结点的值都不相同* 基本思想:从单链表的第一个结点开始,对每个结点进行检查:检查链表中该结点的所有后继结点,只要有值和该结点的值相同,则删除之;然后检查下一个结点,直到所有的结点都检查。*/
bool list_unique(LinkList list) {if (list == nullptr || list->next == nullptr) {return false;}LNode* curr = list->next;while (curr != nullptr) {LNode* pi = curr->next;//内层循环指针LNode* prev = curr;//内层循环指针while (pi != nullptr) {if (curr->data == pi->data) {prev->next = pi->next;free(pi);pi = prev->next;}else {prev = pi;pi = pi->next;}}curr = curr->next;}return true;
}

3.6.链表合并

/*** 设有两个有序的单链表,它们的头指针分别是 La 、Lb,将它们合并为以 Lc 为头指针的有序链表若 La,Lb 两个链表的长度分别是 m,n,则链表合并的时间复杂度为 O(m+n)*/
LinkList merge_linklist(LinkList la, LinkList lb) {if (la == nullptr || la->next == nullptr) {//la为空,直接返回lbreturn lb;}else if (lb == nullptr || lb->next == nullptr) {return la;}LinkList lc = list_create();LNode* pc = lc;LNode* pa = la->next, * pb = lb->next;//[1]每次从la,lb取出数据并比较,将小的数据存入lcwhile (pa != nullptr && pb != nullptr) {if (pa->data <= pb->data) {pc->next = node_create(pa->data, nullptr);pc = pc->next;pa = pa->next;}else {pc->next = node_create(pb->data, nullptr);pc = pc->next;pb = pb->next;}}//[2]lb的数据取完,将剩余la数据全部存入lcwhile (pa != nullptr) {//pb == nullptr pc->next = node_create(pa->data, nullptr);pc = pc->next;pa = pa->next;}//[3]la的数据取完,将剩余lb数据全部存入lcwhile (pb!= nullptr) {//pa == nullptrpc->next = node_create(pb->data, nullptr);pc = pc->next;pb = pb->next;}return lc;
}

3.7.辅助函数

3.7.1.打印链表

/*** 打印单链表(辅助函数)*/
bool list_print(LinkList list) {if (list == nullptr) {return false;}printf("[");for (LNode* cur = list->next; cur != nullptr; cur = cur->next) {printf("%d", cur->data);printf("%s", cur->next == nullptr ? "" : ",");}printf("]\n");
}

3.7.2包含头文件

#ifndef __IOSTREAM_H__
#define __IOSTREAM_H__
#include <iostream>
#endif#ifndef __STDIO_H__
#define __STDIO_H__
#include <stdio.h>
#endif#ifndef __STDARG_H__
#define __STDARG_H__
#include <stdarg.h>
#endif#ifndef __INITIALIZER_LIST__
#define __INITIALIZER_LIST__
#include <initializer_list>
#endif

3.7.3测试函数

void test1() {LinkList list = list_create({1,2,3,4,5});list_print(list);int e = get_elem(list, 3);printf("%d\n", e);printf("len = %d\n", get_length(list));printf("node_locate(list, 3) = %x\n", node_locate(list, 3));printf("node_locate(list, 7) = %x\n", node_locate(list, 7));list_free(list);
}void test2() {LinkList list = list_create({1,2,3,4});list_print(list);list_insert(list, 2, 8);printf("list_insert(list, 2, 8)\n");list_print(list);list_free(list);
}void test3() {LinkList list = list_create({1,2,3,4});list_print(list);list_delete(list, 2, nullptr);list_print(list);list_delete(list, 2, nullptr);list_print(list);list_delete(list, 2, nullptr);list_print(list);list_free(list);
}void test4() {LinkList list = list_create({1,2,3,4});list_print(list);list_delete(list, 2);list_print(list);list_delete(list, 4);list_print(list);list_free(list);
}void test5() {LinkList list = list_create({1,2,3,6,2,2,7,8});list_print(list);list_delete_all(list, 2);list_print(list);list_free(list);
}void test6() {LinkList list = list_create({ 1,2,3,6,2,2,7,8 });list_print(list);list_unique(list);list_print(list);list_free(list);
}void test7() {LinkList la = list_create({1,3,5,9});LinkList lb = list_create({2,4,6,7,8,10});list_print(la);list_print(lb);LinkList lc = merge_linklist(la, lb);list_print(lc);
}

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

04-Charles中的Map Remote和Map Local介绍

Charles提供了Map Remote和Map Local两个功能。 Map Remote是将指定的网络请求重定向到另一个网址。Map Local是将指定的网络请求重定向到本地文件。 一、Map Remote 假设代码中调用了接口A&#xff0c;但是接口A的响应结果不能满足需求&#xff1b;此时&#xff0c;有另一个…

第15周 Zookeeper分布式锁与变种多级缓存

Zookeeper **************************************************************

heic怎么转换成jpg?heic转jpg,分享6款图片格式转换器免费汇总!

众所周知&#xff0c;在与非苹果手机设备用户&#xff08;如安卓手机或Windows台式机用户&#xff09;分享照片之前&#xff0c;通常需要将iphone的heic格式转换为jpg。由于这些操作系统的旧版本不原生支持heic图片格式&#xff0c;因此需要额外的第三方工具来查看这些图像。因…

0727,学什么学,周六就应该休息!!!!!

周六就应该休息&#xff0c;一天就忙了两小时也不是我的错喵 目录 UDP的小总结 01&#xff1a;使用select实现一个基于UDP的一对一即时聊天程序。 1.0 复读机服务器和树洞客户端 2.0 byby不了一点的敬业服务器&#xff01;&#xff01;&#xff01; 今天到此为止&#x…

24暑假算法刷题 | Day22 | LeetCode 77. 组合,216. 组合总和 III,17. 电话号码的字母组合

目录 77. 组合题目描述题解 216. 组合总和 III题目描述题解 17. 电话号码的字母组合题目描述题解 77. 组合 点此跳转题目链接 题目描述 给定两个整数 n 和 k&#xff0c;返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按 任何顺序 返回答案。 示例 1&#xff1a; 输…

面向切面编程(AOP)

通知类型 Grep Console插件可右键选中日志高亮显示 正常情况 异常情况(around after和目标方法在一起&#xff0c;目标方法异常后&#xff0c;around after不执行) 通知顺序 execution 需要匹配两个没有任意交集的方法时&#xff0c;可以使用两个execution annotation 自定义…

【计算机网络】期末实验答辩

注意事项&#xff1a; 1&#xff09;每位同学要在下面做过的实验列表中选取三个实验进行答辩准备&#xff0c;并将自己的姓名&#xff0c;学号以及三个实验序号填入共享文档"1&#xff08;2&#xff09;班答辩名单"中。 2&#xff09;在答辩当日每位同学由老师在表…

支持向量机 及其分类案例详解(附Python 代码)

支持向量机分类器预测收入等级 我们将构建一个支持向量机&#xff08;SVM&#xff09;分类器&#xff0c;以预测一个人基于14个属性的收入等级。我们的目标是判断收入是否高于或低于每年$50,000。因此&#xff0c;这是一个二元分类问题。我们将使用在此处可用的人口普查收入数…

Python高维度大型气象矩阵存储策略分享

零、前情提要 最近需要分析全球范围多变量的数值预报数据&#xff0c;将grb格式的数据下载下来经过一通处理后需要将预处理数据先保存一遍&#xff0c;方便后续操作&#xff0c;处理完发现此时的数据维度很多&#xff0c;数据量巨大&#xff0c;使用不同的保存策略的解析难度和…

nowcoder bc49判断两个数的大小关系

描述 KiKi想知道从键盘输入的两个数的大小关系&#xff0c;请编程实现。 输入描述&#xff1a; 题目有多组输入数据&#xff0c;每一行输入两个整数&#xff08;范围-231~231-1&#xff09;&#xff0c;用空格分隔。 输出描述&#xff1a; 针对每行输入&#xff0c;输出两…

zotfile基础配置详解

zotfile可以将自动移动pdf到指定文件夹中&#xff0c;那么应该如何配置呢&#xff1f; 遵循极简原则&#xff0c;只需配置两个地方即可。 一、路径配置 第一处是pdf附件存放的位置&#xff0c;可以指定自己想要的地方&#xff0c;我放在了C盘的文档文件夹下。 第二处是分类法…

由恶劣事件: CrowdStrike发布案例更新导致微软全球蓝屏事件的启示

前言 网络安全公司 CrowdStrike 周四发布软件更新后&#xff0c;机场、银行、证券交易所、911 服务、交通系统、酒店、新闻媒体、医院、紧急服务等开始出现臭名昭著的蓝屏死机 (BSOD)。在看似多年来最严重的 IT 中断中&#xff0c;大规模的网络安全软件问题正在全球范围内造成…

【七】Hadoop3.3.4基于ubuntu24的分布式集群安装

文章目录 1. 下载和准备工作1.1 安装包下载1.2 前提条件 2. 安装过程STEP 1: 解压并配置Hadoop选择环境变量添加位置的原则检查环境变量是否生效 STEP 2: 配置Hadoop2.1. 修改core-site.xml2.2. 修改hdfs-site.xml2.3. 修改mapred-site.xml2.4. 修改yarn-site.xml2.5. 修改hado…

C/C++大雪纷飞代码

目录 写在前面 C语言简介 EasyX简介 大雪纷飞 运行结果 写在后面 写在前面 本期博主给大家带来了C/C实现的大雪纷飞代码&#xff0c;一起来看看吧&#xff01; 系列推荐 序号目录直达链接1爱心代码https://want595.blog.csdn.net/article/details/1363606842李峋同款跳…

Linux笔记 --- 程序入门

‘\n’换行符 通常来讲我们都是使用这个符号来进行换行的操作&#xff0c;但是这个符号不仅仅是用于换行 当标准输出文件中默认使用缓冲 &#xff0c;也就是当遇到 \n 的时候会进行刷新缓冲区&#xff08;把数据输 出&#xff09; 当打印语句后面没有换行符时 &#xff0c; 需要…

强烈推荐这 3 款让你用一次就爱上,永不想删除的软件

IcecreamPDFEditor IcecreamPDFEditor是一款功能强大的PDF编辑工具&#xff0c;具备多种编辑和查看PDF文件的功能。这款软件不仅可以方便地阅读和查看各种PDF文件&#xff0c;还可以进行编辑操作。它拥有编辑文本、注释添加、页面管理以及PDF文件保护等功能。 用户可以通过下载…

JS逆向高级爬虫

JS逆向高级爬虫 JS逆向的目的是通过运行本地JS的文件或者代码,以实现脱离他的网站和浏览器,并且还能拿到和浏览器加密一样的效果。 10.1、编码算法 【1】摘要算法&#xff1a;一切从MD5开始 MD5是一个非常常见的摘要(hash)逻辑. 其特点就是小巧. 速度快. 极难被破解. 所以,…

ELK安装(Elasticsearch+Logstash+Kibana+Filebeat)

一、简介 1.1、软件简介 ELK其实是Elasticsearch&#xff0c;Logstash 和 Kibana三个产品的首字母缩写&#xff0c;这三款都是开源产品。 1.1.1、Elasticsearch简介 Elasticsearch 是一个分布式、高扩展、高实时的搜索与数据分析引擎。它能很方便的使大量数据具有搜索、分析…

研究生选择学习Android开发的利与弊?

在开始前刚好我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「Android的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01;产品经理可以学学Axure快…

简单的CSS样式

样式分为三种 内部样式&#xff1a;写在html文件里的样式叫内部样式 内联样式&#xff1a;写在需要的标签中 外部样式&#xff1a;写在外部css文件里 可以通过不同的选择器来选择设置指定组件的样式&#xff1a; <style>/* 写在html文件里的样式叫内部样式 *//* 选择器 *…