详解Java数组的排序算法与二分查找法

 更新时间:2023年05月25日 11:41:49   作者:一一哥Sun  
这篇文章详细给大家介绍了Java数组的排序算法与二分查找法,文中有详细的代码示例,对大家的学习或工作有一定的帮助,需要的朋友可以参考下

一. 数组排序

1. 简介

Java中的数组是一种数据集合,里面可以存储若干数据元素。有时我们需要对这些数据元素进行排序,找出数组中的最大值、最小值,或者是按降序或升序对数组进行排列,这些需求都需要我们能够对数组进行排序。但我们要注意,对数组排序会修改数组本身,即数组里元素的内存指向会发生改变。

对数组进行排序是程序中很常见的需求。如果我们想要实现数组排序,可以利用数据结构中的某些排序算法来进行实现,比如著名的冒泡排序、选择排序等,当然也可以利用Java自带的Arrays.sort()方法来实现。接下来就针对这几种实现方案,给大家设计几个实现案例。

2. 冒泡排序(重点)

2.1 简介

冒泡排序的核心实现思路,就是把数据元素按照从下到上,两两进行比较。所以冒泡排序的特点是,每一轮循环后,最大的一个数被交换到末尾。因此,下一轮循环可以“刨除”最后的数,每一轮循环都比上一轮循环的结束位置靠前一位。冒泡排序整体可以分为两种情况,即升序排列和降序排列。

升序排列的实现思想:

将数组中相邻的两个数据元素进行比较,如果前面一个元素比后面的大,就把两者交换位置(一轮比较);

然后将上面的操作进行循环(比较n-1轮)。

排列过程如下图所示:

降序排列的实现思想:

将数组中相邻的两个数据元素进行比较,如果前面一个元素比后面的小,就把两者交换位置(一轮比较);

然后将上面的操作进行循环(比较n-1轮)。

2.2 基本实现

大家要注意,面试时经常会让我们手写冒泡排序和选择排序等算法,你必须牢牢地记住相关的代码实现哦。

/**
 * @author
 */
public class Demo09 {
    public static void main(String[] args) {
	// 冒泡排序--基本实现
	//待排序的数组
	int[] arr = { 1, 3, 46, 22, 11 };
	//控制需要比较几轮
	for (int i = 0; i < arr.length; i++) {
            //控制每一轮的比较次数
            for (int j = 0; j < arr.length - 1; j++) {
            //如果前面的比后面的数字大,则两者就进行交换
		if (arr[j] > arr[j + 1]) {
                    //两数交换,需要一个“第三方”,好比两杯水互换,需要第三个杯子。
                    //交换两个变量的值,必须借助一个临时变量。
                    //定义一个新的临时变量,将数组中的前面的元素先赋值给临时变量
                    int temp = arr[j];
                    //后面的值赋值到前面的位置上
                    arr[j] = arr[j + 1];
                    //再将临时变量的值赋值到后面的位置上
                    arr[j + 1] = temp;
		}
            }
	}
	//遍历排序后的数组
	for(int i=0;i<arr.length;i++) {
            System.out.print(arr[i]+"\t");
	}
    }
}

这种实现方式比较容易理解,但并不是最优的实现方案,因为这种方案需要比较的次数较多。我们可以进一步对该方案进行优化,将比较的次数降下来,请继续往下看。

2.3 优化次数

在本案例中,会对比较次数进行优化。

/**
 * @author 
 */
public class Demo10 {
    public static void main(String[] args) {
	// 冒泡排序--优化比较次数
	// 待排序数组
	int[] arr = { 1, 3, 46, 22, 11 };
	for(int j = 0; j < arr.length; j++) {//控制轮数
	    for(int i = 0; i < arr.length - 1 - j; i++) {//控制每一轮的次数
	        if(arr[i] > arr[i+1]) {
	            int temp = arr[i];
	            arr[i] = arr[i+1];
	            arr[i+1] = temp;
	        }
	    }
	}
        //遍历排序后的数组
	for(int i=0;i<arr.length;i++) {
            System.out.print(arr[i]+"\t");
	}
    }
}

本案例同样也不是最优的实现方案,我们也可以对该实现方案进行优化。

2.4 优化轮数

在本案例中,会对比较的轮数进行优化。

/**
 * @author
 */
