数据结构之单链表java实现

news2024/11/24 6:57:53

基本概念

链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中指针链接次序实现的。和数组相比较,链表不需要指定大小,也不需要连续的地址。
单链表的基本设计思维是,利用结构体的设置,额外开辟一个空间去做指针,指向下一个结点。
在这里插入图片描述
其中,DATA是需要存储的数据元素,可以为任何数据格式,可以是数组,可以是int,还可以是结构体。
NEXT作为一个空指针,其代表了一个可以指向的区域,通常是用来指向下一个结点,链表尾部NEXT指向NULL(空),因为尾部没有任何可以指向的空间了。

创建结点

private static class Node<E> {
    private E item; 
    private Node<E> next;
    Node(E element,Node<E> next){
        item = element;
        this.next = next;
    }
}
创建接口

```java
public interface BaseTab<T> {
    /**
     * 空置链表
     */
    public void clear();
    /**
     * 判断链表是否为空
     * @return true 为空
     */
    public boolean isEmpty();

    //获取链表中的元素个数
    public int length();

    //获取并返回线性表中的第i个元素
    public T get(int i);

    //添加一个元素
    public void insert(T t);

    //向第i个元素之前插入一个元素
    public void insert(int i,T t);

    //删除并返回第i个元素
    public T remove(int i);
    //返回指定元素的序号,若不存在返回-1
    public int indexOf(T t);
}

实现全部功能

public class SingleLinkedList<E> implements BaseTab<E>{
    private Node<E> mHeader; //链表头部结点,头部结点不存储数据,只存储next
    private int size = 0; //记录链表长度

    public SingleLinkedList(){
    }

    @Override
    public void clear() {
        mHeader.next = null;
        size = 0;
    }

    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    @Override
    public int length() {
        return size;
    }

    @Override
    public E get(int index) {
        Node<E> node = mHeader;//从Header开始循环
        for(int i = 0;i < index;i++){
            node = node.next;
        }
        return node.item;
    }

    @Override
    public void insert(E data) {
        if(mHeader == null){
            mHeader = new Node<E>(data,null);
            size++;
            return;
        }
        Node<E> lastNode = mHeader;
        while (lastNode.next != null){ //通过循环找到链表的尾部
            lastNode = lastNode.next;
        }
        lastNode.next = new Node<>(data,null);
        size++;
    }

    @Override
    public void insert(int index, E data) {
        //创建新的结点用来存放数据
        if(mHeader == null){
            mHeader = new Node<E>(data,null);
            size++;
            return;
        }

        Node<E> newNode = new Node<E>(data,null);
        Node<E> preNode = mHeader;
        for(int i = 0;i <= index -1;i++){ //循环找到index位置的前一个结点
            preNode = mHeader.next;
        }
        newNode.next = preNode.next;
        preNode.next = newNode;
        size++;
    }

    /**
     * 打印出链表所有数据
     */
    public void printAll(){
        Node<E> node = mHeader;
        while (node.next != null){
            System.out.println(node.item);
            node = node.next;
        }
        System.out.println(node.item);
    }

    @Override
    public E remove(int index) {
        //1.找到指定位置的前一个Node
        Node<E> preNode = mHeader;
        for(int i = 0; i < index -1;i++){
            preNode = preNode.next;
        }
        //需要被删除的Node
        Node<E> removeNode = preNode.next;
        preNode.next = removeNode.next;
        size--;
        return removeNode.item;
    }

    @Override
    public int indexOf(E data) {
        Node node = mHeader;
        for(int i = 0;i < size;i++){
            if(node.item.equals(data)){
               return i;
            } else {
                node = node.next;
            }
        }
        return -1;
    }

    private static class Node<E> {
        private E item;
        private Node<E> next;
        Node(E element,Node<E> next){
            item = element;
            this.next = next;
        }
    }
}

反转链表

链表反转是一道比较常见的面试题
eg:链表中输入0,1,2,3,4,输出 4,3,2,1,0
在这里插入图片描述
实现一个结点:

public class Node<T> {
    T data; //数据
    Node<T> next; //指向下一个结点
    public Node(T value){
        data = value;
    }
}

从结点的结构上面来说,我们需要修改的是next,将next由指向下一个改成指向上一个。
链表全部反转,那就需要从尾部或者头部开始,从尾部开始的话,使用递归的思想。

    public static <T> Node<T> reversalLink(Node<T> head){
        //主要是通过head.next == null 找出最后面的一个结点
        if(head == null || head.next == null) return head;
        //通过递归找到最后的一个作为Head
        //递归执行顺序是4,3,2,1,0
        Node<T> revHead = reversalLink(head.next);
        //调整指针
        //eg:执行到3时需要做以下操作
        //1.4的next应该是3,当head = 3时, 目前head.next = 4 4.next = head,就将4的下一个结点指向3
        head.next.next = head;
        //执行上上一步后,3->4,4->3,现在需要将3->4断开
        head.next = null;
        return revHead;
    }

    public static void main(String[] args) {
        Node<Integer> head = new Node<>(0);
        Node<Integer> node1 = new Node<>(1);
        Node<Integer> node2 = new Node<>(2);
        Node<Integer> node3 = new Node<>(3);
        Node<Integer> node4 = new Node<>(4);
        head.next = node1;
        node1.next = node2;
        node2.next = node3;
        node3.next = node4;
        //反转前
        Node<Integer> node = head;
        while (node != null){
            System.out.print(node.data + " ");
            node = node.next;
        }
        System.out.println("");
        System.out.println("-----反转后-------");
        Node<Integer> revHead = reversalLink(head);
        while (revHead != null){
            System.out.print(revHead.data + " ");
            revHead = revHead.next;
        }
    }

从链表头部开始
在这里插入图片描述
思路就如上面所画,从header开始,拆成两个链表

    public static <T> Node<T> reversalLink1(Node<T> head){
        Node<T> preNode = null;
        Node<T> curNode = head;
        while (curNode != null){
            Node<T> nextNode = curNode.next;

            curNode.next = preNode;
            preNode = curNode;
            curNode = nextNode;
        }
        return preNode;
    }

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

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

相关文章

平衡二叉树(AVL树)C++

目录 AVL树的概念 AVL树的节点结构 AVL树的插入 更新平衡节点 代码实现 AVL树的旋转 左单旋 右单旋 左右双旋 右左双旋 AVL树的删除 AVL树的查找 AVL树的高度 AVL树的判定 AVL树的遍历 AVL树的概念 二叉排序&#xff08;搜索&#xff09;树&#xff0c;虽然可以…

葡萄叶病害识别(图像连续识别和视频识别,Python代码,pyTorch框架)

葡萄叶病害识别&#xff08;图像连续识别和视频识别&#xff0c;Python代码&#xff0c;pyTorch框架&#xff09;_哔哩哔哩_bilibili 葡萄数据集 第一个文件夹为 Grape Black Measles&#xff08;葡萄黑麻疹&#xff09;病害&#xff08;3783张&#xff09; Grape Black rot葡…

108页石油石化5G智慧炼化厂整体方案PPT

导读&#xff1a;原文《108页石油石化5G智慧炼化厂整体方案PPT》&#xff08;获取来源见文尾&#xff09;&#xff0c;本文精选其中精华及架构部分&#xff0c;逻辑清晰、内容完整&#xff0c;为快速形成售前方案提供参考。以下是部分内容&#xff0c; P P T 喜欢文章&#xf…

【BUG事务内消息发送】事务内消息发送,事务还未结束,消息发送已被消费,查无数据怎么解决?

问题描述 在一个事务内完成插入操作&#xff0c;通过MQ异步通知其他微服务进行事件处理。 由于是在事务内发送&#xff0c;其他服务消费消息&#xff0c;查询数据时还不存在如何解决呢&#xff1f; 解决方案 通过spring-tx包的TransactionSynchronizationManager事务管理器解…

管理与领导-58]:IT基层管理者 - 扩展技能 - 1 - 时间管理 -5- 持续改进— 时间管理的好习惯

前言&#xff1a; 对于大多数管理者而言&#xff0c;提高效能并不能一步到位&#xff0c;需要不断的实践、总结、持续的改进和优化&#xff0c;最终达到较高的效能&#xff0c;持续学习、持续改进是管理者一项终身精进的能力&#xff01;&#xff01;&#xff01;养成时刻进行…

程序员赚钱的六种方式:技术实力和市场分析能力是关键

随着互联网的普及和发展&#xff0c;越来越多的人开始在网上寻找商机&#xff0c;其中程序员作为一个高技能的群体&#xff0c;可以利用自身的编程技术在网上获得收益。以下是一些程序员可以利用自己的编程技术在网上赚钱的途径&#xff1a; 开发软件&#xff1a;程序员可以利…

Spring Boot(Vue3+ElementPlus+Axios+MyBatisPlus+Spring Boot 前后端分离)【五】

&#x1f600;前言 本篇博文是关于Spring Boot(Vue3ElementPlusAxiosMyBatisPlusSpring Boot 前后端分离)【五】&#xff0c;希望你能够喜欢 &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文章…

本地组策略编辑器找不到怎么解决?| 解决windows home 版本隐藏本地组策略编辑器的问题 | 简单的介绍本地组策略编辑器

一般的 Windows 非家庭系统中&#xff0c;本地组策略编辑器不会被隐藏&#xff0c;但在某些特定情况下&#xff0c;可能会受到限制或不可用。如果你无法访问本地组策略编辑器&#xff0c;并且认为应该可以访问&#xff0c;请确保你拥有管理员权限&#xff0c;并检查是否有任何系…

golang-bufio 缓冲读

缓冲 IO 计算机中我们常听到这样的两种程序优化方式&#xff1a; 以时间换空间以空间换时间 今天要来看的缓冲IO就是典型的以空间换时间&#xff0c;它的基本原理见上图。简单的解释就是&#xff1a;程序不再直接去读取底层的数据源&#xff0c;而是通过一个缓冲区来进行读取…

SPI3+DMA外设驱动-TFTLCD初始化

前言 &#xff08;1&#xff09;本系列是基于STM32的项目笔记&#xff0c;内容涵盖了STM32各种外设的使用&#xff0c;由浅入深。 &#xff08;2&#xff09;小编使用的单片机是STM32F105RCT6&#xff0c;项目笔记基于小编的实际项目&#xff0c;但是博客中的内容适用于各种单片…

算法leetcode|74. 搜索二维矩阵(rust重拳出击)

文章目录 74. 搜索二维矩阵&#xff1a;样例 1&#xff1a;样例 2&#xff1a;提示&#xff1a; 分析&#xff1a;题解&#xff1a;rust&#xff1a;go&#xff1a;c&#xff1a;python&#xff1a;java&#xff1a; 74. 搜索二维矩阵&#xff1a; 给你一个满足下述两条属性的…

新手将最简单的springboot部署上tomcat出现的意外问题

现阶段springboot部署到tomcat的文章一抓一大把且都相同,便贴一个地址以展示流程: SpringBoot打war包部署Tomcat(最全)_spring boot war 部署tomcat_聊Java的博客-CSDN博客 那么就说一下我出现的问题: 在完整复现流程且确认代码无误的情况下,部署到tomcat,此时问题出现了:启动…

vue中html引入使用<%= BASE_URL %>变量

首先使用src相对路径引入 注意&#xff1a; js 文件放在public文件下 不要放在assets静态资源文件下 否则 可能会报错 GET http://192.168.0.113:8080/src/assets/js/websockets.js net::ERR_ABORTED 500 (Internal Server Error) 正确使用如下&#xff1a;eg // html中引…

Midjourney学习(二)参数的基础

prompt的组成 prompt 可以由三部分组成&#xff0c; 第一部分是垫图部分&#xff0c;也就是一张网络图片 第二部分是文本描述内容 第三部分则是参数 参数列表 --aspect <value> 或者 --ar <value> 控制画面的比例&#xff0c;横竖比例 --version <value> -…

复数的四则运算(java版)

复数的四则运算&#xff08;java版&#xff09; 目录 复数的四则运算&#xff08;java版&#xff09;介绍复数的四则运算实现思路代码1、封装复数类2、测试复数类3、代码测试结果 介绍 复数&#xff0c;为实数的延伸&#xff0c;它使任一多项式方程都有根。复数当中有个“虚数单…

攻击与防御实战经验分享:分析真实的攻击事件和入侵行为,讨论防御方法和实践经验

章节 1: 前言 作为IT领域的从业者&#xff0c;我们时刻都面临着网络安全的挑战。攻击者不断寻找漏洞&#xff0c;而防御者则需要时刻保持警惕&#xff0c;采取最佳实践来保护系统和数据。在本文中&#xff0c;我们将分享一些真实的攻击事件和入侵行为&#xff0c;并探讨针对这…

JVM 垃圾收集

垃圾收集 分代理论Java 堆的内存分区不同分代收集垃圾收集算法 分代理论 弱分代假说&#xff1a;绝大多数对象都是朝生夕灭&#xff0c;即绝大多数对象都是用完很快需要销毁的。强分代假说&#xff1a;熬过多次垃圾收集过程的对象就越难以消亡&#xff0c;即如果对象经过多次垃…

6. vue-element-admin 二次开发避坑指南

vue-element-admin 二次开发避坑指南 1.1 前言1.1.1 切换标签时未保存页面的操作内容1.1.2 markdown 样式乱码1.1.3 修改默认尺寸1.1.4 当后端服务器宕机情况下页面加载层一直转圈无法停止&#xff0c;只能关闭页面1.1.5 隐藏齿轮 1.1 前言 上一篇博文&#xff0c;我们分享了vu…

HarmonyOS Codelab 优秀样例——购物应用,体验一次开发多端部署魅力

一. 样例介绍 本篇Codelab基于自适应布局和响应式布局&#xff0c;实现购物应用在手机、折叠屏、平板不同屏幕尺寸设备上按不同设计显示。通过三层工程结构组织代码&#xff0c;实现一次开发&#xff0c;多端部署 。 手机运行效果如图所示&#xff1a; 折叠屏运行效果图&#x…

Thymeleaf解析表达式

首先springThymeleaf必过的点 org.springframework.web.servlet.DispatcherServlet#doDispatch那么先跟入handle()方法 然后跟进handleInternal方法 可以看到mav的获取方法&#xff0c;继续跟进invokeHandlerMethod 继续跟进invokeAndHandle 这里判断returnvalue是否有值…