数据结构之单链表java实现

基本概念

链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中指针链接次序实现的。和数组相比较,链表不需要指定大小,也不需要连续的地址。
单链表的基本设计思维是,利用结构体的设置,额外开辟一个空间去做指针,指向下一个结点。
在这里插入图片描述
其中,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;
    }

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

爬虫selenium获取元素定位方法总结(动态获取元素)

目录 元素 查看元素信息 元素定位 通过元素id定位 通过元素name定位 通过xpath表达式定位 绝对路径 相对路径 通过完整超链接定位 通过部分链接定位 通过标签定位 通过类名进行定位 通过css选择器进行定位 id选择器 class选择器 标签选择器 属性选择器 定位带…

CPU、MCU、MPU、SOC、SOCPC、概念解释之在嵌入式领域常听到的名词含义

CPU、MCU、MPU、SOC等几个在嵌入式领域学习过程中会涉及到的几个名词。我们来学习一下&#xff0c;资料从网上搜集的&#xff0c;有错的地方可以指出。。。 CPU、MCU、MPU、SOC、SOCPC、 1. CPU2. MPU3.MCUMPU和MCU的区别&#xff1a;4.SOC5. SoPC 1. CPU CPU&#xff0c;即中…

HBase--技术文档--基本概念--《快速扫盲》

官网 Apache HBase – Apache HBase™ Home 阿里云hbase 云数据库HBase_大数据存储_订单风控_数据库-阿里云 云数据库 HBase-阿里云帮助中心 基本概念 HBase是一种分布式、可扩展、支持海量数据存储的NoSQL数据库。它基于Hadoop&#xff0c;采用列式存储方式&#xff0c;可…

数据库第十七课-------ETL任务调度系统的安装和使用

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ​&#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…

如何基于自己训练的Yolov5权重,结合DeepSort实现目标跟踪

网上有很多相关不错的操作demo&#xff0c;但自己在训练过程仍然遇到不少疑惑。因此&#xff0c;我这总结一下操作过程中所解决的问题。 1、deepsort的训练集是否必须基于逐帧视频&#xff1f; 我经过尝试&#xff0c;发现非连续性的图像仍可以作为训练集。一个实例&#xff0…

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

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

Qt应用开发(基础篇)——对话框窗口 QDialog

一、前言 QDialog类继承于QWidget&#xff0c;是Qt基于对话框窗口(消息窗口QMessageBox、颜色选择窗口QColorDialog、文件选择窗口QFileDialog等)的基类。 QDialog窗口是顶级的窗口&#xff0c;一般情况下&#xff0c;用来当做用户短期任务(确认、输入、选择)或者和用户交流(提…

文件上传漏洞之条件竞争