public class Demo11 {
    public static void main(String[] args) {
	// 冒泡排序--优化比较轮数
	// 待排序数组
	int[] arr = { 1, 3, 46, 22, 11 };
	for (int j = 0; j < arr.length - 1; j++) { //轮数
	    //假设这一轮已经拍好序,设置一个标签进行记录
	    boolean flag = true;
	    for (int i = 0; i < arr.length - 1 - j; i++) {//每一轮比较的次数
	        if(arr[i] > arr[i+1]) {
	            //更改是否比较过的标签
	            flag = false;
	            int temp = arr[i];
	            arr[i] = arr[i+1];
	            arr[i+1] = temp;
	        }
	    }
	    //如果本轮已排序好,则直接跳过,避免没必要的比较。
	    if(flag) {
	        break;
	    }
	}
	//遍历排序后的数组
	for(int i=0;i<arr.length;i++) {
            System.out.print(arr[i]+"\t");
	}
    }
}

这种实现方案,可以说是三种方案中最优的一种,但对初学者来说,理解起来确实不容易。当然,在我们的线下课程中,我们的讲师会对实现的每一个步骤详细讲解,不用怕自己理解不了。

3. 选择排序(重点)

3.1 简介

选择排序的核心实现思路,是随机确定一个标志位(一般为第一个数字)作为最小数,然后向后 遍历 ,找到比标志位更小的数字后,便与标志位互换位置,并更新最小数。选择排序同样可以进行升序或降序排列。

选择排序升序思路:

将当前位置上的数,与它后面的每个数进行比较,选择出最小的那个数,交换到当前位置;

循环选择当前位置上的数。

选择排序降序思路:

将当前位置上的数,与它后面的每个数进行比较,选择出最大的那个数,交换到当前位置;

循环选择当前位置上的数。

3.2 实现案例

以下是以升序的方式实现的选择排序代码,供大家参考。

/**
 * @author
 */
public class Demo12 {
    public static void main(String[] args) {
	// 选择排序
	// 待排序的数组
	int[] arr = { 1, 3, 46, 22, 11 };
	for (int j = 0; j < arr.length-1; j++) {
	    //选择下标为0的位置
	    int min = j;
	    //将当前这个数与后面的每个数进行比较
	    for (int i = j+1; i < arr.length; i++) {
	        //如果当前数字小于标记的最小值,则将当前数字标记为最小值
	        if(arr[min] > arr[i]) {
	            min = i;
	        }
	    }
	    //如果当前数字不是最小的,则进行交换
	    if(min != j) {
	        int temp = arr[j];
	        arr[j] = arr[min];
	        arr[min] = temp;
	    }
	}
        //遍历排序后的数组
        for(int i=0;i<arr.length;i++) {
            System.out.print(arr[i]+"\t");
        }
    }
}

4. Arrays.sort方法

以上两种排序算法,实现起来是比较复杂的,但在面试时,基本上都要求我们能够手写出冒泡排序和选择排序,大家一定要把代码看懂哦。但如果我们想快速实现排序,其实可以使用Java自带的API方法进行实现,这个会更简单。

4.1 简介

Arrays工具类主要用于对数组进行排序、查找、填充、比较等的操作,该类存在于java.util包下,所以我们使用的第一步就是要先进行导包: import java.util.Arrays;

其中Arrays.sort()是Arrays类中的一个静态方法,用于对数组进行排序,我们可以直接调用。该方法有如下几种重载形式:

  • sort(T[] a) :对指定T型数组按数字升序排序;
  • sort(T[] a, int formIndex, int toIndex) :对指定T型数组中 [formIndex,toIndex) 数据按数字升序排序;
  • sort(T[] a, Comparator<? supre T> c) : 依据比较器对T型数组进行排序;
  • sort(T[] a, int formIndex, int toIndex, Comparator<? supre T> c) : 依据比较器产生的顺序对T型数组中的 [formIndex,toIndex) 进行排序。

4.2 实现案例

接下来再给大家设计一个利用Arrays.sort方法实现的排序案例。

/**
 * @author 
 */
public class Demo13 {
    public static void main(String[] args) {
	// 选择排序
	//遍历排序后的数组
	String[] names = { "cxk", "rose", "lihua", "lilei", "zhaosi" };
	//直接利用Arrays类提供的数组排序的方法,内部是基于“快速排序”实现的。
	Arrays.sort(names);
	for (int i = 0; i < names.length; i++) {
            System.out.print(names[i] + "\t");
	}
    }
}

二. 二分查找法

1. 简介

我们对数组除了可以进行排序之外,还能对数组中的元素进行查找,其中一个比较经典的方案是利用二分查找法,也叫做折半查找法进行实现,可以缩小查找范围,提高查找效率。

二分查找是一种效率较高的查找方法,要求数据表须采用顺序存储结构,且数组是有序(升序或者降序)的。核心思路就是将待查找的元素与中间下标对应的元素进行比较,如果大于中间下标对应的元素,则去右半部分查找,否则就去左半部分进行查找。基本实现流程如下:

  • 首先,我们假设数组中的元素是按升序排列的;
  • 然后将数组中间位置记录的 关键字 与查找关键字进行比较,如果两者相等,则查找成功;
  • 否则就利用中间的位置 记录, 将数组分成前、后两个子部分。如果中间位置记录的关键字大于查找关键字,则进一步查找前一子部分,否则进一步查找后一子部分;
  • 重复以上过程,直到找到满足条件的 记录为止 。或直到子部分不存在为止,此时查找不成功。

