分治法

二分查找

在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++];
        }
    }
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1.查找技术 1)顺序表查找,一个一个的遍历下去比对查找就ok了。 2)可以使用哈希表查找。 3)二分法查找,每次...
    仲达_dc6c阅读 276评论 0 0
  • 分治法是一种把大问题分解为小问题逐个求解,再把结果合并的解决方案,分治法衍生出的算法包含二分查找、合并排序、快速排...
    怀念小兔阅读 335评论 0 0
  • 原创-转载请注明出处。 分治法 分治法是一种很重要的算法,也就是“分而治之”的意思,就是把一个复杂的问题分解成两个...
    程序猿Jeffrey阅读 4,159评论 0 1
  • 分治法是一种算法思想,顾名思义就是分而治之的意思。把一个很难解决的问题划分成许多小问题进行解决然后合并。在计算机算...
    LikeWhoWho阅读 787评论 0 0
  • 我们的
    柠檬夏天的c阅读 141评论 0 0