1.链表的实现:不带哨兵

news2024/11/22 13:18:32

一、链表linked list

1.定义

链表是数据元素的线性集合,其每个元素都指向下一个元素,元素存储上并不连续,链表逻辑连续。

2.分类

①单向链表:每个元素只知道其下一个元素是谁

②双向链表: 每个元素知道其上一个元素和下一个元素

 ③循环链表

3.哨兵节点

不存储数据,用作头尾,用来简化边界判断

4.链表性能

①随机访问(读取)

根据index查找,时间复杂O(n)。

根据索引查找元素的时候,要从头节点挨个查找

②插入或删除

起始位置:O(1)

结束位置:已知尾节点是O(1),不知道尾结点是O(n)

中间位置:根据index查找时间+O(1)

二、单向链表,不带哨兵

1.代码实现

 ①定义节点

public class SinglyLinkedList{

	/**
	 * 节点类
	 * 数据域和地址域
	 */
	private static class Node {
		int value;// 值
		Node next;// 指向下一个节点,因为节点的类型是Node

		public Node() {
		}

		public Node(int value, Node next) {
			this.value = value;
			this.next = next;
		}

	}

	private Node head; //头指针
}

②头部添加:每次是往表头依次添加,把新节点指向此时的head。然后让head再指向新节点。

如果head是null,就是head = new Node(value,null)

	public void addFirst(int value) {
		// 1.链表为空时,head是null 相当于head = new Node(value,null)
		// 2.链表不为空时,new Node(value,head) 然后把新节点当为头结点head = new Node(value,head)
		// 3.优化如下
		head = new Node(value, head);
	}

②尾部添加:先找到最后一个节点的地址 while(p.next != null),如果链表为空,返回null

	public Node findLast() {
		// 判断是否为空
		if (head == null) {
			return null;
		}
		// 链表不为空
		Node p = head;
		while (p.next != null) {
			p = p.next;
		}
		return p;
	}

返回的是最后一个节点地址last.next=new Node(value, null);如果返回的是null,那么就表头添加。

	public void addLast(int value) {
		Node last = findLast();
		if (last == null) {
			addFirst(value);
			return;
		}
		// 找到尾巴节点
		last.next = new Node(value, null);
	}

③遍历节点1:定义一个辅助节点p指向头结点,条件是while(p!=null),一直到链表为空

	/**
	 * 2.遍历节点1
	 */
	public void loop1() {
		Node p = head;
		while (p != null) {
			System.out.println(p.value);
			p = p.next;
		}
	}

	/**
	 * 遍历节点2
	 */
	public void loop2() {
		for (Node p = head; p != null; p = p.next) {
			System.out.println(p.value);
		}
	}

也可以用增强for循环,重写iterator()

public class SinglyLinkedList implements Iterable<Integer> {


....

	@Override
	public Iterator<Integer> iterator() {
		return new Iterator<Integer>() {
			Node p = head;
			// 是否有下一个元素
			@Override
			public boolean hasNext() { 
				return p != null;
			}
			// 返回当前元素,指向下一个元素
			@Override
			public Integer next() { 
				int value = p.value;
				p = p.next;
				return value;
			}
		};
	}
}

测试用这个

Iterator<Integer> iterator = singlyLinkedList.iterator();
		for (Integer integer:singlyLinkedList){
			System.out.println(integer);
		}

④根据索引查找get(i) 0,1,2,3...,先查找这个索引的节点。没有找到返回null,找到的话返回当前节点

	public Node findNode(int index) {
		Node p = head;
		int i = 0;
		while (p != null) {
			// 找到了
			if (index == i) {
				return p;
			}
			i++;
			p = p.next;//指向下一个节点
		}
		// 没找到
		return null;
	}

如果为null,说明此时不合法

	public int get(int index){
		Node node = findNode(index);
		if (node == null){
			throw new IllegalArgumentException(
					String.format("inndex[%d]不合法%n",index)
			);
		}
		return node.value;
	}

⑤插入到索引位置,先定义辅助节点p指向索引的前一个地址,先让新节点的地址指向p的地址,再让p节点指向新节点的地址。如果p为空,插入失败。如果索引为0,那么调用头部添加的方法

	/**
	 * 4.insert(int index)
	 * 根据索引插入,插在索引的位置,所以找索引前面的节点
	 */
	public void insert(int index,int value){
		if (index == 0){
			// 插入头位置
			addFirst(value);
			System.out.println("插入成功");
			return;
		}

		Node p = findNode(index-1); // 找到索引的前一个节点
		if (p == null){
			// 链表为空,或者索引超出了范围
			System.out.println("插入失败");
			return;
		}
		// 找到索引的前一个节点
		Node newNode = new Node(value,p.next);
		p.next = newNode;
		System.out.println("插入成功");
	}

