排序算法总结

亡梦爱人 提交于 2019-12-10 19:59:39

冒泡排序

public void sort(int[] nums) {
        int i, j, min, t;

        for(i = 0; i < nums.length; i++){
            min = i;
            for(j = i + 1; j < nums.length; j++){
                if(nums[j] < nums[min]){
                    min = j;
                }
            }
            t = nums[min];
            nums[min] = nums[i];
            nums[i] = t;
        }
    }

无论最好还是最坏情况下时间复杂度都是O(N2)O(N^2),是一种比较低效率的排序方法。

选择排序

插入排序

归并排序

归并排序的思路是一半一半排序,假设左右两边都已经是有序的了,那么再按大小顺序插入一个新的数组里即可,需要 NN 次操作,而利用递归来使左右两边达到有序需要 log2nlog_2n 次,因此总的时间复杂度是 O(NlogN)O(NlogN),又因为需要一个辅助的数组,空间复杂度是 O(N)O(N)

public void mergeSort(int[] nums) {
        int[] help;

        help = new int[nums.length];
        mergeSortHelper(nums, help, 0, nums.length);
    }

    private void mergeSortHelper(int[] nums, int[] help, int start, int end) {
        int i, j, k, mid;

        if(start + 1 == end)
            return;
        mid= (start + end) / 2;
        mergeSortHelper(nums, help, start, mid);
        mergeSortHelper(nums, help, mid, end);
        i = start;
        j = mid;
        k = start;
        while(i < mid && j < end){
            if(nums[i] < nums[j]){
                help[k++] = nums[i];
                i++;
            }else {
                help[k++] = nums[j];
                j++;
            }
        }
        while(i < mid){
            help[k++] = nums[i++];
        }
        while(j < end){
            help[k++] = nums[j++];
        }
        for(k = start; k < end; k++){
            nums[k] = help[k];
        }
    }

快速排序

快排的大致思路是找到一个中间数,使这个数左边的都小于等于它,右边的数都大于等于它,然后接着递归处理两边的部分。
快排的时间复杂度和原数组里的顺序有关,平均复杂度为 O(NlogN)O(NlogN),当原数组是有序的时候,时间复杂度达到最差,为O(N2)O(N^2)

public void quickSort(int[] nums) {
        quickSortHelper(nums,0, nums.length);
    }

    private void quickSortHelper(int[] nums, int start, int end) {
        int i, j, m, t;

        i = start;
        j = end - 1;
        while(i < j){
            m = i;
            while(i < j && nums[j] >= nums[m]){
                j--;
            }
            while(i < j && nums[i] <= nums[m]){
                i++;
            }
            t = nums[m];
            nums[m] = nums[j];
            nums[j] = nums[i];
            nums[i] = t;
        }
        if(start < i)
            quickSortHelper(nums, start, i);
        if(i < end)
            quickSortHelper(nums, i + 1, end);
    }

堆排序

由于大顶堆具有堆顶是最大值的性质,因此可以根据堆的插入(向上重排)和删除(向下重排)来进行排序。
堆的插入和删除都涉及到堆的重排,时间复杂度是 O(logN)O(logN),需要 NN 次,因此时间复杂度是 O(NlogN)O(NlogN)

public void heapSort(int[] nums) {
        int i, j, t, next;

        //大顶堆
        for(i = 1; i < nums.length; i++){
            next = i;
            //向上重排
            while(next != 0){
                j = (next - 1) / 2;
                if(nums[next] > nums[j]){
                    t = nums[next];
                    nums[next] = nums[j];
                    nums[j] = t;
                    next = j;
                }else {
                    break;
                }
            }
        }
        //排序
        for(i = nums.length - 1; i > 0; i--){
            t = nums[i];
            nums[i] = nums[0];
            nums[0] = t;
            //向下重排
            next = 0;
            while(next < i){
                j = 2 * next + 1;
                if(j + 1 < i){
                    j += nums[j] > nums[j+1] ? 0 : 1;
                }
                if(j < i){
                    t = nums[j];
                    nums[j] = nums[next];
                    nums[next] = t;
                }
                next = j;
            }
        }
    }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!