【数据结构与算法】链表的实现以及一些基本算法

news2024/12/23 20:33:32

目录

单选链表的基本实现

有序列表的合并(双指针法)

链表的反转 

链表实现两数之和 

判定链表是否有环


单选链表的基本实现

public class LinkedList1 {
    //头节点
    Node first;
    //尾节点
    Node last;
    //大小
    int size = 0;

    //头插法
    public void addFirst(int v) {
        Node newNode = new Node(v);

        Node f = first;

        first = newNode;

        if (f == null) {
            last = newNode;
        } else {
            newNode.next = f;
        }
        size++;
    }

    //尾插法
    public void addLast(int v) {
        Node newNode = new Node(v);

        Node l = last;

        last = newNode;

        if (l == null) {
            first = newNode;
        } else {
            l.next = newNode;
        }
        size++;
    }

    //使用节点尾插
    public void addNode(Node node){
        if (last ==null){
            last=node;
            first=node;
        }else {
            Node l =last;
            l.next=node;
            last=node;
        }

    }


    //链表的遍历
    @Override
    public String toString() {
        StringJoiner sj = new StringJoiner("->");
        for (Node n = first; n != null; n = n.next) {
            sj.add(String.valueOf(n.val));
        }
        return sj.toString();
    }



    public static class Node {
        int val;
        Node next;

        Node(int val) {
            this.val = val;
        }
    }
}

有序列表的合并(双指针法)

//链表的有序合并排序
    public static LinkedList1 merge(LinkedList1 list1, LinkedList1 list2) {
        Node n1 = list1.first, n2 = list2.first;
        LinkedList1 result = new LinkedList1();
        while (n1 != null || n2 != null) {
            if (n1 == null) {
                result.addLast(n2.val);
                n2 = n2.next;
                continue;
            }
            if (n2 == null) {
                result.addLast(n1.val);
                n1 = n1.next;
                continue;
            }

            if (n1.val < n2.val) {
                result.addLast(n1.val);
                n1 = n1.next;
            } else {
                result.addLast(n2.val);
                n2 = n2.next;

            }
        }
        return result;
    }

 测试

LinkedList1 linkedList1 =new LinkedList1();
        linkedList1.addLast(1);
        linkedList1.addLast(4);
        linkedList1.addLast(6);


        LinkedList1 linkedList2 =new LinkedList1();
        linkedList2.addLast(2);
        linkedList2.addLast(3);
        linkedList2.addLast(5);
        linkedList2.addLast(9);

        System.out.println("链表1:"+linkedList1);
        System.out.println("链表2:"+linkedList2);
        //有序链表的合并排序
        System.out.println("链表1与链表2合并:"+LinkedList1.merge(linkedList1, linkedList2));

链表的反转 

//链表的反转
    public static LinkedList1 reverseLinked(LinkedList1 list1) {
        Stack<Node> stack = new Stack<>();
        for (Node n = list1.first; n != null; n = n.next) {
            stack.add(n);
        }
        LinkedList1 result = new LinkedList1();
        while (!stack.isEmpty()) {
            result.addLast(stack.pop().val);
        }
        return result;
    }

测试

        LinkedList1 linkedList1 =new LinkedList1();
        linkedList1.addLast(1);
        linkedList1.addLast(4);
        linkedList1.addLast(6);

        System.out.println("链表1:"+linkedList1);
        //链表的反转
        System.out.println("链表1反转后:"+LinkedList1.reverseLinked(linkedList1));

测试结果

链表实现两数之和 

    //两数之和
    public static LinkedList1 addNumber(LinkedList1 list1, LinkedList1 list2) {
        Node n1 = list1.first, n2 = list2.first;
        LinkedList1 result = new LinkedList1();
        int carry = 0;
        while (n1 != null || n2 != null) {
            int x = n1 != null ? n1.val : 0;
            int y = n2 != null ? n2.val : 0;
            int sum = x + y + carry;
            carry = sum / 10;
            result.addLast(sum % 10);

            if (n1 != null) {
                n1 = n1.next;
            }
            if (n2 != null) {
                n2 = n2.next;
            }
        }
        if (carry != 0) {
            result.addLast(carry);
        }
        return result;
    }

测试

        LinkedList1 linkedList1 =new LinkedList1();
        linkedList1.addLast(1);
        linkedList1.addLast(4);
        linkedList1.addLast(6);


        LinkedList1 linkedList2 =new LinkedList1();
        linkedList2.addLast(2);
        linkedList2.addLast(3);
        linkedList2.addLast(5);
        linkedList2.addLast(9);
        //两数之和
        System.out.println("链表1:"+linkedList1);
        System.out.println("链表2:"+linkedList2);
        System.out.println("链表1+链表2:"+LinkedList1.addNumber(linkedList1,linkedList2));

测试结果(注意从左到右依次是个十百位)

判定链表是否有环

