常用的排序算法-堆排、快排、归并

1、排序算法

1.1 快速排序

快排的时间复杂度是O(nlogn)
其实现思想就是随机找到一个中间值 小于这个值得放左边 大于这个值得放右边 
然后大于这个值得半部分和小于这个值得半部分分别递归
直到全部排完
实现代码:
    
```
    public class QuickSort {

        /**
         * 递归 进行排序
         * @param arr
         * @param left
         * @param right
         */
        public static void quickSort(int [] arr , int left, int right){
            //递归终止条件
            if (left < right){
                swap(arr,left + ((right - left ) >> 1),right);
                int [] p = partition(arr,left,right);
    
                //等于区域的左边界递归(小于区域所有值)
                quickSort(arr,left,p[0] -1);
    
                //等于区域的右边界递归(大于区域所有值)
                quickSort(arr,p[1]+1,right);
            }
        }
    
        /**
         * 划分数组的partition过程  时间复杂度为O(n)  返回的为等于区域的左右边界
         * @param arr
         * @param left
         * @param right
         * @return
         */
        private static int[] partition(int[] arr, int left, int right) {
    
            int less  = left - 1;
            int more = right;
            while (left < more){
                if (arr[left] < arr[right]){
                    swap(arr, ++less, left++);
                }else if (arr[left] > arr[right]){
                    swap(arr,--more, left);
                }else {
                    left++;
                }
            }
            swap(arr,more,right);
            return new int [] {less +1 ,more};
        }
    
    
        private static void swap(int[] arr, int j, int i) {
    
            int temp = arr[j];
            arr[j] = arr[i];
            arr[i] = temp;
        }
    
        public static void main(String[] args) {
            int[] arr = ArrayUtils.getArray(10,20);
            ArrayUtils.printArray(arr);
            quickSort(arr,0,arr.length -1);
            System.out.println();
            ArrayUtils.printArray(arr);
        }
    }
```

1.2 堆排

堆排就是建立一个抽象意义上的堆、算法上的堆是一个完全二叉树结构。
其底层是一个数组,一个节点的左孩子是 index * 2 + 1
右孩子是 index * 2 + 2
父亲节点是 (index - 1)/ 2
大根堆就是在以当前节点作为一个树的时候、此节点是整棵树中的最大值(小根堆反之)。
堆排序主要分为两步:
    1、建立一个堆,然后每次将堆顶的元素和最后一层的最后一个元素交换。
    2、然后将堆顶的元素进行下沉,直到以他为树的所有节点中只有他最大(小)。

堆排时间复杂度是严格意义上的O(nlogn) 空间复杂度是O(1)

    
```

    public class HeapSort {

        public static void heapSort(int [] arr){
            if (arr == null || arr.length < 2){
                return;
            }
            //建立大根堆 每个节点是整个子树中的最大值
            for (int i = 0 ; i < arr.length ; i++){
                heapInsert(arr,i);
            }
            int size = arr.length;
            swap(arr,0,--size);
            while (size > 0){
                heapify(arr,0,size);
                swap(arr,0,--size);
            }
        }
    
        /**
         * 下沉的过程
         * @param arr
         * @param index
         * @param size
         */
        private static void heapify(int[] arr, int index, int size) {
            int left = index * 2 +1;
            while (left < size){
    
                //如果左右孩子都存在 选最大的  作为largest
                int largest = left + 1 < size && arr[left + 1] > arr[left] ? left +1 : left;
                //largest变为 自己和左右孩子中最大的值
                largest = arr[largest] > arr[index] ? largest : index;
                if (largest == index){
                    break;
                }
                swap(arr,largest,index);
                index = largest;
                left = index * 2 +1;
            }
    
        }
    
        /**
         * 从index位置开始进行与父节点的比较 直到不比父节点大 或者到0的位置停止
         * @param arr
         * @param index
         */
        private static void heapInsert(int[] arr, int index) {
    
            while (arr[index] > arr[(index - 1 ) / 2]){
                swap(arr,index,(index -1 ) / 2 );
                index = (index -1 ) / 2;
    
            }
        }
    
    
    
        private static void swap(int[] arr, int j, int i) {
    
            int temp = arr[j];
            arr[j] = arr[i];
            arr[i] = temp;
        }
    
        public static void main(String[] args) {
            int[] arr = ArrayUtils.getArray(10,20);
            ArrayUtils.printArray(arr);
            heapSort(arr);
            System.out.println();
            ArrayUtils.printArray(arr);
        }

}

```

1.3 归并排序

归并排序就是将数组递归的两两划分、然后再合并的过程 在合并的过程中排好序
递的过程就是将数组从中间分成两半、直到数组大小为1,
归的过程就是讲两部分合成成一个部分,合成的过程中排好序
时间复杂度O(nlogn)


```
    public class MergeSort {

        public static void mergeSort(int[] arr) {
            if (arr.length < 2 || arr == null) {
                return;
            }
            mergeSort(arr, 0, arr.length - 1);
    
        }
    
        private static void mergeSort(int[] arr, int left, int right) {
    
            if (left == right) {
                return;
            }
            //left 和right的中间位置
            int mid = left + ((right - left) >>> 1);
            //左半部分递归
            mergeSort(arr, left, mid);
            //右半部分递归
            mergeSort(arr, mid + 1, right);
            //最后再合并
            merge(arr, left, mid, right);
    
        }
    
        /**
         * 合并 l 到 r上以 mid 为划分点的两部分的元素
         *
         * @param arr
         * @param left
         * @param mid
         * @param right
         */
        private static void merge(int[] arr, int left, int mid, int right) {
            int[] help = new int[right - left + 1];
            int i = 0;
            int leftPoint = left;
            int rightPoint = mid + 1;
            while (leftPoint <= mid && rightPoint <= right) {
                help[i++] = arr[leftPoint] < arr[rightPoint] ? arr[leftPoint++] : arr[rightPoint++];
            }
            while (leftPoint <= mid) {
                help[i++] = arr[leftPoint++];
            }
            while (rightPoint <= right) {
                help[i++] = arr[rightPoint++];
            }
            //将数组拷贝回原数组
            for (i = 0; i < help.length; i++) {
                arr[left + i] = help[i];
            }
        }
    
        public static void main(String[] args) {
            int[] arr = ArrayUtils.getArray(10, 20);
            ArrayUtils.printArray(arr);
            mergeSort(arr, 0, arr.length - 1);
            System.out.println();
            ArrayUtils.printArray(arr);
        }
}
```
posted @ 2019-02-21 20:52  evildoerDb  阅读(177)  评论(0编辑  收藏  举报