Seven comparison-based sorting algorithms (JAVA)

Table of contents

Bubble Sort

optimization:

Heap sort

insertion sort

Hill sort

merge sort

Quick sort

optimization

selection sort 


 Stability of the sorting algorithm : If elements of the same size have the same relative position before and after sorting, it is called a stable sorting.

Note: A sorting that is inherently stable can be implemented as an unstable sorting; but conversely, a sorting that is inherently unstable cannot be implemented as a stable sorting.

Stable sorting algorithm : insertion sort, bubble sort, merge sort

Bubble Sort

Time complexity: o(n^2) If optimization is added, the best case is O(N)
Space complexity: O(1)
Stability: Stable

    public static void bubbleSort(int[] array){

        for (int i = 0; i < array.length-1; i++) {
            for (int j = 0; j < array.length-1; j++) {
                if (array[j] > array[j+1]) {
                    swap(array, j, j+1);
                }
            }
        }
    }

    private static void swap(int[] array, int minIndex, int i) {
        int tmp = array[i];
        array[i] = array[minIndex];
        array[minIndex] = tmp;
    }

optimization:

     public static void bubbleSort(int[] array) {
        for (int i = 0; i < array.length-1; i++) {
            boolean flg = false;
            for (int j = 0; j < array.length-1-i; j++) {
                if(array[j] > array[j+1]) {
                    swap(array,j,j+1);
                    flg = true;
                }
            }
            if(!flg) {
                return;
            }
        }
    }

Heap sort

Time complexity: O(n*logN) N^1.3 -->
Space complexity: O(1)
Stability: Unstable
When the amount of data is very large, heap sorting must be faster than Hill's heap

sorting principle:

  1. Swapping the top element of a large root heap with the last element
  2. Decrease the length of an array by one
  3. After re-adjusting the heap into a large root heap

    public static void heapSort(int[] array){

        createHeap(array);
        for (int i = 0; i < array.length - 1; i++) {
            swap(array, 0, array.length-1-i);
            shiftDown(array, 0, array.length-1-i);
        }
    }

    private static void createHeap(int[] array) {
        for (int i = (array.length-1-1)/2; i >= 0; i--) {
            shiftDown(array, i, array.length);
        }
    }

    private static void shiftDown(int[] array, int i, int length) {//length个元素
        int child = i * 2 + 1;
        while (child < length) {
            if (child + 1 < length && array[child] < array[child+1]) {
                child++;
            }
            if (array[child] > array[i]) {
                swap(array, child, i);
                i = child;
            }else {
                break;
            }
            child = i * 2 + 1;
        }
    }
    private static void swap(int[] array, int minIndex, int i) {
        int tmp = array[i];
        array[i] = array[minIndex];
        array[minIndex] = tmp;
    }

insertion sort

Time complexity:
        Best case: O(N) when the data is completely ordered
        Worst case: O(N^2) when the data is completely in reverse order
Space complexity: O(1)
Stability: Stable


The principle of insertion sort

  1. Make them key codes one by one starting from the first one on the left
  2. From left to right, insert the records to be sorted into the sorted sequence on the left one by one according to the size of their key values.
  3. Until all records are inserted, a new ordered sequence is obtained
    public static void insertSort(int[] array){

        for (int i = 1; i < array.length; i++) {
            int tmp = array[i];
            int j = i - 1;
            for (; j >= 0 ; j--) {
                //如果此处改为array[j] >= tmp就会变成不稳定排序
                if (array[j] > tmp) {
                    array[j+1] = array[j];
                }else{
                    break;
                }
            }
            array[j+1] = tmp;
        }
    }

Hill sort

Time complexity:
             approximately equal to: n^1.3 - n^1.5
Complexity: O(1)
Stability: unstable

Hill sorting is actually an optimization of insertion sorting

Fundamental:

  1. First divide the array into several groups according to the step size
  2. Insertion sort for each group
  3. Reduce the step size and repeat the above steps

    public static void shellSort(int[] array){

        int gap = array.length;
        while (gap > 1) {
            gap = gap / 2;
            shell(array, gap);
        }
    }

    private static void shell(int[] array, int gap) {
        for (int i = gap; i < array.length; i++) {
            int tmp = array[i];
            int j = i-gap;
            for (; j >= 0; j -= gap) {
                if (array[j] > tmp) {
                    array[j+gap] = array[j];
                }else {
                    break;
                }
            }
            array[j+gap] = tmp;
        }
    }

merge sort

Time complexity: 0(N*logN)
Space complexity: O(n)
Stability: Stable

Merge sort is an effective sorting algorithm based on merge operations. This algorithm is a very typical application of the divide-and-conquer method. Merge the already ordered subsequences to obtain a completely ordered sequence; that is, first make each subsequence orderly, and then make the subsequence segments orderly.

