Summary of Sorting Algorithms

Here are ten well-known algorithms, with their own understanding and code.
- Bubble Sort
- Selection Sort
- Insertion Sort
- Hill Sort
- Merge Sort
- Quick Sort
- Heap Sort
- Count Sort
- Bucket Sort
- Radix Sort

Inspiration and pictures from Top 10 Classic Sorting Algorithms (Animation Demonstration)

Let’s first understand two concepts: time complexity and space complexity.
They are opposite to each other. The reduction of time complexity must be accompanied by the increase of space complexity, so the choice of algorithm is also a trade-off between time and space.


Bubble Sort

Understanding: From left to right, judge whether the current bubble is larger than the next one, and move the big bubble to the right.
The inner loop, which moves the larger bubble backwards, ensures that the current value of the inner loop is greater than all previous values. (The process of bubbling, moving step by step)
For the first time in the outer loop, the maximum value in the array is scanned and exchanged to the end of the array one by one.
The second time of the outer loop, scan out the sub-maximum value in the array and swap to the sub-end of the array one by one.

    public String sort(int[] numbers) {

        long stamp = System.currentTimeMillis();

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

        return Utils.intsToString(numbers) + "   cost:" + (System.currentTimeMillis() - stamp);

    }

Time and space complexity: O(n 2 ), O(0) (depending on which swap method Utils.swap(numbers, j, j + 1) is)

selection sort


Comprehension: In the unsorted part, each time a minimal swap is chosen to the unsorted head item.

    public String sort(int[] numbers) {

        long stamp = System.currentTimeMillis();

        for (int i = 0; i < numbers.length - 1; i++) {
            int position=i;
            for (int j = i + 1; j < numbers.length; j++) {
                if (numbers[j]<numbers[position]){
                    position=j;
                }
            }
            Utils.swap(numbers,i,position);
        }
        return Utils.intsToString(numbers) + "   cost:" + (System.currentTimeMillis() - stamp);

    }

Time and space complexity: O(n 2 ), O(0)

*Crappy selection sort

Before writing this article, I had been using this sort:

        for (int i = 0; i < numbers.length - 1; i++) {
            for (int j = i + 1; j < numbers.length; j++) {
                if (numbers[j] < numbers[i]) {
                    Utils.swap(numbers, i, j);//正规的是记录最小位置
                }
            }
            //在内循环完成后再交换,这样可以减少交换次数
        }

Very similar, but this sort weakens the function of selection and increases the number of exchanges.

Insertion sort


Understanding: select an item, if it is less than the previous item, move the previous item back, and the operation reciprocates until the previous item is less than it, and place the selected item at the current position (the current position item has been moved back)

    public String sort(int[] numbers) {

        long stamp = System.currentTimeMillis();

        for (int i = 1; i < numbers.length; i++) {

            int prePosition = i - 1;
            int current = numbers[i];
            while (prePosition >= 0 && current < numbers[prePosition]) {
                numbers[prePosition + 1] = numbers[prePosition];
                prePosition--;
            }
            numbers[prePosition + 1] = current;
        }

        return Utils.intsToString(numbers) + "   cost:" + (System.currentTimeMillis() - stamp);

    }

Time and space complexity: O(n 2 ), O(1)

Hill sort

Understanding:
set an interval gap, sort the new array formed by gap;
set a decreasing rule for gap until 1;
perform the first step after each gap change;

    public String sort(int[] data) {

        long stamp = System.currentTimeMillis();

        for (int gap = data.length / 2; gap > 0; gap /= 2) {
            for (int i = gap; i < data.length; i++) {
                int temp = data[i];
                int j;
                for (j = i - gap; j >= 0; j -= gap) {
                    if (temp < data[j]) {
                        data[j + gap] = data[j];//交换的话会有很多次
                    } else {
                        break;//之前的已经排好序了,继续循环也没意义
                    }
                }
                data[j + gap] = temp;
            }
        }

        return Utils.intsToString(data) + "   cost:" + (System.currentTimeMillis() - stamp);

    }

