数据结构与算法-Java篇

news2024/9/20 1:05:29

1.队列问题

  • 队列是一个有序列表,可以用数组或是链表来实现。
  • 遵循先入先出的原则。即:先存入队列的数据,要先取出。后存入的要后取出

1.1 数组模拟队列

1.1.1 单列队列

  •  MaxSize表示队列的容量
  • 因为队列的输出、输入是分别从前后端来处理,因此需要两个变量 font 及 rear 分别记录队列前后端的下标,front 会随着数据输出而改变,而 rear 则是随着数据输入而改变。
  • 当我们将数据存入队列时称为”addQueue”,addQueue 的处理需要有两个步骤: 思路分析
  1. 将尾指针往后移: rear+1,当 front  == rear ->[空]
  2. 若尾指针 rear 小于队列的最大下标 maxSize-1,则将数据存入 rear 所指的数组元素中,否则无法存入数据。== maxSize - 1[队列满1

代码:


@Data
class ArrQuery {
    private Integer masSize;

    private Integer rear;

    private Integer front;

    private Integer[] arrData;

    /**
     * 初始化队列
     *
     * @param masSize
     */
    ArrQuery(Integer masSize) {
        this.masSize = masSize;
        arrData = new Integer[masSize];
        front = -1;
        rear = -1;

    }

    /**
     * 判断队列是否满
     */
    private Boolean isFull() {
        return masSize.equals(rear + 1);
    }

    /**
     * 判断队列是否为空
     */
    private Boolean isNull() {
        return Objects.equals(front, rear);
    }

    /**
     * 添加数据
     */
    private Integer add(Integer data) {
        if (this.isFull()) {
            return -1;
        }
        //队尾后移
        rear++;
        //给当前队尾添加数据
        arrData[rear] = data;
        return rear;
    }

    /**
     * 取出队列数据(先进先出 ,队头出队)
     */
    private Integer getQuery() {
        if (isNull()) {
            return null;
        }
        //取出队头后移
        front++;
        return arrData[front];
    }


}

但是这种单列队列有以下局限性:

  1. 一次性使用当队列满了再取出 front的下标索引后移无法还原->无法服用

1.2 循环数组模拟队列

  • front不再指向-1,直接队列指向第一个数据。初始值=0
  • rear指向队尾的后一个位置,初始值=0。
  • 队列满的条件事:(rear+1)%maxSize==front。
  • 队列为空的条件是 :rear==front。
  • 队列有效数据数量:(rear+maxSize-front)%maxSize。

代码:


@Data
class AnnularArrQuery {
    private Integer masSize;

    private Integer rear;

    private Integer front;

    private Integer[] arrData;

    /**
     * 初始化队列
     *
     * @param masSize
     */
    AnnularArrQuery(Integer masSize) {
        this.masSize = masSize;
        arrData = new Integer[masSize];
        front = 0;
        rear = 0;
    }

    /**
     * 判断是否为空
     */
    public Boolean isNull() {
        return front == rear;
    }

    /**
     * 是否满
     */
    public Boolean isFull() {
        return (rear + 1) % masSize == front;
    }

    /**
     * 统计有效数据数量
     */
    public Integer countData() {
        return (rear + masSize - front) % masSize;
    }

    /**
     * 添加
     */
    public Integer add(Integer data) {
        if (isFull()) {
            return -1;
        }
        arrData[rear] = data;
        //考虑取模
        rear = (rear + 1) % masSize;
        return rear - 1;
    }

    /**
     * 取出队列  先入先出 队头先出
     */
    public Integer get() {
        if (isNull()) {
            return null;
        }
        Integer data = arrData[front];
        front = (front + 1) % masSize;
        return data;
    }
    public void showQuery(){
        if (isNull()){
            System.out.println("null");
            return;
        }
        //从当前头遍历 剩余数量的数据
        for (int i=front;i<front+this.countData();i++){
            System.out.printf("arr[%d]=%d\n",i%masSize,arrData[i%masSize]);
        }
    }

    public Integer headQueue() {
        if (isNull()){
            return null;
        }
        return arrData[front];
    }
}

这样就优化了上述的无法服用问题。

但是使用数组队列还有有一定的局限性:

  • 空间有限。
  • 空间过大早期会浪费空间。
  • 如果做数组中的(删除/插入)操作需要迁移下标。

2.链表的使用

2.1 单链表

上面介绍的数组队列是地址空间连续的链式存储结构。

那么链表就是空间地址不联系的存储结构如图:

 

  •  链表是以节点的方式来存储,是链式存储
  • 每个节点包含 data 域, next 域: 指向下一个节点
  • 发现链表的各个节点不一定是连续存储
  • 链表分带头节点的链表和没有头节点的链表,根据实际的需求来确定 

代码:


public class SingleLinkListDemo {
    public static void main(String[] args) {
        SingleLinkList linkList = new SingleLinkList();

        linkList.addLinkNode(new LinkNode(new Person(1,"DFP",18)));
        linkList.addLinkNode(new LinkNode(new Person(3,"GG",13)));
        linkList.addLinkNode(new LinkNode(new Person(2,"CC",12)));
        linkList.addLinkNode(new LinkNode(new Person(7,"qq",17)));
        linkList.addLinkNodeById(new LinkNode(new Person(6,"rq",16)));

        linkList.showLink();

        linkList.deleteNode(3);
        linkList.updateNodeById(new LinkNode(new Person(6,"up6",26)));
        System.out.println("删除过后---------------------------");
        linkList.showLink();
    }
}

class SingleLinkList {
    private LinkNode head = new LinkNode(new Person(-1, "", -1));

    public Boolean addLinkNode(LinkNode data) {
        //操作变量
        LinkNode temp = head;
        while (true) {
            //找到队尾添加
            if (temp.nextData == null) {
                break;
            }
            //向后移
            temp = temp.nextData;
        }
        temp.nextData = data;
        return true;

    }

    public Boolean addLinkNodeById(LinkNode data) {
        //操作变量
        LinkNode temp = head;
        while (true) {
            if (temp.nextData.value.getId() == data.value.getId()) {
                System.out.printf("Person id is %d have exit ", data.value.getId());
                return false;
            }
            //从小到大排序插入 找到要插入的位置
            if (temp.nextData.value.getId() > data.value.getId()) {
                break;
            }
            //找到队尾添加
            if (temp.nextData == null) {
                break;
            }
            //向后移
            temp = temp.nextData;
        }
        //插入操作
        //1.将插入点的数据 接上当前节点后的数据
        data.nextData = temp.nextData;
        //2.将插入数据 接上当前节点
        temp.nextData = data;
        return true;
    }

    public void updateNodeById(LinkNode data) {
        if (head.nextData == null) {
            System.out.println("link is null");
            return;
        }
        LinkNode temp = head.nextData;
        while (true) {
            if (Objects.equals(temp.value.getId(), data.value.getId())) {
                temp.value.setAge(data.value.getAge());
                temp.value.setName(data.value.getName());
                break;
            }
            if (temp.nextData == null) {
                System.out.println("dont have node id is " + data.value.getId());
                break;
            }
            temp = temp.nextData;
        }
    }

    public void deleteNode(Integer id) {
        if (head.nextData == null) {
            System.out.println("link is null");
            return;
        }
        LinkNode curr = head.nextData;
        while (true) {
            //找到当前节点的下一个值
            if (Objects.equals(curr.nextData.value.getId(), id)) {
                //跳过目标节点,让当前节点的next指向下一个节点的next
                curr.nextData = curr.nextData.nextData;
                break;
            }
            if (curr.nextData == null) {
                System.out.println("dont have node id is " + id);
                break;
            }
            curr = curr.nextData;
        }
    }

    public void showLink() {
        if (head == null) {
            System.out.println("Link:[]");
            return;
        }
        LinkNode curr = head.nextData;
        while (true) {
            if (curr == null) {
                break;
            }
            System.out.println(curr);
            curr = curr.nextData;
        }
    }

}

@Data
@AllArgsConstructor
@NoArgsConstructor
class LinkNode {
    public Person value;
    public LinkNode nextData;

    LinkNode(Person person) {
        this.value = person;
    }

    @Override
    public String toString() {
        return "LinkNode{" + value + '}';
    }
}

@Data
@AllArgsConstructor
@NoArgsConstructor
class Person {
    private Integer id;
    private String name;
    private Integer age;


    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age='" + age + '\'' +
                ", id=" + id +
                '}';
    }
}

