二分查找与几种排序方法

  1. 递归二分查找
  2. 冒泡排序
  3. 选择排序
  4. 插入排序
  5. 归并排序
  6. 快速排序

1、递归二分查找

思想

使用二分查找的前提条件是数组元素必须已经排好序。

代码:

public static int binarySearch(int[] list, int key){
        return binarySearch(list, key, 0, list.length - 1);
    }
    public static int binarySearch(int[] list, int key , int low, int high){
        //没有查找到
        if(low > high)
            return - low - 1;
        
        int mid = (low + high) / 2;
        if(key < list[mid]){
            return binarySearch(list, key, low, mid - 1);
        }else if(key == list[mid]){
            return mid;
        }else{
            return binarySearch(list, key, mid + 1, high);
        }
    }

2、冒泡排序

动画演示:http://liveexample.pearsoncmg.com/dsanimation/BubbleSortNeweBook.html

思路

依次比较相邻的两个数,将小数放在前面,大数放在后面

即在第一趟:首先比较第1个和第2个数,将小数放前,大数放后。然后比较第2个数和第3个数,将小数放前,大数放后,如此继续……直至比较最后两个数,将小数放前,大数放后。重复第一趟步骤,直至全部排序完成。

第一趟比较完成后,最后一个数一定是数组中最大的一个数,所以第二趟比较的时候最后一个数不参与比较;

第二趟比较完成后,倒数第二个数也一定是数组中第二大的数,所以第三趟比较的时候最后两个数不参与比较;

依次类推,每一趟比较次数-1;

……

代码:

public static void bubbleSort(int[] array) {

        // 优化:如果在某次遍历中没有发生交换,那么就不用再进行下一次遍历了,因为所有元素已经排好序了
        boolean needNextPass = true;

        //需要array.length-1次遍历
        for(int k = 1; k < array.length && needNextPass; k++){

            needNextPass = false; //假设不需要进行下次遍历

            //第k次遍历处理前array.length-k个数
            for(int i = 0; i < array.length - 1; i++){
                //依次比较相邻两个元素
                if(array[i] > array[i + 1]){
                    //交换
                    int temp = array[i];
                    array[i] = array[i + 1];
                    array[i + 1] = temp;

                    needNextPass = true;  //需要进行下次遍历
                }
            }
        }
    }

3、选择排序

动画演示:http://liveexample.pearsoncmg.com/dsanimation/SelectionSortNeweBook.html

思路

找数组中最小的数,并将其和第一个数交换;

然后从剩下的数中找最小的数,和第二个交换;

……一直进行下去,直到仅剩一个数           (是一个递归的过程)

代码:

//主程序初始时候执行 selectionSort(array,0, array.length - 1)

public static void selectionSort(double[] array, int low, int high){
        if(low < high){
            int indexOfMin = low;    //最小数下标
            double min = array[low]; //最小数
            //找到最小的数min和最小数下标indexOfMin
            for(int i = low + 1; i <= high; i++){
                if(array[i] < min){
                    min = array[i];
                    indexOfMin = i;
                }
            }
            //交换第low个元素与min
            array[indexOfMin] = array[low];
            array[low] = min;
            
            //递归
            selectionSort(array, low + 1, high);
        }
    }

4、插入排序

动画演示:http://liveexample.pearsoncmg.com/dsanimation/InsertionSortNeweBook.html

思路

重复的将新的元素插入一个排好序的子线性表中,直到整个线性表排好序。

[0,1,4,6,3]

我们要做的从a[1]开始,至于为什么不是a[0]。a[0]之前没有与a[0]进行比较的元素。我们插入a[1],这个时候我们需要遍历a[1]和a[1]之前的所有元素并进行比较。设置一个变量j,用来记录第一个 比 a[1]元素小的那个元素的下标,也就是a[1]要插入的位置,这个时候跳出循环,并且没发现一个比a[1]大的元素,就要令这个元素后移一位。依次类推的算法直到整个数组的最后一个。

代码:

public static void insertionSortt(int[] array){
        //从a[1]开始
        for(int i = 1; i < array.length; i++){
            int currentElement = array[i];
            int j; //标记元素要移动到的位置
            //先判断currentElement前面一个数,如果要移动,移动后再判断前面一个数,直到判断到不需要移动或已经判断到list[0]
            for(j = i - 1; j >=0 && array[j] > currentElement; j--){
                //将currentElement前面一个数向后移动一位
                array[j + 1] = array[j];
            }
            array[j + 1] = currentElement;
        }
    }