方法一 通过set集合

    //set集合判断是否有环
    public static boolean hasCycle(Node node) {
        Set<Node> set = new HashSet<>();

        while (node != null) {
            if (set.contains(node)) {
                return true;
            }
            set.add(node);

            node = node.next;
        }
        return false;
    }

方法二 通过快慢指针

    //快慢指针判断是否有环
    public static boolean hasCycle2(Node node) {
        Node fast = node;//快指针
        Node slow = node;//慢指针

        //判断是不是空节点
        if (node == null) {
            return false;
        }
        while (fast != null && fast.next != null && slow != null) {
            fast = fast.next.next;
            slow = slow.next;

            if (fast == slow) {
                return true;
            }
        }
        return false;
    }

测试 无论方法一还是二 测试结果都是相同 一般使用方法二 效率更高 更节省资源

        LinkedList1.Node node1 =new LinkedList1.Node(1);
        LinkedList1.Node node2 =new LinkedList1.Node(2);
        LinkedList1.Node node3 =new LinkedList1.Node(3);
        LinkedList1.Node node4 =new LinkedList1.Node(4);
        LinkedList1.Node node5 =new LinkedList1.Node(5);

        node1.next=node2;
        node2.next=node3;
        node3.next=node4;
        node4.next=node5;
        node5.next=node3;//环 注意这是专门设置的环


        //set集合判断是否有环
        System.out.println("set集合判断是否有环:"+LinkedList1.hasCycle(node1));
        //快慢指针判断是否有环
        System.out.println("快慢指针判断是否有环:"+LinkedList1.hasCycle2(node1));

测试结果

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

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

相关文章

Springboot 前后端分离项目使用 POI 生成并导出 Excel

在做一个 SpringBoot 前后端分离项目的时候&#xff0c;需要将数据存到 Excel中&#xff0c;用户可以下载 Excel。具体实现是采用 Apache 强大的 POI。文章最后将源码例出。 POI API 文档&#xff1a; https://poi.apache.org/apidocs/dev/index.html 步骤 导入 POI 的 maven …

前端面试:01.图中输入什么?

~~~~~~~~~~~~~ 先自行想一想&#xff0c;答案在~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~ 先自行想一想&#xff0c;答案在~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~ 先自行想一想&#xff0c;答案在~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~ 先自行想一想&#xff0c;答案在~~~~~~~~~~~~~~~~~ ~~~~~~~~…

大数据Flink(九十一):Array Expansion(数组列转行)和Table Function(自定义列转行)

文章目录 Array Expansion(数组列转行)和Table Function(自定义列转行)

Vue系列(二)之 基础语法上篇【插值,指令,过滤器,计算属性监听属性】以及购物车实现

目录 一. 插值 1.1 文本 1.2 原始HTML 1.3 属性 1.4 表达式 二. 指令 2.1 v-if/v-else-if/v-else指令 2.2 v-show指令 2.3 v-for指令 2.4 下拉框/复选框 2.5 动态参数 三. 过滤器 3.1 局部过滤器基本应用 3.2 局部过滤器串行使用 3.3 局部过滤器传参 3.4 全局过…

华为云云耀云服务器L实例评测 | 实例使用教学之简单使用:通过部署宝塔面板可视化管理华为云云耀云服务器

华为云云耀云服务器L实例评测 &#xff5c; 实例使用教学之简单使用&#xff1a;通过部署宝塔面板可视化管理华为云云耀云服务器 介绍华为云云耀云服务器 华为云云耀云服务器 &#xff08;目前已经全新升级为 华为云云耀云服务器L实例&#xff09; 华为云云耀云服务器是什么华为…

遥遥领先喊得再大声也没用了,美企领先优势越发明显,无奈的现实

遥遥领先已成为这一段时间特殊的口号&#xff0c;然而口号终究代替不了现实&#xff0c;在广受关注的两个行业--汽车和手机市场&#xff0c;都显示出真正遥遥领先的其实是美企&#xff0c;后来者已越发难以追赶了。 在手机行业&#xff0c;苹果饱受诟病&#xff0c;又是镜头进灰…

Nginx之memcached_module模块解读

目录 基本介绍 安装添加模块 模块配置指令 基本介绍 nginx的memcached_module模块可以直接从memcached服务器中读取内容后输出&#xff0c;后续的请求不再经过应用程序处理&#xff0c;如php-fpm、django&#xff0c;大大的提升动态页面的速度。nginx只负责从memcach…

STM32 UART通信协议 基础知识

通用异步收发器&#xff08;Universal Asynchronous Receiver/Transmitter)&#xff0c;通常称作UART&#xff0c;是一种串行、异步、全双工的通信协议。 在通信领域中&#xff0c;有两种数据通信方式&#xff1a;并行通信和串行通信。串口的数据传输是以串行方式进行的。串口在…

libtorch之tensor的使用