计算链表有效数据:

    /**
     * 统计链表数据
     */
    public Integer countSize() {
        int size = 0;
        LinkNode node = head.nextData;
        if (node == null) {
            return size;
        }
        while (node != null) {
            size++;
            node = node.nextData;
        }
        return size;
    }
查找倒数第n个节点数据:
public LinkNode getLastNode(Integer n) {
        LinkNode temp = head.nextData;
        if (temp == null) {
            System.out.println("dont have data");
            return null;
        }
        //倒数第1 就是正数size-n
        Integer index = this.countSize() - n;
        if (n < 0 || index < 0) {
            System.out.println("index is illegal");
            return null;
        }
        for (int i = 0; i < index; i++) {
            temp = temp.nextData;
        }
        return temp;
    }

链表反转;

  public void rollbackLink() {
        LinkNode curr = this.head.nextData;
        //空链表或者只有一个节点不需要反转
        if (curr.nextData == null || curr.nextData.nextData == null) {
            return;
        }
        LinkNode next = null;
        LinkNode rollbackLink = new LinkNode(new Person(-1, "", -1), null);

        while (curr!=null) {
            //next 存放当前节点下一位置
            next = curr.nextData;
            //将当前节点尾部链接到 反转链表头节点的下一节点
            curr.nextData = rollbackLink.nextData;
            //将当前节点追加到 反转链表头部
            rollbackLink.nextData = curr;
            //当前链表后移
            curr=next;
        }
        //链表互换
        head.nextData=rollbackLink.nextData;
    }

 

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

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