5、归并排序

动画演示:http://liveexample.pearsoncmg.com/dsanimation/MergeSortNeweBook.html

思想:

使用分而治之法对数组排序。将数组分为两半,对每部分递归地应用归并排序。在两部分都排好序后,对它们进行归并。

代码:

public static void mergeSort(int[] array) {
        if (array.length > 1) {
            // 创建临时数组firstHalf存放前面一半的元素
            int[] firstHalf = new int[array.length / 2];
            System.arraycopy(list, 0, firstHalf, 0, array.length / 2);
            // 递归
            mergeSort(firstHalf);

            // 创建临时数组secondHalf存放后面一半的元素
            int lengthOfSecondHalf = array.length - array.length / 2;
            int[] secondHalf = new int[lengthOfSecondHalf];
            System.arraycopy(array, array.length / 2, secondHalf, 0,
                    lengthOfSecondHalf);
            // 递归
            mergeSort(secondHalf);

            // 归并到原始数组array中
            merge(firstHalf, secondHalf, array);
        }
    }

    /** 归并 */
    public static void merge(int[] array1, int[] array2, int[] temp) {
        /*
         * 归并两个有序数组array1、array2为一个临时数组temp。
         * current1和current2指向array1和array2中要考虑的当前元素,重复比较array1和array2中的当前元素,并将较小的一个元素移动到temp中。
         * 如果较小元素在array1中,current1增加1;如果较小元素在array2中,current2增加1。
         * 最后array1或array2会剩余一个元素没有移动,将它直接复制到temp中。
         */
        int current1 = 0;// array1中要考虑的当前元素
        int current2 = 0;// array2中要考虑的当前元素
        int current3 = 0;// temp中要考虑的当前元素

        while (current1 < array1.length && current2 < array2.length) {
            // 如果较小元素在array1中,current1增加1
            if (array1[current1] < array2[current2])
                temp[current3++] = array1[current1++];
            // 如果较小元素在array2中,current2增加1
            else
                temp[current3++] = array2[current2++];
        }

        while (current1 < array1.length)
            temp[current3++] = array1[current1++];

        while (current2 < array2.length)
            temp[current3++] = array2[current2++];
    }

6、快速排序

动画演示:http://liveexample.pearsoncmg.com/dsanimation/QuickSortNeweBook.html

思想

在数组中选择一个基准元素(pivot),将数组分为两部分,使得第一部分中的所有元素都小于等于pivot,第二部分的所有元素都大于pivot。

对第一部分递归的应用快速排序算法,然后对第二部分递归的应用快速排序算法。

代码:

//主程序输入quickSort(array, 0, array.length - 1);开始执行

public static void quickSort(int[] array, int first, int last) {
        if(last > first){
            //将基准元素放置到正确的位置,获得基准元素下标
            int pivotIndex = partition(array, first, last);
            quickSort(array, 0, pivotIndex - 1);
            quickSort(array, pivotIndex + 1, last);
        }
    }
    /**将基准元素放置到正确的位置后返回基准元素下标*/
    public static int partition(int[] array, int first, int last) {
        //将数组第一个元素作为基准元素
        int pivot = array[first];
        //初始情况下,low指向子数组中第二个元素
        int low = first + 1;
        //初始情况下,high指向子数组中最后一个元素
        int high = last;
        
        while(high > low) {
            //从左侧开始查找第一个大于基准元素的元素,如果array[low] <= pivot,跳过,继续找下一个,即low++
            while(low <= high && array[low] <= pivot) {
                low++;
            }
            //从右侧开始查找第一个小于等于基准元素的元素,如果array[high] > pivot,跳过,继续找下一个,即high--
            while(low <= high && array[high] > pivot) {
                high--;
            }
            //找到后交换
            if(high > low){
                int temp = array[low];
                array[low] = list[high];
                array[high] = temp;
            }
        }
        //low<high时,查找结束,从右开始寻找第一个小于等于pivot,即小于等于list[first]的元素,找到后与基准元素交换
        while(high > first && array[high] > pivot){
            high--;
        }
        if(pivot > array[high]){
            array[first] = array[high];
            array[high] = pivot;
            return high;
        }else{
            return first;
        }
            
    }

猜你喜欢

转载自www.cnblogs.com/toria/p/sort.html
今日推荐