1. tensor的创建 tensor的创建有三种常用的形式&#xff0c;如下所示 ones创建一个指定维度&#xff0c;数据全为1的tensor. 例子中的维度是2维&#xff0c;5行3列。 torch::Tensor t torch::ones({5,3}); zeros创建一个指定维度&#xff0c;数据全为0的tensor&#xff0c;例子…

最新AI写作系统ChatGPT源码/支持GPT4.0+GPT联网提问/支持ai绘画Midjourney+Prompt+MJ以图生图+思维导图生成

一、AI创作系统 SparkAi系统是基于很火的GPT提问进行开发的Ai智能问答系统。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署AI创作ChatGPT系统&#xff1f;小编这里写一个详细图文教程吧&#x…

极光笔记 | 聊一聊推送系统中事件驱动架构的应用

微服务间通信方式主要有2种&#xff1a;RPC和消息传递。 通常来说在请求/响应的场景下使用RPC更加合适&#xff0c;具体实现通常是REST API或者基于长链接的协议&#xff08;例如gRPC/Thrift/Zero ICE等&#xff09;。两个服务有比较强的依赖关系&#xff0c; 调用者依赖被调用…

亚马逊无线鼠标FCC认证办理 FCC ID

无线鼠标是指无线缆直接连接到主机的鼠标&#xff0c;采用无线技术与计算机通信&#xff0c;从而省却电线的束缚。通常采用无线通信方式&#xff0c;包括蓝牙、Wi-Fi (IEEE 802.11)、Infrared (IrDA)、ZigBee (IEEE 802.15.4)等多个无线技术标准。随着人们对办公环境和操作便捷…

OpenAI放出的ChatGPT 4的多模态语音和图像更新

近日OpenAI放出的ChatGPT 4的多模态语音和图像更新的模型其实叫GPT-4V(ision)。OpenAI放出了19页的GPT-4V(ision)报告来解释这个模型&#xff0c;释放了大量信息&#xff1a;GPT-4V(ision)的训练完成于2022年&#xff0c;2023年3月开始提供早期访问。GPT-4V 的训练过程与 GPT-4…

SQLAlchemy关联表一对多关系的详解

目录 ORM关系之一对多 示例1 代码刨析 示例2 代码刨析 ORM关系之一对多 mysql级别的外键&#xff0c;还不够爽&#xff0c;必须拿到一个表的外键&#xff0c;然后通过这个外键再去另外一张表中查找&#xff0c;这样太麻烦了。 SQLAlchemy提供了一个relationship&#xf…

软件工程第三周

可行性研究 续 表达工作量的方式 LOC估算&#xff1a;Line of Code 估算公式S(Sopt4SmSpess)/6 FP&#xff1a;功能点 1. LOC (Line of Code) 估算 定义&#xff1a;LOC是指一个软件项目中的代码行数。 2. FP (Function Points) 估算 定义&#xff1a;FP是基于软件的功能性和…

H5类似易企秀/编辑器/页面制作/开发/生成工具/软件/源码/授权

概述 H5DS (HTML5 Design software) 这是一款基于WEB的 H5制作工具。让不会写代码的人也能轻松快速上手制作H5页面。 详细 项目简介 H5DS (HTML5 Design software) 这是一款基于WEB的 H5制作工具。让不会写代码的人也能轻松快速上手制作H5页面。H5DS 官方 Git (GitHub - h5…

XC3110 高性能、低成本离线式PWM功率开关 可用于小家电电源 辅助电源 最大200MA的电流

XC3110是一款非隔离型、高集成度且低成本的PWM功率开关&#xff0c;适用于降压型和升降压型电路。 XC3110采用高压单晶圆工艺&#xff0c;在同一片晶圆上集成有500V 高压 MOSFET 和采用开关式峰值电流模式控制的控制器。在全电压输入的范围内可以保证高精度的5V 默认输出。在芯…

C#设置自动关机

功能&#xff1a;自动设置电脑关机时间&#xff0c;可取消 创建一个shutdown函数&#xff0c;bool isCancle&#xff0c;传入值为ture就取消关机&#xff0c;interval间隔时间&#xff0c;unit不带符号的整型 private static void ShutdownPC(bool isCancel, uint interval){P…

A*搜索算法

前言 这个我也不知道算不算是A*搜索算法&#xff0c;可能只是A搜索算法。 首先看相关的定义&#xff1a; 启发式搜索在搜索过程中根据启发信息评估各个节点的重要性&#xff0c;优先搜索重要的节点。 估价函数的任务就是估计待搜索节点“有希望”的程度。 估价函数f(n)定义…

vue 实现数字验证码功能

需求&#xff1a;写了一个 手机发送验证码后 输入固定验证码的功能 封装成一个组件,如下: <template><div class"conts"><div class"box"><div class"code_list"><div :class"[ code_item, hideIndex 0 ? co…