相关文章

深度学习模型训练好后使用time.time()测试处理每一帧速度(时间)和模型推理速度(时间)

在深度学习中&#xff0c;如果想测试训练好的模型处理每一帧图像的运行时间&#xff0c;可以在模型预测代码段添加时间统计的逻辑: 目录 加载预训练模型遍历测试图像汇总统计预测测试集全部图像的平均处理时间测试结果样式 加载预训练模型 model torch.load(best_model.pth) …

图数据库的挑战是什么?

无论是什么数据库&#xff0c;如果不突出性能这个第一生产力&#xff0c;那么还有什么继续深入了解它的必要呢&#xff1f;图数据库尤其如此——因为图数据库解决的最主要的挑战就是传统数据库在面对深度数据间的关联关系时指数级性能下降、时耗增长的问题。 这里我们就不去赘述…

uni-app自定义多环境配置,动态修改appid

背景 在企业级项目开发中&#xff0c;一般都会分为开发、测试、预发布、生产等多个环境&#xff0c;在工程化中使用不同的打包命令改变环境变量解决不同环境各种变量需要手动修改的问题&#xff0c;比如接口请求地址&#xff0c;不同环境的请求路径前缀都是不同的。在使用uni-…

百度王海峰披露飞桨生态最新成果 开发者数量已达800万

8月16日&#xff0c;由深度学习技术及应用国家工程研究中心主办的WAVE SUMMIT深度学习开发者大会2023在北京举行。百度首席技术官、深度学习技术及应用国家工程研究中心主任王海峰做了主题演讲。王海峰首次对外表示&#xff0c;大语言模型具备了理解、生成、逻辑、记忆等人工智…

CAN协议

CAN总线特点&#xff1a; 多主机多从机 串行异步通讯、没时钟线 2.只有CAN_HIGH和CAN_LOW两条差分信号 3.连接方式多个节点挂在总线上&#xff0c;比较类似I2C总线&#xff0c;可以再SCL和SDA上挂载多个从 4.每个设备都是一个节点Node&#xff0c;节点直接可以相互通讯&#…

使用PHP实现随机调用图片

&#x1f482; 个人网站:【工具大全】【游戏大全】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 寻找学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 预览地址&#xff1a;ht…

JavaWeb博客项目--推荐算法--完整代码及思路

基于用户的协同过滤算法&#xff08;UserCF&#xff09; 因为我写的是博客项目&#xff0c;博客数量可能比用户数量还多 所以选择基于用户的协同过滤算法 重要思想 当要向用户u进行推荐时&#xff0c;我们先找出与用户u最相似的几个用户&#xff0c;再从这几个用户的喜欢的物…

【NX】NX二次开发中如何绕固定轴旋转矢量

如何让任意矢量绕着任意轴旋转一定角度&#xff0c;得到新的矢量&#xff0c;在NX中&#xff0c;通过矩阵运算&#xff0c;可以直接得到目标向量。 直接上代码&#xff1a; AUTUMOON::AUTUMOONMathVector3d CAMToolPathToolkit::RotateVector(const AUTUMOONMathVector3d &…

版本控制工具Git集成IDEA的使用(超详细)