⑥:按照索引删除节点,先实现删除头结点,让head指向head.next

	public void removeFirst(){
		if (head == null){
			System.out.println("链表为空,删除失败");
			return;
		}
		head = head.next; //
	}

 // 删除节点

	/**
	 * 删除节点:按照索引
	 */
	public void removeIndex(int index){
		if (index == 0){
			// 删除头结点
			removeFirst();
			return;
		}
		Node prev= findNode(index - 1);
		// 如果为空
		if (prev == null){
			// 链表为空或者超过了索引范围
			System.out.println("删除失败");
			return;
		}
		// 此时node是删除索引的前一个节点
        Node removed = prev.next;
        if (removed == null ){
            System.out.println("删除失败");
        }
		prev.next=removed.next;// 索引的前一个节点,指向索引的后一个节点
		System.out.println("删除成功");
	}

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

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

相关文章

Java - Stream流详解

文章目录 前言 大家好,好久不见了,最近由于实训的影响导致拖更了,在更新这一次估计javaSE基本上就算是完结了,还有一些落下的后面也会补上的,下次见面就是数据结构了 尽情期待吧!那么就让我们步入Stream流的学习吧! 一、Stream流是什么&#xff1f; Stream流是Java 8中的一个…

【openEuler 20.03 TLS编译openGauss2.0.0源码】

openEuler 20.03 TLS编译openGauss2.0.0源码 一、安装环境二、安装前准备二、安装步骤 一、安装环境 项目Value操作系统openEuler 20.03 64bit with ARMopenGauss2.0.0openGauss-third_party2.0.0 二、安装前准备 项目Value购买华为ECS鲲鹏 8vCPU32G 100M/s带宽 openEuler 2…

使用CubeMX配置STM32驱动HC-SR04超声波模块

文章目录 前言1 使用STM32CubeMX初始化代码1.1 时钟配置1.2 设置定时器1.3 触发引脚1.4 串口配置 2 代码编写2.1 添加驱动文件2.2 修改main.c 3 实现效果参考 前言 硬件选择 stm32f103c8t6&#xff08;最小板&#xff09;hc-sr04超声波模块 软件环境 stm32cubeIDE 1.12.1 …

【Linux】TCP网络套接字编程+协议定制+序列化和反序列化

悟已往之不谏&#xff0c;知来者之可追。抓不住的就放手&#xff0c;属于你的都在路上…… 文章目录 一、TCP网络套接字编程1.日志等级分类的日志输出API2.单进程版本的服务器客户端通信3.多进程版本和多线程版本4.线程池版本5.守护进程化的线程池服务器6.三次握手和四次挥手的…

python编程——pycharm的安装与使用

作者&#xff1a;Insist-- 个人主页&#xff1a;insist--个人主页 本文专栏&#xff1a;python专栏 专栏介绍&#xff1a;本专栏为免费专栏&#xff0c;并且会持续更新python基础知识&#xff0c;欢迎各位订阅关注。 目录 一、python IDLE的使用 二、pycharm的安装与使用 1、…

十分钟带你看懂——Python测试框架之pytest最全讲

pytest特短 pytest是一个非常成熟的全功能的Python测试框架&#xff0c;主要有以下几个特点&#xff1a; 简单灵活&#xff0c;容易上手 支持参数化 能够支持简单的单元测试和复杂的功能测试&#xff0c;还可以用来做selenium/appnium等自动化测试、接口自动化测试&#xff08…

重磅版本发布|三大关键特性带你认识 Milvus 2.2.9 :JSON、PartitionKey、Dynamic Schema

亮点颇多、精彩程度堪比大版本的 Milvus 2.2.9 来啦&#xff01; 随着 LLM 的持续火爆&#xff0c;众多应用开发者将目光投向了向量数据库领域&#xff0c;而作为开源向量数据库的领先者&#xff0c;Milvus 也充分吸收了大量来自社区、用户、AI 从业者的建议&#xff0c;把重心…

非常简单就能理解的 链表带环问题 你也能轻松学会!

文章目录 判断链表是否带环若链表带环找出环的入口其他高频的面试问题 判断链表是否带环 题目描述&#xff1a; 给定一个链表&#xff0c;判断链表中是否有环。 思路&#xff1a; 可以明确的是&#xff1a;若一个链表带环&#xff0c;那么用指针一直顺着链表遍历&#xff0c…

《嵌入式系统》知识总结10:使用位带操作操纵GPIO

位操作 汇编层面 外设控制常要针对字中某个位&#xff08;Bit&#xff09;操作 以字节编址的存储器地址空间中&#xff0c;需要3步骤&#xff08;读出-修改-写回&#xff09; 1.&#xff08;从外设&#xff09;读取包含该位的字节数据 2. 设置该位为0或1、同时屏蔽其他位&am…