这里拿upload-labs的第18关做演示 首先先看代码 $is_upload false; $msg null;if(isset($_POST[submit])){$ext_arr array(jpg,png,gif);$file_name $_FILES[upload_file][name];$temp_file $_FILES[upload_file][tmp_name];$file_ext substr($file_name,strrpos($file_…

MyBatis-Plus框架技术总结

MybatisPlus 1、概述 MybatisPlus是一款Mybatis增强工具&#xff0c;用于简化开发&#xff0c;提高效率。 它在 MyBatis 的基础上只做增强不做改变&#xff0c;为简化开发、提高效率而生。 ​ 官网&#xff1a; https://mp.baomidou.com/ 2、快速入门 2.0、准备工作 ①准…

怎样快速选择正确的可视化图表?

数据可视化的图表类型十分丰富&#xff0c;好的图表可以有效、清晰地呈现数据的信息。对于用户而言&#xff0c;选择正确的图表是十分关键的&#xff0c;不仅可以达到“一图胜千言”的效果&#xff0c;而且会直接影响分析的结果。 用户选择正确的数据可视化图表前&#xff0c;…

嵌入式学习笔记——ARM的编程模式和7种工作模式

ARM提供的指令集 ARM态-ARM指令集&#xff08;32-bit&#xff09; Thumb态-Thumb指令集&#xff08;16-bit&#xff09; Thumb2态-Thumb2指令集&#xff08;16 & 32 bit&#xff09; Thumb指令集是对ARM指令集的一个子集重新编码得到的&#xff0c;指令长度为16位。通常在…

2023年四款热门护眼台灯推荐/测评/排行/选购指南-内含明基/书客/飞利浦

灯具可以说是我们日常生活中使用很频繁的工具了&#xff0c;我们每天都离不开它给我们带来的光亮。当然&#xff0c;现在灯具也有很多种类可以挑选&#xff0c;今天主要带来的就是护眼台灯的选购问题&#xff01; 护眼台灯品牌那么多&#xff0c;怎么选到适合自己的台灯&#x…

Linux下的系统编程——vim/gcc编辑(二)

前言&#xff1a; 在Linux操作系统之中有很多使用的工具&#xff0c;我们可以用vim来进行程序的编写&#xff0c;然后用gcc来生成可执行文件&#xff0c;最终运行程序。下面就让我们一起了解一下vim和gcc吧 目录 一、vim编辑 1.vim的三种工作模式 2.基本操作之跳转字符 &a…

always for

怎么改写 reg test[3:0]; always (posedge clk) begin//int i0;if(rst) begintest[0] <0;test[1] <0;test[2] <0;test[3] <0;endelse beginif(test[0]0) beginif(wea )test[0] < 1;endelse if(test[1]0) begin //优先级if(wea )test[1] < 1;endelse if(te…

【android12-linux-5.1】【ST芯片】HAL移植后没调起来

ST传感器芯片HAL按官方文档移植后&#xff0c;测试一直掉不起来&#xff0c;加的日志没出来。经过分析&#xff0c;是系统自带了一个HAL&#xff0c;影响的。 按照官方文档&#xff0c;移植HAL后&#xff0c;在/device/<vendor\>/<board\>/device.mk*路径增加PROD…

线性代数的学习和整理12: 矩阵与行列式,计算上的差别对比

目录 1 行列式和矩阵的比较 2 简单总结矩阵与行列式的不同 3 加减乘除的不同 3.1 加法不同 3.2 减法不同 3.3 标量乘法/数乘 3.3.1 标准的数乘对比 3.3.2 数乘的扩展 3.4 乘法 4 初等线性变换的不同 4.1 对矩阵进行线性变换 4.2 对行列式进行线性变换 1 行列式和…

CUDA小白 - NPP(2) -图像处理-算数和逻辑操作

cuda小白 原文链接 NPP GPU架构近些年也有不少的变化&#xff0c;具体的可以参考别的博主的介绍&#xff0c;都比较详细。还有一些cuda中的专有名词的含义&#xff0c;可以参考《详解CUDA的Context、Stream、Warp、SM、SP、Kernel、Block、Grid》 常见的NppStatus&#xff0c…

docker部署前端项目保姆级教程

本地启动docker&#xff08;有不会启动的吗&#xff1f;下载docker&#xff08;小海豚&#xff09;双击起来就行&#xff09; 准备阿里云账号&#xff08;免费&#xff09; 没有就去注册一个&#xff0c;记住密码后面要用到 官网地址&#xff1a;阿里云登录 - 欢迎登录阿里云…

字符设备驱动(内核态用户态内存交互)

前言 内核驱动&#xff1a;运行在内核态的动态模块&#xff0c;遵循内核模块框架接口&#xff0c;更倾向于插件。 应用程序&#xff1a;运行在用户态的进程。 应用程序与内核驱动交互通过既定接口&#xff0c;内核态和用户态访问依然遵循内核既定接口。 环境搭建 系统&#…

华为云Stack的学习(三)

四、华为云Stack公共组件 1.华为云Stack公共负载均衡方案介绍 1.1 LVS原理 LVS是四层负载均衡&#xff0c;建立在OSI模型的传输层之上&#xff0c;所以效率非常高。 LVS有两种转发模式&#xff1a; NAT模式的转发主要通过修改IP地址&#xff08;位于OSI模型的第三层网络层&…