分治法

作者: 追寻米K | 来源:发表于2019-07-18 15:49 被阅读0次

二分查找

在android的SparseArray中get方法就是通过二分法查找到结果。
二分查找的前提是有一个已经排好序的数组。


二分查找

思路:假设我们需要查找22这个值在数组中的位置,如上图的数组,取数组的中间下标5中的值,为21,用目标值22跟21做对比,22大于21,就在右边继续查找22这个值,否则在左边查找。
接着再从剩下的数组大小中同理取一半的下标为8,值是62同目标22对比大于22,这在右边查找。以此类推,直到找到目标22为止,返回22的下标。没找到返回负 1。

 public void Test(){
        int[] array = {4,7,8,10,14,21,22,36,62,77,81,91};
        int key = 22;
        System.out.println(binarySearch(array,0,array.length,key));
    }
/**
     * 在array中从start到end查找有没有key这个值
     * @param array
     * @param start
     * @param end
     * @param key
     */
    private int binarySearch(int[] array,int start,int end,int key){
        int lo = 0;
        int low = start;
        int hight = end -1;

        while (low < hight){
            int mid = (low + hight)>>>1;
            int midVal = array[mid];
            if (midVal <key){
                low = mid +1;
            }else if (midVal > key){
                hight = mid -1;
            }else {
                return mid;
            }

        }
        return ~lo;
    }

输出结果就是 6

也有使用递归的思想去实现二分查找,但不建议这样做。

 /**
     *  递归实现二分查找
     * @param array
     * @param start
     * @param end
     * @param key
     * @return
     */
    private int binarySearch2(int[] array,int start,int end,int key){
        int mid = (start+end)>>>1;
        if (array[mid] == key){
            return mid;
        }
        if (start <end){
            if (array[mid] < key){
                return binarySearch2(array,mid + 1,end,key);
            }else if (array[mid] > key){
                return binarySearch2(array,start,mid - 1,key);
            }
        }
        return 0;
    }

快速排序
应用场景:大量数据并且是线性结构。
短处:
1、有大量重复数据,性能不好。
2、单向链式结构处理性能不好(一般来说,链式都不使用)

排序排序的思想:

给一组数据进行排序,首先把左边第一个值暂存在T上。


在数组两端各定义一个指针(就叫指针吧,好理解)。


移动high指针取值,然后跟T中存的数据比对(这里是31)。


如果high指针取的值(12)比暂存的值(31)小。


就替换low指针指向的值。


接着换low指针移动跟暂存的值(31)做对比。



如果low指向的值(68)比暂存值(31)大。



就把high指向的值替换为low的值。

接着再次更换移动的指针为high。

同样的指针指向的值(23)比暂存值(31)小,就替换。



用high指针的值替换low指针的值。

同理,再次切换指针移动,比暂存值大就往high指针替换,比暂存值小就往low指针替换。

最后两个指针指到了同一个值上。

把暂存值替换上去。

这样第一轮的排序完成,31左边的都比它小,右边的都比它大。
然后排序左边和右边,实现整个数组的排序。

  public void testQuickSort(){
        int[] array = new int[]{31,68,45,90,23,39,54,12,87,76};
        quickSort(array,0,array.length-1);
        for (int i = 0;i<array.length;i++){
            System.out.print(array[i]+" ");
        }
    }
 private void quickSort(int[] array,int begin,int end){
        if ((end - begin)<=0) return;
        int x = array[begin];
        int low = begin;
        int high = end;
        //由于会从两个方向取数据,需要定义一个方向;
        boolean direction = true;
        //开始排序
        L1:
        while (low < high){
            if (direction){
                //从右到左的找
                for (int i = high;i>low;i--){
                    if (array[i]<=x){
                        array[low++] = array[i];
                        high = i;
                        direction = !direction;
                        continue L1;
                    }
                }
                high = low;
            }else {

                for (int i= low;i<high;i++){
                    if (array[i]>=x){
                        array[high--] = array[i];
                        low = i;
                        direction = !direction;
                        continue L1;
                    }
                }
                low = high;
            }
        }
        //把最后找到的值放入中间位置
        array[low] = x;
        //开始完成左右两边的操作
        quickSort(array,begin,low-1);
        quickSort(array,low+1,end);

    }

归并排序
思想:


应用场景:数据量大并且是链式结构。
短处:需要空间大。
 public static void mergeSort(int[] array, int left, int right) {
        if (left == right) {
            return;
        } else {
            int mid = (left + right) >>> 1;
            mergeSort(array, left, mid);//排好左边  L
            mergeSort(array, mid + 1, right);//排好右边  R
            merge(array, left, mid + 1, right);//再对左右进行合并 D
        }
    }
//归并排序
    public static void merge(int[] array, int left, int mid, int right) {
        int leftSize = mid - left;
        int rightSize = right - mid + 1;
        //生成数组
        int[] leftArray = new int[leftSize];
        int[] rightArray = new int[rightSize];
        //填充数据
        for (int i = left; i < mid; i++) {
            leftArray[i - left] = array[i];
        }
        for (int i = mid; i <= right; i++) {
            rightArray[i - mid] = array[i];
        }
        //合并数组
        int i = 0;
        int j = 0;
        int k = left;
        while (i < leftSize && j < rightSize) {
            if (leftArray[i] < rightArray[j]) {
                array[k++] = leftArray[i++];
            } else {
                array[k++] = rightArray[j++];
            }
        }
        while (i < leftSize) {
            //左边还有数据没用完
            array[k++] = leftArray[i++];
        }
        while (j < rightSize) {
            //右边还有数据没用完
            System.out.print("k:" + k);
            System.out.print("length:" + array.length);
            array[k++] = rightArray[j++];
        }
    }

相关文章

  • Divide and Conquer

    算法之 分治法 Divide and Conquer 分治法: 分治法的设计思想是:将一个难以直接解决的大问题,分...

  • 归并排序

    1、分治法 归并排序是完全遵循分治策略的排序算法。什么是分治法? 分治法,即将原问题分解为几个规模较小的子问题,递...

  • 分治法,动态规划及贪心算法区别

    原文:分治法,动态规划及贪心算法区别 1.分治法 分治法(divide-and-conquer):将原问题划分成n...

  • [算法导论]归并排序

    时间复杂度 《算法导论》2.3.1 分治法。 归并排序采用了分治法的递归排序。分治法:分解子问题,解决子问题,合并...

  • Divide and Conquer 分治法

    Divide and Conquer 分治法

  • 分治法

    分治算法也叫分治策略,把输入分为若干个部分,递归的解每一个问题,最后将这些子问题合并成为一个全局解。 由此可以得到...

  • 分治法

    分治法求解的思想是将整个问题分成若干小问题后分而治之。通常,由分治法多得到的小问题与原问题具有相同的类型。并且在求...

  • 分治法

    分治法是一种算法思想,顾名思义就是分而治之的意思。把一个很难解决的问题划分成许多小问题进行解决然后合并。在计算机算...

  • 分治法

    一、基本概念 在计算机科学中,分治法是一种很重要的算法。字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或...

  • 分治法

    整数划分 所谓整数划分,是指把一个正整数n写成如下形式:n=m1+m2+...+mi; (其中mi为正整数,并且1...

网友评论

      本文标题:分治法

      本文链接:https://www.haomeiwen.com/subject/kfnvoqtx.html