微信小程序 <view></view>容器嵌套,wxss样式修改内部内部样式不产生效果

网上关于”微信小程序讲的知识很少“&#xff0c;微信开发文档对于新手不是很友好&#xff0c;但是建议一定要学会看文档。 问题如下&#xff1a; 我写了好几个<view></view> 容器嵌套&#xff0c;我在对内部容器包括的内容做修改时&#xff0c;不产生效果&#…

apache RocketMQ远程代码执行(CVE-2023-33246)

RocketMQ是阿里巴巴在2012年开发的分布式消息中间件&#xff0c;专为万亿级超大规模的消息处理而设计&#xff0c;具有高吞吐量、低延迟、海量堆积、顺序收发等特点。它是阿里巴巴双十一购物狂欢节和众多大规模互联网业务场景的必备基础设施。 RocketMQ的NameServer、Broker、…

【计算机网络之HTTP篇】Cookie与Session的区别

目录 Cookie 原理 缺点 Session 原理 区别 Cookie cookie是浏览器在本地存储数据的一种机制。 原理 当浏览器向服务器第一次发送请求时&#xff0c;服务器会向浏览器返回一个Cookie&#xff0c;此时 cookie记录着浏览器访问服务器的用户登录状态。 后续浏览器再次访问服…

[深度学习入门案例1]基于Keras的手写数字图像识别

文章目录 一、工具与环境 二、深度学习环境的搭建 1.安装Anaconda 2.创建虚拟环境 第1步&#xff1a;打开Anaconda的命令窗口&#xff0c;即Anaconda Prompt 第2步&#xff1a;使用命令创建指定版本的python环境&#xff08;这里以py36命令环境名称举例&#xff09; 3.切换…

深度解析MethodHandle方法句柄之findspecial方法的原理

网上看过太多关于MethodHandle方法句柄的文章&#xff0c;但是基本上没有人能把其中的findspecial方法讲清楚&#xff0c;特别是findspecial的第四个参数specialCaller, 相信大家都不明白是干嘛用的&#xff0c;网上给出的水文是很多都是说&#xff1a; 执行到specialCaller的父…

kafka二

练一练 需求&#xff1a;写一个生产者&#xff0c;不断的去生产用户行为数据&#xff0c;写入到kafka的一个topic中 生产的数据格式&#xff1a; 造数据 {"guid":1,"eventId":"pageview","timestamp":1637868346789} isNew 1 {&quo…

面了一个32岁的程序员,只因这一点,一眼看穿是培训班出来的,简历都是假的.....

首先&#xff0c;我说一句&#xff1a;培训出来的&#xff0c;优秀学员大有人在&#xff0c;我不希望因为带着培训的标签而无法达到用人单位和候选人的双向匹配&#xff0c;是非常遗憾的事情。 最近&#xff0c;在网上看到这样一个留言&#xff0c;引发了程序员这个圈子不少的…

Kafka安装及架构

kafka的特点 高吞吐量、低延迟&#xff1a;kafka每秒可以处理几十万条消息&#xff0c;它的延迟最低只有几毫秒&#xff0c;每个topic可以分多个partition, 由多个consumer group 对partition进行consume操作。可扩展性&#xff1a;kafka集群支持热扩展持久性、可靠性&#xf…

机智云的离线语音识别模组,让家电变得更加智能和便捷

随着人们对智能化生活的需求不断增加&#xff0c;离线语音模组越来越受到欢迎。它可以为家庭、工作和娱乐提供更加智能和便捷的服务&#xff0c;例如通过语音指令控制家居设备、查询天气信息、播放音乐等。 “小智同学&#xff0c;打开灯光” “调到最亮” “正转一档” 人工智…

Golden Gate (GGX) ZK 预编译: 彻底改变游戏玩法,成本降低千倍

Golden Gate (GGX) 作为一种新型跨链基础设施协议&#xff0c;解决了困扰 Web3.0 Layer1 和 Layer2 的跨链通信和流动性转换难题。 其解决方案主要涉及两个核心: 1) 与协议无关的通信&#xff0c;可以实现主流标准消息的传递&#xff0c;包括 IBC、XCMP 和 LayerZero 等标准。 …

2023 华为 Datacom-HCIE 真题题库 10/12--含解析

单项选择题 1.[试题编号&#xff1a;190585] &#xff08;单选题&#xff09;华为SD-WAN解决方案中&#xff0c;当CPE位 于NAT设备后的私网时&#xff0c;特别是两个站点的CPE同时位于NAT设备后的私网时&#xff0c;CPE之 间需要使用NAT穿越技术。华为SD-WAN解决方案中使用以下…