Time and space complexity: O(n 2 ), O(1) The three-layer for is not a power of 3, because each layer of for is not all n

merge sort


Understanding: Cut the middle of the array until it is uncut, and then merge it according to the size of each doubling rule (1-1, 2-2, 4-4, 8-8). The last merge into a sorted array.

    private int[] mergeSort(int[] numbers) {
        int len = numbers.length;
        if (len < 2) {
            return numbers;
        }
        int middle = len / 2;
        int[] left = new int[middle];
        int[] right = new int[len - middle];

        System.arraycopy(numbers, 0, left, 0, middle);
        System.arraycopy(numbers, middle, right, 0, numbers.length - middle);

        return merge(mergeSort(left), mergeSort(right));
    }

    private int[] merge(int[] left, int[] right) {
        int[] result = new int[left.length + right.length];

        int leftP = 0;
        int rightP = 0;
        int resultP = 0;

        while (leftP < left.length && rightP < right.length) {
            if (left[leftP] > right[rightP]) {
                result[resultP++] = right[rightP++];
            } else if (left[leftP] < right[rightP]) {
                result[resultP++] = left[leftP++];
            } else {
                result[resultP++] = left[leftP++];
                result[resultP++] = right[rightP++];
            }
        }


        while (leftP < left.length) {
            result[resultP++] = left[leftP++];
        }

        while (rightP < right.length) {
            result[resultP++] = right[rightP++];
        }

        return result;
    }

Time and space complexity: O(nlog 2 n), O(n)

quick sort

Understanding: Select a reference value and find the sorted position in the array where the reference value is located. The reference value is selected in a loop until all the values ​​in the array serve as reference values, and the array sorting is completed.

    private void quickSort(int[] numbers, int left, int right) {
        int partitionIndex;

        if (left < right) {
            partitionIndex = partition(numbers, left, right);
            quickSort(numbers, left, partitionIndex - 1);
            quickSort(numbers, partitionIndex + 1, right);
        }
    }

    private int partition(int[] numbers, int left, int right) {
        int pivot = left;
        int index = pivot + 1;
        for (int i = index; i <= right; i++) {
            if (numbers[i] < numbers[pivot]) {
                Utils.swap(numbers, i, index++);
            }
        }

        Utils.swap(numbers, pivot, index - 1);
        return index - 1;
    }

Time and space complexity: O(n 2 ), O(nlog 2 n) (nlog 2 n is a temporary variable generated during exchange, and the space complexity can be reduced by adding and subtracting exchange)

heap sort

prior knowledge

heap

A complete binary tree whose non-leaf nodes must be greater than (or less than) its leaf nodes

Large bank

A non-leaf node larger than its leaf node is called a big top heap

small top pile

A non-leaf node smaller than its leaf node is called a small top heap

Understanding: Using the characteristics of the large top heap, the nodes of the upper layer must be larger than the nodes of the next layer.
Take the root node (maximum value) and exchange it with the last leaf node, and reorder the remaining nodes according to the nature of the big top heap. Repeat this operation to get a sorted array from small to large.

    public String sort(int[] numbers) {

        long stamp = System.currentTimeMillis();

        len=numbers.length;
        for (int i = numbers.length / 2; i >= 0; i--) {//生成大顶堆
            adjustHeap(numbers, i);
        }

        for (int i = numbers.length-1; i >=0 ; i--) {
            Utils.swap(numbers,0,i);
            len--;
            adjustHeap(numbers,0);
        }


        return Utils.intsToString(numbers) + "   cost:" + (System.currentTimeMillis() - stamp);

    }

    int len;

    private void adjustHeap(int[] numbers, int p) {

        int left = p * 2 + 1;
        int right = p * 2 + 2;
        int bigP = p;

        if (left < len && numbers[left] > numbers[bigP]) {
            bigP = left;
        }

        if (right < len && numbers[right] > numbers[bigP]) {
            bigP = right;
        }

        if (p != bigP) {
            Utils.swap(numbers, p, bigP);
            adjustHeap(numbers, bigP);
        }

    }