目录 一、团队内协作和跨团队协作讲述 1、团队内协作 2、跨团队协作 二、Gitee的使用 1、注册网站会员 2、用户中心 3、创建远程仓库 4、配置SSH免密登录 三、集成IDEA&#xff0c;Git项目搭建 1、本地仓库搭建 1&#xff09;创建一个新项目 2&#xff09;打开终端&…

windos安装oracle数据库图文教程

首先准备安装包&#xff0c; 链接&#xff1a;https://pan.baidu.com/s/17ltLy9TCwb5fAlaWq3hW4g 提取码&#xff1a;dsmd 这个版本是11.2&#xff0c;如果需要其他版本可以通过官网下载。 下载完成之后&#xff0c;保存路径不要有中文。 右键解压&#xff0c;会多出来个data…

重建与突破,探讨全链游戏的现在与未来

全链游戏&#xff08;On-Chain Game&#xff09;是指将游戏内资产通过虚拟货币或 NFT 形式记录上链的游戏类型。除此以外&#xff0c;游戏的状态存储、计算与执行等皆被部署在链上&#xff0c;目的是为用户打造沉浸式、全方位的游戏体验&#xff0c;超越传统游戏玩家被动控制的…

USB2.0与USB3.0接口的PCB布局布线要求

USB是通用串行总线的英文缩写&#xff0c;是连接外部装置的一个串口总线标准&#xff0c;也是一种输入输出接口的技术规范&#xff0c;被广泛地应用于个人电脑和移动设备等信息通迅产品&#xff0c;并扩展到摄影器材&#xff0c;数字电视&#xff08;机顶盒&#xff09;、游戏机…

智能仓储管理系统(自动化仓库管理解决方案)

企业实际的仓储管理中&#xff0c;往往会出现那样这样的错误&#xff0c;归根结底&#xff0c;主要是由于没使用合适的仓库管理工具。相反&#xff0c;人工使用合适的仓库管理工具&#xff0c;不仅可以在日常仓库管理方法中根据采集到的产品信息数据&#xff0c;大大地提高管理…

Leangoo领歌免费敏捷看板工具做—用户反馈管理

一个产品在面向市场之后势必会收到来自各个渠道的用户反馈。好的反馈有利于公司品牌的建立&#xff0c;挑剔和负面反馈可以帮助我们了解到用户最真是的需求和使用场景&#xff0c;有利于优化产品提高服务。更加能够提升用户的粘性。 在进行用户反馈管理时&#xff0c;用户反馈…

selenium 选定ul-li下拉选项中某个指定选项

场景&#xff1a;selenium的下拉选项是ul-li模式&#xff0c;选定某个指定的选项。 from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # 显示等待def select_li(self, text, *ul_locator):"…

随手笔记——Pose Graph理论以及g2o实现

随手笔记——Pose Graph理论以及g2o实现 说明源代码CMakeLists.txt 说明 源代码 #include <iostream> #include <fstream> #include <string>#include <g2o/types/slam3d/types_slam3d.h> #include <g2o/core/block_solver.h> #include <g2o…

Python实现两个主机的数据库同步

实现两个主机间mysql数据同步 import pymysql import pandas as pd from sqlalchemy import create_engineHOST_SUBOR_SYNCLIST (account_t, measure_system_t) # 需要更新的数据表def syncSqldata(source_db, target_db):for table in HOST_SUBOR_SYNCLIST :query "SE…

小米有品众筹,小米上新3D打印机!米家3D打印机购买前必看的注意事项!

小米推出3D打印机&#xff0c;米家3D打印机购买前必看 3D打印机在人们的生活中发挥着巨大的作用&#xff0c;无论是在科研实验室还是家庭工作室&#xff0c;它们正以惊人的速度改变着我们的世界。最近&#xff0c;科技巨头小米也加入了这一领域&#xff0c;推出了一款全新的&q…

从零实战SLAM-第十课(回环检测与建图)(完)

在七月算法报的班&#xff0c;老师讲的蛮好。好记性不如烂笔头&#xff0c;关键内容还是记录一下吧&#xff0c;课程入口&#xff0c;感兴趣的同学可以学习一下。 --------------------------------------------------------------------------------------------------------…

未来数字银行的样子

对银行长期发展来讲&#xff0c;这意味着将关闭和减少 低效率的实体分行&#xff0c;加速向数字化发展。实现成本节省和 IT 预算提效的需求&#xff0c;将为数字柜台和银行代理点创造新的机遇。 一个崭新的世界&#xff1a;未来数字银行趋势图 现在是银行迎头赶上并为客户提供超…