Java实现快速排序和二分查找详解

本文将详细讲解二分查找和快速排序,以及实现代码. 真正理解原理和代码, 你将在面试中通关.

二分查找:

折半算法, 一种在 有序数组 中 查找某一特定元素 的搜索算法。

从定义中我们可以知道三个要点:

1.二分, 怎么分呢

方法一: mid = (low + high) / 2 (当low和high值特别大时,存在溢出风险)

方法二: mid = low + (high – low)/2 (没有风险,更优)

2.必须要有序

我们很难保证我们的数组都是有序的, 在构建数组的时候可以进行排序

3.必须是数组

二分查找过程:

1.从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;

2.如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。

3.如果在某一步骤数组为空,则代表找不到。这种搜索算法每一次比较都使搜索范围缩小一半。

二分查找有递归和循环两种方式实现, 两种方式的区别:

1.效率和资源占用问标题: 递归实现效率不如循环。
      递归由于是函数调用自身,而函数调用要消耗空间和时间,每一次调用都需要在内存栈中分配空间,来保存参数、返回地址及临时变量,并且往栈里压入数据和弹出数据都需要时间。递归中有很多计算是重复的,因此带来很大的负面影响。其本质是把一个问题分解成两个和多个小问题,如果多个小问题存在相互重叠部分,就造成重复计算。
2.调用栈溢出。每次函数调用在内存栈中分配空间,而每个进程栈的容量有限,当递归调用层级太多,就会超出栈的容量,导致调用栈溢出。

代码实现及详解如下:

 //参数arrays传入查找的数组, target:目标数值, low:最低索引位, high:最高索引位 返回目标索引值
    public static int MyBinarySearch(int[] arrays, int target,int low,int high){
        //(测试时要先排序,比如这个数组,arrays[high]值为4,110比最高位大,直接返回错位结果)
        System.out.println(arrays[low]+"-"+arrays[high]);
        if (target < arrays[low] || target > arrays[high] || low > high){
            return -1;
        }
        int middle = low + (high - low)/2;
        if (arrays[middle] > target){
            //也可以用循环调用的方式进行二分,这里采用递归
            return MyBinarySearch(arrays, target, low,middle-1);
        }else if (arrays[middle] < target){
            return MyBinarySearch(arrays,target,middle+1,high);
        }else {
            return middle;
        }
    }

    //这里采用循环方式实现二分查找,与递归区别在于递归消耗更多的内存计算资源
    public static int MyBinarySearch2(int[] arrays,int target,int low ,int high){
        if (target < arrays[low] || target > arrays[high] || low > high){
            return -1;
        }

        while (low <= high){
            int middle = low + (high - low)/2;
            if (arrays[middle] < target){
                low = middle+1;
            }else if (arrays[middle] > target){
                high = middle-1;
            }else {
                return middle;
            }
        }
        return -1;
    }

快速排序:

采用从两头向中间扫描的方法,同时交换与基准记录逆序的记录.

排序原理:

1.从数列中挑出一个元素,称为"基准";

2.重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边).在这个分区退出之后,该基准就处于数列的中间位置.这个称为分区操作;

3.递归地把小于基准值元素的子数列和大于基准值元素的子数列排序

代码实现及详解如下:

//快速排序 参数arrays:要排序的数组, low:首元素索引 high:尾元素索引
    public static void QuickSort(int[] arrays, int low, int high){
        //如果low>high直接返回,如果low==high,表示只有一个元素,也不用排序,直接返回
        if (low >= high || arrays.length <=1 || arrays==null){
            return;
        }

        //低位索引
        int i = low;
        //高位索引
        int j = high;
        //待排序第一个值,作为基准值
        int base = arrays[low];

        while (i < j){
            //高位索引值大于或等于基准值,就继续向低位索引找,一直找到比基准值小的元素
            while (arrays[j] >= base && i < j){
                j--;
            }

            //低位索引小于或等于基准值,就向高位索引找,一直找到比基准值大的元素
            while (arrays[i] <= base && i < j){
                i++;
            }
            //找到两个元素就将比基准值小的放左边, 比基准值大的放右边, 交换位置
            swap(arrays,i,j);
        }
        //再将基准值归位
        swap(arrays,low,j);
        //递归调用,从低位索引向高位索引
        QuickSort(arrays,low,j-1);
        //递归调用,从高位索引向低位索引
        QuickSort(arrays,j+1,high);
    }

    private static void swap(int[] arrays,int i , int j){
        int tmp = arrays[i];
        arrays[i] = arrays[j];
        arrays[j] = tmp;
    }

代码结果测试代码:

import java.util.Arrays;
import java.util.logging.Level;

/**
 * @author Jeady
 * @Date 2020/2/3
 */
public class BinarySearch {
    public static void main(String[] args) {
        //定义一个数组
        int[] arrays =  {5,1,7,3,110,6,9,4};
        QuickSort(arrays,0,arrays.length-1);

//        for (int array : arrays) {
//            System.out.println(array);
//        }
        //二分查找代码测试
        int result = MyBinarySearch(arrays,7,0,arrays.length-1);
//        int result = MyBinarySearch2(arrays,110,0,arrays.length-1);
        System.out.println(result);
    }
}
如果您是一位程序员大佬,躬请加V:"J786494566",给我的文章提提意见;
如果您对我的文章有兴趣,躬请加V:"J786494566",您是我动力的源泉;
发布了20 篇原创文章 · 获赞 4 · 访问量 2726

猜你喜欢

转载自blog.csdn.net/qq_43149023/article/details/104166944
今日推荐