链表的实现

单向循环链表

定义

在计算机科学中,链表是数据元素的线性集合,其每个元素都指向下一个元素,元素存储上并不连续。

图解

 链表内还有一种特殊的节点被称为哨兵(Sentinel)节点,也叫做哑元,它不存储数据,通常用作头尾,用来简化边界判断。

链表的实现

package com.ma.test;import java.util.Iterator;
import java.util.function.Consumer;/*** @author Mtz* @version 1.0* @2023/12/2311:01* @function* @comment*/
// 单向链表
public class SinglyLinkedList implements Iterable<Integer> {  // 整体private Node head = null; // 头指针/*节点类*/private static class Node {int value; // 值Node next; // 下一个节点指针/*** 构造方法,创建一个节点** @param value 值* @param next  下一个节点指针*/public Node(int value, Node next) {this.value = value;this.next = next;}}/*** 在链表头部插入一个值为 value 的节点** @param value 要插入的节点值*/public void addFirst(int value) {if (head == null) {// 链表为空,直接创建新节点作为头节点head = new Node(value, null);} else {// 链表不为空,创建新节点并更新头指针Node newNode = new Node(value, head);head = newNode;}}/*** 遍历链表,对每个节点执行指定的操作** @param consumer 对每个节点执行的操作*/public void loop(Consumer<Integer> consumer) {Node p = head;while (p != null) {consumer.accept(p.value);p = p.next;}}/*** 遍历链表,对每个节点执行指定的操作(使用 for 循环实现)** @param consumer 对每个节点执行的操作*/public void loop2(Consumer<Integer> consumer) {for (Node p = head; p != null; p = p.next) {consumer.accept(p.value);}}/*** 获取链表的迭代器,用于支持增强的 for 循环** @return 迭代器对象*/@Overridepublic Iterator<Integer> iterator() {return new Iterator<Integer>() {Node p = head;@Overridepublic boolean hasNext() {return p != null;}@Overridepublic Integer next() {int v = p.value;p = p.next;return v;}};}/*** 查找链表中的最后一个节点** @return 最后一个节点,如果链表为空则返回 null*/private Node findLast() {Node p = head;while (p != null && p.next != null) {p = p.next;}return p;}/*** 在链表尾部插入一个值为 value 的节点** @param value 要插入的节点值*/public void addLast(int value) {Node last = findLast();if (last == null) {// 链表为空,直接在头部插入addFirst(value);} else {// 在最后一个节点后插入新节点last.next = new Node(value, null);}}/*** 根据索引查找节点** @param index 索引值* @return 索引位置的节点,如果索引非法则返回 null*/private Node findNode(int index) {int i = 0;for (Node p = head; p != null; p = p.next, i++) {if (i == index) {return p;}}return null;}/*** 获取指定索引位置的节点值** @param index 索引值* @return 索引位置的节点值,如果索引非法则抛出 IllegalArgumentException*/public int get(int index) {Node node = findNode(index);if (node == null) {Illega(index);}return node.value;}// 向索引位置插入一个值为 value 的节点public void insert(int index, int value) {// 向头部插入值if (index == 0) {addFirst(value);return;}// 找到索引位置的上一个节点Node prev = findNode(index - 1);if (prev == null) {// 如果上一个节点为 null,说明索引非法Illega(index);}// 在上一个节点后插入新节点prev.next = new Node(value, prev.next);}// 删除链表中的第一个元素public void removeFirst() {if (head == null) {// 如果链表为空,抛出索引非法异常Illega(0);}// 更新头指针,跳过第一个节点head = head.next;}// 根据索引位置删除节点public void remove(int index) {// 删除头节点的情况if (index == 0) {removeFirst();return;}// 找到索引位置的上一个节点Node prev = findNode(index - 1);if (prev == null) {// 如果上一个节点为 null,说明索引非法Illega(index);}// 被删除的节点Node removed = prev.next;if (removed == null) {// 如果被删除的节点为 null,说明索引非法Illega(index);}// 更新上一个节点的 next 指针,跳过被删除的节点prev.next = removed.next;}// 抛出 IllegalArgumentException 异常,表示索引非法private void Illega(int index) {throw new IllegalArgumentException(String.format("index [%d] 不合法%n", index));}}
测试
static void t2() {SinglyLinkedList singlyLinkedList = new SinglyLinkedList();singlyLinkedList.addLast(1);singlyLinkedList.addLast(2);singlyLinkedList.addLast(3);singlyLinkedList.addLast(4);singlyLinkedList.remove(2);for (Integer value : singlyLinkedList) {System.out.println(value);}}
思路

这是一个单向链表(Singly Linked List)的简单实现。单向链表是一种数据结构,其中的元素按顺序存储,并通过每个元素中的指针链接到下一个元素,形成一个链条。在这个实现中,链表的基本结构如下:

  1. 节点类 Node

    • Node 类表示链表中的每个节点,包含两个字段:value 存储节点的值,next 存储指向下一个节点的引用。
  2. 链表类 SinglyLinkedList