Time and space complexity: O(nlog 2 n), O(0) determined by the exchange method

count sort

Understand: Counting sort is suitable for collections with dense data ranges.
Create a temporary array (data range) to store data, the subscript of the temporary array represents the data value, and the value of the temporary array represents the number of times the data appears. After all the data is placed in the temporary array according to the rules, all the data is taken out according to the subscript of the temporary array, that is, the sorted array.

    public String sort(int[] numbers) {

        long stamp = System.currentTimeMillis();

        int[] result = new int[numbers.length];
        int max = numbers[0], min = numbers[0];
        for (int number : numbers) {
            if (number > max) {
                max = number;
            }
            if (number < min) {
                min = number;
            }
        }

        int[] temp = new int[max - min + 1];

        for (int i = 0; i < numbers.length; i++) {

            temp[numbers[i] - min]++;

        }

        int p=0;
        for (int i = 0; i <temp.length ; i++) {
            while (temp[i]>0){
                result[p++]=i+min;
                temp[i]--;
            }
        }


        return Utils.intsToString(result) + "   cost:" + (System.currentTimeMillis() - stamp);

    }

Time and space complexity: O(n+k), O(n+k) k represents the size of the range array

bucket sort

Understanding: Counting sorting is a special case of bucket sorting. The data in each bucket in counting sorting is the same. When sorting, you only need to pour out the order of the buckets to get a sorted array; and bucket sorting each The data in the buckets are not the same, you need to sort the data in the buckets, and then pour them out in the order of the buckets to get a sorted array;

    public String sort(int[] numbers) {

        long stamp = System.currentTimeMillis();

        int max = numbers[0];
        int min = numbers[0];

        for (int number : numbers) {
            if (number > max) {
                max = number;
            }

            if (number < min) {
                min = number;
            }
        }

        int bucketNum = (max - min) / numbers.length + 1;
        ArrayList<ArrayList<Integer>> buckets = new ArrayList<ArrayList<Integer>>();

        for (int i = 0; i < bucketNum; i++) {
            buckets.add(new ArrayList<Integer>());
        }

        for (int i = 0; i < numbers.length; i++) {
            int p = (numbers[i] - min) / numbers.length;
            buckets.get(p).add(numbers[i]);
        }

        for (int i = 0; i < buckets.size(); i++) {
            Collections.sort(buckets.get(i));
        }

        return buckets.toString() + "   cost:" + (System.currentTimeMillis() - stamp);

    }

Time and space complexity: O(n), O(n)

radix sort

Understanding: All numbers are composed of 0-9, and the comparison of size is also the comparison of the number of digits and the number on each bit.
Sort the array by the one-digit size first, then by the tens-digit size, increasing the number of digits until the number of digits of the largest item in the array.

    public String sort(int[] numbers) {

        long stamp = System.currentTimeMillis();

        ArrayList<ArrayList<Integer>> temp = new ArrayList<ArrayList<Integer>>();
        int max = numbers[0];
        int radix = 10;

        for (int i = 0; i < 10; i++) {
            temp.add(i, new ArrayList<Integer>());
        }


        do {
            for (int i = 0; i < numbers.length; i++) {
                if (numbers[i] > max) {
                    max = numbers[i];
                }
                temp.get(numbers[i] % radix / (radix / 10)).add(numbers[i]);
            }

            int p = 0;

            for (int i = 0; i < temp.size(); i++) {
                for (int j = 0; j < temp.get(i).size(); j++) {
                    numbers[p++] = temp.get(i).get(j);
                }
                temp.get(i).clear();
            }
            radix *= 10;
        } while (radix < max * 10);

        return Utils.intsToString(numbers) + "   cost:" + (System.currentTimeMillis() - stamp);

    }

Time and space complexity: O(nk), O(n+k) Some say that the space complexity is O(n), which is the limit for n


In addition, there is a company's computer problem: sort the number of occurrences of char in String, and the same number of times are sorted by dictionary.
This question will not be written. The code for this question and the above ten sorting algorithms are on GitHub

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325994069&siteId=291194637