Please refer to: icon-default.png?t=N7T8http://t.csdnimg.cn/Yd62c

    public void mergerSort(int[] nums, int left, int right) {//right:数组长度减一
        if (left >= right) {
            return;
        }
        int mid = (left + right) / 2;
        mergerSort(nums, left, mid);
        mergerSort(nums, mid + 1, right);
        merger(nums, left, mid, right);
    }

    private void merger(int[] nums, int left, int mid, int right) {
        int[] tmp = new int[right-left+1];
        int i = 0;
        int l = left;
        int r = mid + 1;
        while (l <= mid && r <= right) {
            if (nums[l] < nums[r]) {
                tmp[i++] = nums[l++];
            }else {
                tmp[i++] = nums[r++];
            }
        }
        while (l <= mid) {
            tmp[i++] = nums[l++];
        }
        while (r <= right) {
            tmp[i++] = nums[r++];
        }
        i = 0;
        for (int j = 0; j < tmp.length; j++) {
            nums[left++] = tmp[j];
        }
    }

Quick sort

Time complexity:
        Best case: O(N*logN) full binary tree/complete binary tree
        Worst case: O(N^2) single-branch tree
Space complexity:
        Best case: O(logN) full binary tree/complete binary tree
        Worst case: O(N) single-branch tree
Stability: unstable

Basic principles of quick sort

  1. Take any element in the sequence of elements to be sorted as the base value
  2. Divide the set to be sorted into two subsequences according to this sorting code. All elements in the left subsequence are less than the reference value, and all elements in the right subsequence are greater than the reference value.
  3. Repeat this process for each subsequence until all elements are arranged in the corresponding position

There are the Hoare method, the digging method, and the front and rear pointer method.
Here we only introduce the Hoare method .

    public static void quickSort(int[] array){

        quick(array, 0, array.length-1);
    }

    private static void quick(int[] array, int left, int right) {
        if (left >= right) {
            return;
        }
        int Index = findSwap(array, left, right);
        quick(array, left, Index-1);
        quick(array, Index+1, right);

    }
    
    private static int findSwap(int[] array, int left, int right) {
        int key = array[left];
        int keyIndex = left;
        while (left < right) {
            //必须right先走
            //如果是left先走,两个相遇的地方一定比key大
            while (left < right && array[right] >= key) {
                right--;
            }
            while (left < right && array[left] <= key) {
                left++;
            }
            swap(array, right, left);
        }
        if (left == right) {
            swap(array, keyIndex, left);
        }
        return left;
    }

    private static void swap(int[] array, int minIndex, int i) {
        int tmp = array[i];
        array[i] = array[minIndex];
        array[minIndex] = tmp;
    }

optimization

Use the three-number method to avoid the formation of branch books (try to reduce the height of the tree)

    public int[] sortArray(int[] nums) {
        //快速排序
        quickSort(nums, 0, nums.length-1);
        return nums;
    }

    private void quickSort(int[] nums, int left, int right) {
        if (left >= right) {
            return;
        }
        //三数取中法
        swap(nums, left, threeNumMid(nums, left, right));
        //也可以在这里加一个判断当左右之间的数据个数小于一定值然后调用插入排序
        //因为在排序过程中数组会趋近于有序所以插入排序的效率会很快
        int pivot = quick(nums, left, right);
        quickSort(nums, left, pivot-1);
        quickSort(nums, pivot+1, right);
    }

    private int threeNumMid(int[] nums, int left, int right) {
        int mid = (left + right) / 2;
        if (nums[left] > nums[right]) {
            if (nums[mid] > nums[left]) {
                return left;
            }else if (nums[mid] < nums[right]) {
                return right;
            }else {
                return mid;
            }
        }else {
            if (nums[mid] < nums[left]) {
                return left;
            }else if (nums[mid] > nums[right]) {
                return right;
            }else {
                return mid;
            }
        }
    }

    private int quick(int[] nums, int left, int right) {
        int index = left;
        int key = nums[left];
        while (left < right) {
            while (left < right && nums[right] >= key) {
                right--;
            }
            while (left < right && nums[left] <= key) {
                left++;
            }
            swap(nums, right, left);
        }
        swap(nums, index, left);
        return left;
    }

    private void swap(int[] nums, int left, int right) {
        int tmp = nums[left];
        nums[left] = nums[right];
        nums[right] = tmp;
    }

selection sort 

Time complexity: O(n^2)
Space complexity: O(1)
Stability: unstable sorting

Basic principles of selection sorting:

  1. Select the smallest (or largest) element from the data elements to be sorted each time from left to right.
  2. Place it at the beginning of the elements to be sorted and at the end of the ordered elements
  3. Repeat the above steps until all data elements to be sorted are arranged.
    public static void selectSort(int[] array){

        for (int i = 0; i < array.length; i++) {
            int minIndex = i;
            for (int j = i+1; j < array.length; j++) {
                if (array[minIndex] > array[j]) {
                    minIndex = j;
                }
            }
            swap(array, minIndex, i);
        }
    }

    private static void swap(int[] array, int minIndex, int i) {
        int tmp = array[i];
        array[i] = array[minIndex];
        array[minIndex] = tmp;
    }

Guess you like

Origin blog.csdn.net/2302_76339343/article/details/133498231