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

单项链表的操作及其实现

单项链表的操作及其实现

很好我们已经明白了顺序表的实现了

如果不明白请看我的数据结构专栏中顺序表的文章

我们来简单的复习一下顺序表

顺序表:

1.物理上连续的空间,下标作为索引号,按位置访问效率高。

2.逻辑上连续的,查找某个值,从头到尾依次查找。

3.尾插入/删除,效率高,任意位置的插入/删除,后续数据的向后/向前搬移,效率低。

4.物理上连续空间条件苛刻 会有内存碎片 申请连续空间可能失败

为啥连续的空间条件苛刻,我简单的来个比喻你就明白了,如果你想要再一条步行街上买上十间商铺,那如果这个步行街已经有一段时间了,你买十间连续的商铺肯定比你买十间不连续的商铺要难的多,为什么?这还用说,肯定是其他的商铺主了,你无法将十间商铺连这买,但是你要是将十间商铺分开买就简单的多了。

依次类推我们的内存也是这样一个道理,而在数据结构中我们将这种方法称之为链表

那么我们正式来开始我们的链表学习

单项链表的结构说明

链式存储:

1.利用物理上不连续的空间,表示逻辑上的连续

上面商铺的比喻很是形象的说明了这个特性

2.节点结构 也就是数据+指针域

也就是我们经常看见的图

在这里插入图片描述

3.按位置查找,值查找,效率低,只能按顺序逐一查找

为啥?因为你没法一下子定位位置只能一步步的向前走

走到一你才知道二,走到二你才知道三,这叫真正的走一步看一步

4.插入,删除,效率高?

一般我们的书上都会写效率高,但是效率高是有条件的,因为我们今天讲的链表叫做单向链表,何为单向一句话,开弓没有回头箭,一旦向前走了就没有办法退回来,所以我们在向前移动的时候一定要先考虑清楚。

好的,现在我们如果在x位置插入元素,必须在x的前一个位置上守着,所以如果是寻找值插入删除,效率其实也不见得高多少,但是如果是头插那效率肯定很高。

如何插入/删除

根据刚才讲的,你要思考清楚然后再去插入/删除,那么如何思考呢?

先说插入

其实插入和做菜一样,首先我们要找到插入的位置的前一个(你直接指向插入位置没法删),其次我们要先准备一个新节点,新节点需要数据+指针域,数据好处理那指针域是哪里的呢?

很显然我相信聪明的你一定可以想到用前一个节点的指针域,这样我们就制作完成了一个全新的节点,而后插入的操作很简单,直接将前一个节点的指针域指向新的节点,就完成了一个插入操作了。

很好,我相信你一定已经被绕晕了

来个图搭配食用

在这里插入图片描述

总结一下:

插入新节点

1.引入辅助指针p,p找到待插入位置的前一个位置。

2.创建新节点。

3.更新新节点。

4.最后更新老节点。

再说删除

还是熟悉的套路,先找到删除的前一个位置,然后从新定义一个指针,将要删除的节点地址先复制一份到新节点上,将所选位置的前一个指向它删除位置的下一个节点,最后释放掉你需要删除的位置的空间。

很好其实这个过程有点像倒垃圾,你先找到垃圾,然后找个垃圾桶,将你不需要的垃圾放入垃圾桶,然后收拾好自己的东西,最后再将垃圾倒掉。

转化为代码就是

tmp=p->next;
p->next=temp->next;
free(tmp);

总结一下

删除某个节点:

1.引入辅助指针p,p找到待删除的前一个节点

2.引入辅助指针备份待删除位置tmp。

3.更新前一个节点,然后释放位置。

我们思想方面也可以总结一下

1.核心结构:节点

2.开弓没有回头箭,不要轻易的p=p->next;

3.备份思想

带头节点vs带头指针

带头节点

何为带头节点,其实所谓带带头结点其实就是在头上多加一个没有值的节点,用这个节点来作为链表的开始,虽然可能会浪费一点空间但是使用起来很方便。

如图

在这里插入图片描述

那么其实我们会发现一个问题,当一个节点的使用的空间很大的时候,我们用带头结点的方式会有一点浪费空间,但是比较好的一点就是它其实比较好操作。

为了解决浪费空间的问题

人们就想出了一个办法,用一个指针来表示头节点。

带头指针

其实就是用一个指针来表示头节点,虽然方便但是需要时刻的变换

如图

在这里插入图片描述

你需要时刻的判断好你的头节点是否指向正确的地方,对于初学者来说有些难度。

所以,我们还是建议使用带头节点的链表。

单项链表的实现代码

很顺序表的实现一样,先写结构定义,然后写结构操作的接口,而后一一实现这些接口,最后对这些接口进行测试。

这样的一套丝滑小连招是我们必不可少的