2. 实现案例

然后就按照上述思路,给大家设计了如下案例,大家可以对照练习,好好琢磨该案例。

/**
 * @author 
 */
public class Demo14 {
    public static void main(String[] args) {
	// 二分查找法--折半查找法
	// 遍历排序后的数组
	int[] arr = { 1, 3, 46, 22, 11 };
	int index = search(arr,46);
	System.out.println("46所在的索引位置="+index);
    }
    //定义一个方法,实现二分查找
    public static int search(int[] arr,int num) {
	//1. 获取最小、大值的下标
	int min = 0;
	int max = arr.length -1;
	while(min <= max) {
	    //2. 获取中间值的下标
	    int middle = (min + max) / 2;
	    //3. 将要查找的数字与中间值做比较
	    if(num > arr[middle]) {
	        min = middle +1;
	    }else if(num < arr[middle]) {
	        max = middle -1;
	    }else {
	        return middle;
	    }
        }
	return -1;
    }
}

三. 结语

至此,就把一维数组的内容给大家介绍完毕了,现在你知道数组有什么作用了吗?今日重点:

  • 常用的排序算法有冒泡排序、插入排序和快速排序等;
  • 冒泡排序使用两层for循环实现排序;
  • 交换两个变量的值需要借助一个临时变量。
  • 可以直接使用Java标准库提供的Arrays.sort()进行排序;
  • 对数组排序会直接修改数组本身。

对于数组,我们要掌握其基本用法,明白数组的扩容原理,并掌握数组的排序算法。

以上就是详解Java数组的排序算法与二分查找法的详细内容,更多关于Java数组排序算法与二分查找法的资料请关注脚本之家其它相关文章!

相关文章

  • Spring Boot中KafkaListener的介绍、原理和使用方法案例详解

    Spring Boot中KafkaListener的介绍、原理和使用方法案例详解

    本文介绍了Spring Boot中 @KafkaListener 注解的介绍、原理和使用方法,通过本文的介绍,我们希望读者能够更好地理解Spring Boot中 @KafkaListener 注解的使用方法,并在项目中更加灵活地应用
    2023-09-09
  • 详解springboot热启动与热部署

    详解springboot热启动与热部署

    本篇文章主要介绍了详解springboot热启动与热部署,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-06-06
  • SpringMVC + servlet3.0 文件上传的配置和实现代码

    SpringMVC + servlet3.0 文件上传的配置和实现代码

    本篇文章主要介绍了SpringMVC + servlet3.0 文件上传的配置和实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-04-04
  • Java利用Geotools实现不同坐标系之间坐标转换

    Java利用Geotools实现不同坐标系之间坐标转换

    GeoTools 是一个开源的 Java GIS 工具包,可利用它来开发符合标准的地理信息系统。本文将利用工具包Geotools实现不同坐标系之间坐标转换,感兴趣的可以了解一下
    2022-08-08
  • Spring Boot基础学习之Mybatis操作中使用Redis做缓存详解

    Spring Boot基础学习之Mybatis操作中使用Redis做缓存详解

    这篇文章主要给大家介绍了关于Spring Boot基础学习之Mybatis操作中使用Redis做缓存的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用spring boot具有一定的参考学习价值,需要的朋友们下面来一起看看吧
    2018-11-11
  • chatgpt java环境调用源码实现demo

    chatgpt java环境调用源码实现demo

    这篇文章主要介绍了chatgpt java环境调用源码实现demo,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-02-02
  • SpringBoot项目URL访问异常的问题处理

    SpringBoot项目URL访问异常的问题处理

    这篇文章主要介绍了SpringBoot项目URL访问异常的问题处理方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • java 方法泛型入参T和String的重载关系详解

    java 方法泛型入参T和String的重载关系详解

    这篇文章主要介绍了java 方法泛型入参T和String的重载关系详解,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-02-02
  • springboot Quartz动态修改cron表达式的方法

    springboot Quartz动态修改cron表达式的方法

    这篇文章主要介绍了springboot Quartz动态修改cron表达式的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-09-09
  • Java实战项目之校园跑腿管理系统的实现

    Java实战项目之校园跑腿管理系统的实现

    只有理论是不够的,只有在实战中才能获得能力的提升,本篇文章手把手带你用java+Springboot+vue+maven+elementui+mysql实现一个校园跑腿管理系统,大家可以在过程中查缺补漏,提升水平
    2022-01-01

最新评论