【Java】数组的复制、反转、查找、排序

news2024/11/17 21:45:41

数组的复制、反转、查找、排序

复制

其中最关键的一点是搞清楚为什么数组复制和基本数据类型复制不同,是什么导致了这样的不同?
先来看例子

package com.atguigu.java;

public class ArrayTest3 {
    public static void main(String[] args) {
        //新建arr数组并输出
        int[] arr = new int[]{60,56,78,24,90,63};
        System.out.println("arr数组:");
        for(int i = 0;i<arr.length;i++){
            System.out.print(arr[i] + " ");
        }
        System.out.println();
        //虚假的数组复制
        int[] arr1;
        arr1 = arr;
        
        //真实的数组的复制
        int[] arr2 = new int[arr.length];
        for (int i = 0;i < arr.length;i++){
            arr2[i] = arr[i];
        }


        // 修改一下arr里面的值
        for (int i = 0; i < arr2.length; i++) {
            if (i % 2 == 0) {
                arr[i] = i;
            }
        }

        System.out.print("修改后的arr1数组");
        for(int i = 0;i<arr.length;i++){
            System.out.print(arr1[i] + " ");
        }
        System.out.println();
        System.out.println("----------------");
        System.out.print("修改后的arr2数组");
        for(int i = 0;i<arr.length;i++){
            System.out.print(arr2[i] + " ");
        }
        System.out.println();
        System.out.println("----------------");
    }
}

最后输出的结果是:

arr数组:
60 56 78 24 90 63
修改后的arr1数组0 56 2 24 4 63
----------------
修改后的arr2数组60 56 78 24 90 63
----------------

我们会发现通过=赋值来进行复制的操作让arr1在arr内值变化的同时也跟着变化,相当于一个快捷方式arr1指向了arr数组的真实数据,实际上在内存中也是这样,下面这张图就是相似的情况,两个变量名指向了同一片地址的内容。
内存解析
到这里你已经理解为什么修改arr1,arr也会跟着变了。因为他们根本就是同一个数组。
那么,我们不妨进一步进行总结,为什么int型、double型、Boolean型这些变量通过=来复制就没有问题?

答案是:数据类型不同

Java的8种基本数据类型,byte,short,int,Long,flout,double,boolean,char它们在声明和初始化时,都是存储在栈内存中的,相当于变量内直接就是值,那么,通过=来进行赋值就理所当然,也很直观。
而引用数据类型,例如String、数组这里的String是一个例外,虽然他也是存储的地址,但是对两个指向同一地址的变量之一进行修改时,会创建新的变量,有待后续研究,以及需要new关键字来声明的对象,是存放在其他内存中的,所以变量中存储的,只是一个地址值,如果这时候我们通过=来进行赋值,相当于只对地址进行了复制,而地址相同,指向的内存也当然相同了。相当于对同一对象进行操作,并没有真正创建一个新的数组。

反转

两种方式

public class ArrayTest3 {
    public static void main(String[] args) {
        //求数组
        String[] arr = new String[]{"我","是","恒","星","同","学"};
        System.out.println("arr数组:");
        for(int i = 0;i<arr.length;i++){
            System.out.print(arr[i] + " ");
        }
        System.out.println();

        //数组的反转:
        // 方式一:
        System.out.println("通过方式一反转:");
        for (int i = 0; i < arr.length / 2; i++){
            String temp = arr[i];
            arr[i] = arr[arr.length - i - 1];
            arr[arr.length - i - 1] = temp;
        }
        for(int i = 0;i<arr.length;i++){
            System.out.print(arr[i] + " ");
        }
        System.out.println();
        //方式二
        System.out.println("通过方式二反转:");
        for (int i = 0,j = arr.length - 1; i < j; i++,j--) {
            String temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
        for(int i = 0;i<arr.length;i++){
            System.out.print(arr[i] + " ");
        }
        System.out.println();
        System.out.println("----------------");
    }
}

结果为:

arr数组:
我 是 恒 星 同 学
通过方式一反转:
学 同 星 恒 是 我
通过方式二反转:
我 是 恒 星 同 学
----------------

查找

线性查找

查找刚刚的数组,线性查找只是依次比对每个元素

//线性查找
        String dest = "星";
        Boolean isFlag = false;
        for (int i = 0; i < arr.length; i++) {
            if (arr[i].equals(dest)) {
                System.out.println("找到了,是索引为" + i + "的元素。");
                isFlag = true;
                break;
            }
        }
        if (!isFlag) {
            System.out.println("没找到。");
        }

结果

arr数组:
我 是 恒 星 同 学
找到了,是索引为3的元素。

二分查找

前提:数组中元素有序

int[] arr = new int[]{12,23,45,56,67,78,90};