好的我们来一一的实现吧

结构定义+结构操作的接口


#ifndef LINKLIST_H
#define LINKLIST_H
typedef int Element_t;//实现节点
typedef struct _node {Element_t data;struct _node*next;
}node_t;//实现头节点
typedef struct {node_t head;int cout;
}Linklist_t;
//初始化
Linklist_t* createlinklist();
//释放空间
void releaselinklist(Linklist_t* list);//插入
int insertLinklistHeader(Linklist_t* table, Element_t data);//头插法
int insertLinklistpos(Linklist_t* table,int number, Element_t data);//按位置插入//删除
int deleteLinklistHeader(Linklist_t* table, Element_t data);//打印
void printLinklist(const Linklist_t* table);#endif //LINKLIST_H

对结构定义的实现


#include <stdio.h>
#include"linkList.h"#include <stdlib.h>Linklist_t * createlinklist() {Linklist_t*take=NULL;take=(Linklist_t*)malloc(sizeof(Linklist_t));if (take==NULL) {return NULL;}take->cout=0;take->head.data=0;take->head.next=NULL;return take;
}int insertLinklistHeader(Linklist_t *table, Element_t data) {node_t *p=&table->head;node_t* newnode=(node_t*)malloc(sizeof(node_t));if (newnode==NULL) {return -1;}newnode->data=data;newnode->next=p->next;p->next=newnode;;++table->cout;return 0;
}int insertLinklistpos(Linklist_t *table, int number, Element_t data) {//判断边界条件if (number<0||number>table->cout) {return -1;}//寻找到插入位置node_t *p=&table->head;int node=-1;while (node<number-1) {p=p->next;node++;}//插入node_t *newnode=(node_t*)malloc(sizeof(node_t));newnode->data=data;newnode->next=p->next;p->next=newnode;++table->cout;return 0;
}int deleteLinklistHeader(Linklist_t *table, Element_t data) {node_t *p=&table->head;//找while (p->next) {if (p->next->data==data) {break;}p=p->next;}//判断是否为空if (p->next==NULL) {printf("No find");return-1;}//删除node_t*node=p->next;p->next=node->next;free(node);table->cout--;return 0;}void releaselinklist(Linklist_t *list) {if (list) {node_t* p=&list->head;node_t* node;while (p->next) {node=p->next;p->next=node->next;free(node);list->cout--;}printf("link list number %d",list->cout);free(list);}}void printLinklist(const Linklist_t *table) {node_t* p=table->head.next;printf("link list number %d\n:",table->cout);while (p) {printf(" %d ",p->data);p=p->next;}printf("\n");
}

测试

#include <stdio.h>#include "linkList.h"int main() {printf("Hello linkList\n");Linklist_t*table=createlinklist();if (table==NULL)return -1;for (int i=0;i<10;i++) {insertLinklistHeader(table,i+100);}insertLinklistpos(table,3,300);deleteLinklistHeader(table,109);printLinklist(table);releaselinklist(table);return 0;
}
e);return 0;
}

测试结果

在这里插入图片描述

好得这篇博客到这里就结束了,喜欢记得点一个小小的赞哦(๑′ᴗ‵๑)I Lᵒᵛᵉᵧₒᵤ❤

相关文章:

  • 【二叉树】(四)二叉搜索树的基础修改构造及属性求解1
  • Spring 事务传播行为详解
  • AbMole小课堂:从肿瘤研究到体内模型构建,Mitomycin C一“剂”搞
  • 寻找区域中的面积和中心点
  • java哨兵底层原理
  • linux下安装所有用户能共享的anaconda
  • rocketmq producer和consumer连接不同的集群,如何隔离
  • Windows10电脑开始菜单快速查找应用程序
  • Web网页端即时通讯源码/IM聊天源码RainbowChat-Web
  • RocketMQ总结
  • 导出支付宝账单步骤
  • Unity 接入抖音小游戏一
  • 【指针和函数求数组的相反数】2022-5-21
  • 聊一聊 - 如何写好README文档
  • MCP(模型上下文协议)——AI生态的“万能插座”
  • 改写爬虫, unsplash 图片爬虫 (网站改动了,重写爬虫)
  • Python基础之函数(1/3)
  • 使用ubuntu串口数据收和发不一致问题
  • LangServe 完整使用指南:部署LangChain应用到生产环境
  • Python队列与堆栈深度解析:从基础实现到高并发消息系统的实战之旅
  • 数据标注接单平台/淘宝怎样优化关键词
  • 用vs做网站的教程/免费个人网站建站申请
  • 适合个人站长的网站有哪些/业务推广公司
  • 简单自适应网站/搜索引擎优化特点
  • 河南两学一做网站/怎么开个人网站
  • wordpress随机图片/萧山seo