    • SinglyLinkedList 类表示整个单向链表,包含一个头指针 head,指向链表的第一个节点。
    • 提供了基本的链表操作方法,如在头部插入节点、遍历链表、在尾部插入节点、获取指定索引位置的节点值、在指定索引位置插入节点、删除指定索引位置的节点等。
    • 实现了 Iterable 接口,使得链表对象可以通过增强的 for 循环遍历。
  3. 思路概述:

    • 在链表头部插入节点(addFirst 方法):如果链表为空,直接创建一个新节点作为头节点;如果链表不为空,创建一个新节点,将其指向原头节点,并更新头指针。
    • 遍历链表(looploop2 方法):通过循环遍历链表中的每个节点,对每个节点执行指定的操作。
    • 在链表尾部插入节点(addLast 方法):找到链表中的最后一个节点,然后在其后插入新节点;如果链表为空,直接在头部插入新节点。
    • 获取指定索引位置的节点值(get 方法):通过循环找到指定索引位置的节点,并返回其值。
    • 在指定索引位置插入节点(insert 方法):找到指定索引位置的上一个节点,然后在其后插入新节点;如果是在头部插入,直接调用头部插入的方法。
    • 删除指定索引位置的节点(removeFirstremove 方法):删除头节点或指定索引位置的节点,更新相邻节点的指针。

这个实现是链表数据结构的基础,可以用于在不需要连续内存分配的情况下动态管理数据。链表的特点是插入和删除操作相对高效,但随机访问某个位置的元素相对较慢。

双向循环链表

图解

代码

package com.ma.lianbiao;import java.util.Iterator;/*** @author Mtz* @version 1.0* @2023/12/2517:27* @function* @comment*/// 双向循环列表
public class DoublyLinkedListSentinel implements Iterable<Integer> {static class Node {Node prev; // 上一个节点指针int value; // 值Node next; // 下一个节点指针public Node(Node prev, int value, Node next) {this.prev = prev;this.value = value;this.next = next;}}private Node head;private Node tail;public DoublyLinkedListSentinel() {head = new Node(null, 666, null);tail = new Node(null, 888, null);head.next = tail;tail.prev = head;}private Node findNode(int index) {int i = -1;for (Node p = head; p != tail; p = p.next, i++) {if (i == index) {return p;}}return null;}public void remove(int index) {Node prev = findNode(index - 1);if (prev == null) {Illega(index);}Node removed = prev.next;if (removed == tail) {Illega(index);}Node next = removed.next;prev.next = next;next.prev = prev;}void removeFirst() {remove(0);}public void addFirst(int value) {insert(0, value);}public void insert(int index, int value) {Node prev = findNode(index - 1);if (prev == null) {Illega(index);}Node next = prev.next;Node inserted = new Node(prev, value, next);prev.next = inserted;next.prev = inserted;}private void addLast(int value) {Node last = tail.prev;Node added = new Node(last, value, tail);last.next = added;tail.prev = added;}public void First(int value) {}public void removeLast() {Node removed = tail.prev;if (removed == head) {Illega(0);}Node prev = removed.prev;prev.next = tail;tail.prev = prev;}// 抛出 IllegalArgumentException 异常,表示索引非法private void Illega(int index) {throw new IllegalArgumentException(String.format("index [%d] 不合法%n", index));}@Overridepublic Iterator<Integer> iterator() {return new Iterator<Integer>() {private Node current = head.next; @Overridepublic boolean hasNext() {return current != tail;}@Overridepublic Integer next() {if (!hasNext()) {throw new IllegalStateException("No more elements");}int value = current.value;current = current.next;return value;}};}
}

环形链表

定义

双向环形链表带哨兵,这是哨兵即作为头,也作为尾。

图解

代码

package com.ma.lianbiao;import java.util.Iterator;/*** @author Mtz* @version 1.0* @2023/12/2520:37* @function* @comment*/
public class DoublyLinkedListSentinelx implements Iterable<Integer> {private static class Node {Node prev;int value;Node next;public Node(Node prev, int value, Node next) {this.prev = prev;this.value = value;this.next = next;}}private Node sentinel = new Node(null, -1, null);@Overridepublic Iterator<Integer> iterator() {return new Iterator<Integer>() {Node p = sentinel.next;@Overridepublic boolean hasNext() {return p != sentinel;}@Overridepublic Integer next() {int value = p.value;p = p.next;return value;}};}public void removeFirst() {Node removed = sentinel.next;if (removed == sentinel) {throw new IllegalArgumentException("非法");}Node a = sentinel;Node b = removed.next;a.next = b;b.prev = a;}public void removeLast() {Node removed = sentinel.prev;if (removed == sentinel) {throw new IllegalArgumentException("非法");}Node a = removed.prev;Node b = sentinel;a.next = b;b.prev = a;}public void addLast(int value) {Node a = sentinel.prev;Node b = sentinel;Node added = new Node(a, value, b);a.next = added;b.prev = added;}public DoublyLinkedListSentinelx() {sentinel.prev = sentinel;sentinel.next = sentinel;}public void addFirst(int value) {Node a = sentinel;Node b = sentinel.next;Node added = new Node(a, value, b);a.next = added;b.prev = added;}private Node findByValue(int value) {Node p = sentinel.next;while (p != sentinel) {if (p.value == value) {return p;}p = p.next;}return null;}public void removeByValue(int value) {Node removed = findByValue(value);if (removed == null) {return;}Node a = removed.prev;Node b = removed.next;a.next = b;b.prev = a;}private void Illega(int index) {throw new IllegalArgumentException(String.format("index [%d] 不合法%n", index));}
}

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

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

相关文章

kubelet源码学习(二):kubelet创建Pod流程

本文基于Kubernetes v1.22.4版本进行源码学习 4、kubelet创建Pod流程 syncLoop()的主要逻辑是在syncLoopIteration()方法中实现&#xff0c;Pod创建相关代码只需要看处理configCh部分的代码 // pkg/kubelet/kubelet.go // 该方法会监听多个channel,当发现任何一个channel有数…

ssh工具 从ssh服务器下载文件夹

此文分享一个python脚本,用于快速的定位、选择ssh服务器上的文件夹,并将其下载到本地指定的位置。 效果演示 🔥完整演示效果 👇 第一步,显然,我们需要选择功能 👇 第二步,确认我们需要从哪个ssh服务器上下载文档 👇 第三步,定位、选择、确认需要下载的文件夹…

c 语言学习:输出阶乘的算式

c 语言学习&#xff1a;输出阶乘的算式 代码 #include "stdio.h"int fact(int num){if (num < 1){printf("1 ");return 1;} else {printf("%d x ",num);return num * fact(num-1);} }int main(){int num 10; // printf("plz inpu…

基于SSM在线协同过滤汽车推荐销售系统

SSM毕设分享 基于SSM在线协同过滤汽车推荐销售系统 1 项目简介 Hi&#xff0c;各位同学好&#xff0c;这里是郑师兄&#xff01; 今天向大家分享一个毕业设计项目作品【】 师兄根据实现的难度和等级对项目进行评分(最低0分&#xff0c;满分5分) 难度系数&#xff1a;3分 工作…

simulink代码生成(四)——SCI发送模块(串口通信)

C2000中的SCI模块分为两种&#xff0c;一种是接收模块&#xff0c;一种是发送模块&#xff1b; 1 发送模块 发送模块如下图所示&#xff1a; SCI传输块使用指定的SCI硬件模块传输标量或矢量数据。采样率和数据类型是与输入端口一致&#xff1b; 注意&#xff1a;一个模型只能…

商城首页卡爆了!!!

前言 最近我们的商城系统出现了一个线上问题&#xff0c;用户访问商城首页的时候要差不多20秒&#xff0c;才返回数据&#xff0c;可以说卡爆了。 到底怎么回事呢&#xff1f; 1.案发现场 上周四晚上&#xff0c;我们有一个正常的迭代版本按照预期的时候上线。 本次迭代&a…

【K8S基础】-k8s的核心概念控制器和调度器

Kubernetes是一个开源的容器编排平台&#xff0c;旨在简化和自动化容器化应用程序的部署、扩展和管理。它提供了一个强大的基础设施来管理容器化应用程序的生命周期&#xff0c;并确保它们在整个集群中高效运行。 Kubernetes的核心概念包括集群、节点、Pod、控制器、调度器等。…

vue3使用mixins

<template><div>{{ num }}___{{ fav }}</div><button click"favBtn">改变值</button> </template><script setup lang"ts"> import mixin from "../mixins/mixin"; let { num, fav, favBtn } mixin(…

如何使用PatchaPalooza对微软每月的安全更新进行全面深入的分析

关于PatchaPalooza PatchaPalooza是一款针对微软每月安全更新的强大分析工具&#xff0c;广大研究人员可以直接使用该工具来对微软每月定期推送的安全更新代码进行详细、全面且深入的安全分析。 PatchaPalooza使用了微软MSRC CVRF API的强大功能来获取、存储和分析安全更新数…

ip addr和ifconfig

ip addr可以显示更多信息&#xff0c;包括为启动的网络驱动如wlan&#xff0c;而ifocnfig只显示在线的驱动。若wlan是down的&#xff0c;则ip addr会显示信息&#xff0c;ifconfig不会显示信息。 ip addr: ifconfig:

双端队列、优先级队列、阻塞队列

双端队列、优先级队列、阻塞队列 文章目录 双端队列、优先级队列、阻塞队列1 双端队列1.1 概述1.2 应用实例1.2.1 双端链表实现1.2.2 数组实现1.2.3 测试代码 1.3 课后作业- LeeTCode103 2. 优先级队列2.1 概述2.2 基于无序数组实现2.3 基于有序数组实现2.3 堆实现优先级队列2.…

Python 爬虫之下载歌曲(一)

爬取某酷音乐平台歌曲 文章目录 爬取某酷音乐平台歌曲前言一、基本流程二、代码编写三、效果展示总结 前言 老是爬视频有点乏味&#xff0c;换个口味。今天出个爬歌曲的。后续由易到难也出个相关的系列教程。 一、基本流程 打开某酷网站播放某个歌曲&#xff0c;复制这个歌曲…