        //二分查找
        int dest = 56;
        int head = 0;//初始的首索引
        int end = arr.length - 1;
        Boolean isFlag = false;//找到了吗?
        while (head <= end) {//等于的情况也要考虑
            int middle = (head + end) / 2;
            if (arr[middle] == dest) {
                System.out.println("找到了!索引为:" + middle);
                isFlag = true;
                break;
            } else if (arr[middle] > dest){
                end = middle - 1;
            } else if (arr[middle] < dest){
                head = middle + 1;
            }
        }
        if (!isFlag) {
            System.out.println("很遗憾,没找到你想要的。");
        }

排序

面向工资的话,需要至少掌握冒泡排序和快速排序。

冒泡排序

可以点这里查看冒泡排序动画

//冒泡排序
//这是一个最简单的,不考虑优化的实现,即:每次都把所有数据比对一遍
for (int i = 0; i < arr.length - 1; i++) {
    for (int j = 0; j < arr.length - 1 - i; j++) {
        if (arr[j] > arr[j + 1]) {
            int temp = arr[j];
            arr[j] = arr[j+1];
            arr[j+1] = temp;
        }
    }
}

这里面可以解释一下为什么第二个循环是结束条件是j < arr.length - 1 - i

首先第一层循环条件是这个算法总共遍历多少轮,我们来看下面这张图,数组中有8个元素,这是第一轮遍历已经完成的结果,最后一个元素已经是最大。那么下一次我们只需要比对前7个元素,再比对6轮即可(共计7轮),因为比对到最后一轮时,第二个元素的位置已经确定,只剩下最后一个元素,他的位置不会再变了。所以第一个for循环结束条件是i < arr.length - 1

image-20230108171615769

其次,第二层是从第一个元素对比到当前无序的最后一个元素,拿上面这张图的例子来说,现在第二轮是比对从1到7这7个元素,arr.length - 1是当前数组的长度,显然还不够,还要再减去已经排好顺序的元素个数i,就变成了j < arr.length - 1 - i

优化

如果在某一步执行完时所有元素已经全部有序,那么下一步便不会再有数据交换发生 。抓住这一特点,我们可以让冒泡排序在检测到当前没有发生元素交换时主动结束。

//冒泡排序
for (int i = 0; i < arr.length - 1; i++) {
    Boolean swap = true;
    for (int j = 0; j < arr.length - 1 - i; j++) {
        if (arr[j] > arr[j + 1]) {
            int temp = arr[j];
            arr[j] = arr[j+1];
            arr[j+1] = temp;
        }else {
            swap = false;
        }
        if (!swap) {
            break;
        }
    }
}

快速排序

日后再说。

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

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

相关文章

【Java数据结构与算法】Day2-高级排序(希尔、归并、快速、计数)

✅作者简介&#xff1a;热爱Java后端开发的一名学习者&#xff0c;大家可以跟我一起讨论各种问题喔。 &#x1f34e;个人主页&#xff1a;Hhzzy99 &#x1f34a;个人信条&#xff1a;坚持就是胜利&#xff01; &#x1f49e;当前专栏&#xff1a;【Java数据结构与算法】 &#…

实验七:555定时器及其应用

答疑解惑用555定时器组成的单稳态电路中&#xff0c;若触发脉冲宽度大于单稳态持续时间&#xff0c;电路能否正常工作&#xff1f;如果不能&#xff0c;则电路应做如何修改&#xff1f;答:若触发脉冲宽度大于单稳态持续时间后&#xff0c;输出脉冲宽度将等于触发脉冲的低电平持…

【精】EditorConfig 小老鼠 跨编辑器 | IDE 保持一致的编码风格

【精】EditorConfig 小老鼠 跨编辑器 | IDE 保持一致的编码风格 &#x1f345;因发布平台差异导致阅读体验不同&#xff0c;将本文原编写地址贴出&#x1f339;&#xff1a;《【精】EditorConfig 小老鼠 跨编辑器 | IDE 保持一致的编码风格》 文章目录【精】EditorConfig 小老鼠…

实时数仓方案

2、实时数仓方案 2.1、为何需要实时数仓架构 随着数据量的增大&#xff0c;传统数据的方案在时效性上和数据维护上变得越来越困难。实时数仓架构应运而生。 具体方案落地上实时数仓有很多方案可以选择&#xff0c;不同的业务和应用场景到底应该选择哪种技术方案&#xff1f;…

React18新特性

React 团队在 2022 年 3 月 29 日正式发布了 React 的第 18 个版本。 在这篇文章里简单介绍 React 18 的新特性&#xff0c;React Concurrent Mode&#xff08;并发模式&#xff09;的实现&#xff0c;以及简要的升级指南。 New Features Automatic Batching 早在 React 18 之…

011-Ensp-实验-配置ACL

实验要求 1.通过ACL 使PC1无法访问PC3 实验结构 实验步骤 基础环境配置: PC间互通 1. PC1 2 3 配置IP网关 2. LSW2 创建三个vlan &#xff0c;g0/0/2 g0/0/3 g/0/04 类型配置为Access 分别加入三个vlan g0/0/1 配置为trunk 并允许所有vlan通过 3. LSW1 g0/0/1 配置trunk …

vector底层实现及深层次拷贝问题

目录 大框架 接口实现 深层次拷贝问题&#xff08;两次深拷贝&#xff09; 大框架 为了与库里实现的更接近一些&#xff0c;先来看一下STL中是如何实现vector的&#xff08;这里不是PJ版&#xff0c;PJ版稍微晦涩一点不容易理解&#xff0c;这里采用Linux下g的版本&#xf…

VectorNet: Encoding HD Maps and Agent Dynamics from Vectorized Representation

Paper name VectorNet: Encoding HD Maps and Agent Dynamics from Vectorized Representation Paper Reading Note URL: https://arxiv.org/pdf/2005.04259.pdf TL;DR waymo 出品的 CVPR2020 论文 &#xff0c;关注在自动驾驶场景&#xff08;复杂多智能体系统&#xff0…

【算法自由之路】快慢指针在链表中的妙用(下篇)

【算法自由之路】快慢指针在链表中的妙用&#xff08;下篇&#xff09; 继上篇之后&#xff0c;链表这块还有两个相对较难的问题我们继续举例。 问题 1 给定具有 random 指针的 next 方向无环单链表&#xff0c;复制该链表 单听这个问题可能有点懵&#xff0c;这个链表结构我…

PCB封装创建(CHIP类)

PCB封装要有以下内容 PCB焊盘管脚序号丝印阻焊1脚标识目录 CHIP类&#xff08;电阻 电容 电感 三极管&#xff09; 0805C 0805R 0805L SOT-23 1.CHIP类&#xff08;电阻 电容 电感 三极管&#xff09; 1.新建一个PCB元件库 打开PCB Library 以下以0805为例。 创建080…

“CAcModuleResourceOverride”: 未声明的标识符

本文迁移自本人网易博客&#xff0c;写于2011年10月8日首先是运行时提示&#xff1a;试图执行系统不支持的操作。添加CAcModuleResourceOverride resourceOverride; 后&#xff0c;编译出现如下错误&#xff1a;error C2065: “CAcModuleResourceOverride”: 未声明的标识符 添…

scikit-learn 普通最小二乘法

scikit-learn 普通最小二乘法什么是普通最小二乘法&#xff1f;参考文献什么是普通最小二乘法&#xff1f; 线性回归模型的数学表达式如下&#xff1a; y^(w,x)w0w1x1…wpx1\hat{y}(w, x)w_{0}w_{1} x_{1}\ldotsw_{p} x_{1}y^​(w,x)w0​w1​x1​…wp​x1​ 其中 w0,w1,...,w…

Java--集合

1、集合框架 集合框架被设计成要满足以下几个目标。 该框架必须是高性能的。基本集合&#xff08;动态数组&#xff0c;链表&#xff0c;树&#xff0c;哈希表&#xff09;的实现也必须是高效的。 该框架允许不同类型的集合&#xff0c;以类似的方式工作&#xff0c;具有高度的…

【自用】高频电子线路复习(更新中)

疫情原因 没有考试就放假回家了 返校后将先进行死亡考试周 七天考完九门 回校再进行极限复习只能说可以通过 而不利于绩点的提升 所以要从现在开始抽取一些时间进行学习 第七章 频率变换方法与电路分析 7.1 非线性电路包括 发送端的高频振荡器、倍频器、谐振功率放大器和调…

【ROS自定义文件】自定义头文件及源文件的调用

本文记录ROS中的自定义文件的调用&#xff0c;主要包括自定义头文件和源文件的使用。 1 自定义C头文件的调用 注意这个文件目录的结构&#xff0c;尤其是 hello.h 这个自定义的头文件在 include/plumbing_head 文件夹之下&#xff0c;这个会直接影响后续头文件的引用。 hello.…

尚医通-整合网关-Nuxt搭建前端环境(二十六)

目录&#xff1a; &#xff08;1&#xff09;整合服务网关 &#xff08;2&#xff09;前台用户系统-nuxt搭建前端环境 &#xff08;3&#xff09;前台用户系统-目录结构和封装axios &#xff08;1&#xff09;整合服务网关 前面的过程使用nginx请求转发 下面使用SpringClo…

ScheduledThreadPoolExecutor定时任务执行线程池分析

概述 ScheduledThreadPoolExecutor自然是继承了ThreadPoolExecutor&#xff0c;那么它也就是一个被定义了特定功能的线程池而已&#xff0c;本质上就是一个ThreadPoolExecutor。 代码分析 可以看到其继承了ThreadPoolExecutor&#xff0c;在new ScheduledThreadPoolExecutor…

【FPGA】Verilog 编码实现:与非门 | 或非门 | 异或门 | NAND/NOR/XOR 行为验证

写在前面&#xff1a;本章主要内容为了解和确认 NAND/NOR/XOR 门的行为&#xff0c;并使用Verilog实现&#xff0c;生成输入信号后通过模拟&#xff0c;验证每个门的操作&#xff0c;并使用 FPGA 来验证 Verilog 实现的电路的行为。 本章目录&#xff1a; Ⅰ. 前置知识 0x00…

C++ 排序大合集

目录 一、了解排序 1、内部 2、外部 二、排序的稳定性 三、插入排序 1、算法和操作 2、代码 四、选择排序 1、算法和操作 2、代码 五、冒泡排序 1、算法和操作 2、代码 六、堆排序 1、优先队列 2、排序代码 七、归并排序 1、定义 2、基本算法 &#xff08;1&#xff09;、分离 …

宝塔Linux面板安装MySQL数据库,并且开启远程链接

1.宝塔面板【软件商店】->【应用搜索】&#xff0c;搜索MySQL,然后点击安装想要的版本&#xff0c;我这边是安装的5.6版 2. 安装完后重置数据库管理员密码 3.Navicat Premium 15连接数据库 4.外网navicat工具无法连接数据库的处理办法 4.1输入 mysql -u root -p 后回车&a…