Java implements commonly used sorting algorithms (quick sort, merge sort, radix sort)

Common Sorting Algorithms

insert image description here

quick sort

1 Introduction

Quicksort is a sorting algorithm developed by Tony Hall. On average, sorting n items requires O(nlogn) comparisons. In the worst case, Ο(n2) comparisons are required, but this is not common. In fact, quicksort is usually significantly faster than other Ο(nlogn) algorithms because its inner loop can be implemented efficiently on most architectures.

Quicksort uses a divide and conquer strategy to divide a list into two sub-lists.

Quick sort is another typical application of the idea of ​​divide and conquer in sorting algorithms. In essence, quick sort should be regarded as a recursive divide and conquer method based on bubble sort.

The name of Quick Sort is simple and rude, because as soon as you hear the name, you know the meaning of its existence, which is fast and efficient! It is one of the fastest sorting algorithms for big data. Although the time complexity of Worst Case reaches O(n²), they are excellent, and in most cases, they perform better than sorting algorithms with an average time complexity of O(n logn).

The worst running case of quick sort is O(n²), such as quick sort of sequential arrays. But its amortized expected time is O(nlogn), and the constant factor implied in the O(nlogn) notation is small, which is much smaller than the merge sort whose complexity is stable at O(nlogn). Therefore, for the vast majority of random number sequences with weaker order, quick sort is always better than merge sort.

2. Thinking analysis

The quick sorting algorithm implements sorting through multiple comparisons and exchanges, and its sorting process is as follows:
(1) First, set a cutoff value, and divide the array into left and right parts through the cutoff value.
(2) Collect the data greater than or equal to the cutoff value to the right of the array, and collect the data smaller than the cutoff value to the left of the array. At this time, each element in the left part is less than the cutoff value, and each element in the right part is greater than or equal to the cutoff value.
(3) Then, the left and right data can be sorted independently. For the array data on the left side, a boundary value can be taken to divide this part of the data into left and right parts, and the smaller value is placed on the left side, and the larger value is placed on the right side. The array data on the right can also be processed similarly.
(4) Repeat the above process, it can be seen that this is a recursive definition. After sorting the left part by recursion, recursively sort the order of the right part. When the sorting of the data in the left and right parts is completed, the sorting of the entire array is also completed.

3. Diagram

3.1 start

Start from both ends of the arr array respectivelydetection. First find a number less than 8 from right to left, then find a number greater than 8 from left to right, and then exchange them. Here you can use two variables L (left) and R (right), which point to the leftmost and rightmost of the sequence respectively. At the beginning let L point to the far left of the array, pointing to the number 8. Let R point to the far right of the array, pointing to the number 11.
insert image description here

3.2 Encounter a number smaller than the benchmark from right to left

insert image description here

3.3 Stop on the right, look for a number greater than the benchmark from left to right

insert image description here

3.4 Exchange the numbers corresponding to L and R

insert image description here

after exchange
insert image description here

3.5 Continuation of the above method

First R starts to dispatch. Because the base number set here is the leftmost number, it is very important to let R go first (please think for yourself why). The sentinel R moves to the left step by step (that is, R–-) until it finds a number less than 8 and stops. Next, the sentinel L moves to the right step by step (ie L++) until it finds a number greater than 8 and stops.

exchange
insert image description here

after exchange

insert image description here

At this time R continues to move to the left
insert image description here

Then L moves
insert image description here

When L == R, it means that this position is the position of 8, exchange
insert image description here

get:

insert image description here
This concludes the first round of detection. At this time, the reference number 8 is used as the dividing point, the numbers to the left of 8 are all less than or equal to 8, and the numbers to the right of 8 are all greater than or equal to 8. Looking back at the process just now, in fact, the mission of R is to find a number smaller than the benchmark number, and the mission of L is to find a number greater than the benchmark number until L and R meet.

3.6 Handling the numbers on the left

insert image description here

3.7 Processing the numbers on the right

insert image description here

get:
insert image description here

4. Code implementation

/**
 * 快速排序
 * @author 尹稳健~
 * @version 1.0
 * @time 2022/9/10
 */
public class QuickSort {
    
    
    public static void main(String[] args) {
    
    
        int[] arr = {
    
    8, 12, 19, -1, 45, 0, 14, 4, 11};
        quickSort(arr,0,arr.length-1);
        for (int i = 0; i < arr.length; i++) {
    
    
            System.out.print(arr[i]+" ");
        }
    }
    public static void quickSort(int[] arr,int start, int end){
    
    
        // 什么时候结束排序?
        if (start>end){
    
    
            return;
        }
        // 左指针
        int L = start;
        // 右指针
        int R = end;
        // 基准
        int pivot = arr[start];
        // 只要L!=R就继续循环
        while (L < R){
    
    
            // 右边大于基准,从右向左移动
            while (L<R && arr[R] >= pivot){
    
    
                R --;
            }
            // 左边小于基准,从左向右移动
            while (L<R&& arr[L] <= pivot){
    
    
                L ++;
            }
            // 说明右边有小于基准的数,左边有大于基准的数,交换
            if (L<R){
    
    
                int temp = arr[L];
                arr[L] = arr[R];
                arr[R] = temp;
            }
        }
        // L 与 R碰面 找到了 基准的位置
        arr[start] = arr[L];
        arr[L] = pivot;

        // 左边排序
        quickSort(arr,start,R-1);
        // 右边排序
        quickSort(arr,L+1,end);

    }

}

Quick sort This article is well written, you can refer to other people's quick sort writing and understanding


merge sort

1 Introduction

Merge sort is an effective and stable sorting algorithm based on the merge operation. This algorithm is a very typical application of divide and conquer (Divide and Conquer). Combine the ordered subsequences to obtain a completely ordered sequence; that is, first make each subsequence in order, and then make the subsequence segments in order. Merging two sorted lists into one sorted list is called a two-way merge.

2. Thinking analysis

Merge sort uses the idea of ​​​​divide and conquer, and the difficulty is to rule

  • Apply for space so that its size is the sum of the two sorted sequences, which is used to store the merged sequence
  • first of alldecomposition sequence, decomposing the sequence into the sequences in each groupQuantity is 1, and then perform a merge sort
  • set uptwo pointers, the initial positions are the starting positions of the two sorted sequences
  • Compare the elements pointed by the two pointers, select the relatively small element and put it into the merge space, and move the pointer to the next position
  • Repeat the previous step until a certain pointer reaches the end of the sequence
  • Copy all remaining elements of another sequence directly to the end of the merged sequence

3. Diagram

3.1 Split, decompose all sequences

insert image description here

3.2 Start sorting and merging

insert image description here

After each filling, the pointer moves one bit
insert image description here

insert image description here

When the left array has no elements, the right is directly filled in
insert image description here

get
insert image description here

4. Code implementation

/**
 * 归并排序
 * @author 尹稳健~
 * @version 1.0
 * @time 2022/9/12
 */
public class MergeSort {
    
    
    public static void main(String[] args) {
    
    
        int[] arr = {
    
    1, 5, 6, 3, 2, 8, 7, 4};
        int[] temp = new int[arr.length];
        mergeSort(arr,0,arr.length-1,temp);
        for (int i = 0; i < arr.length; i++) {
    
    
            System.out.print(arr[i]+" ");
        }
    }

    /** 分解,并合并排序 */
    public static void mergeSort(int[] arr,int left ,int right,int[] temp){
    
    
        if (left<right){
    
    
            //中间索引
            int mid = (left+right)/2;
            //向左递归分解
            mergeSort(arr,left,mid,temp);
            //向右递归分解
            mergeSort(arr,mid+1,right,temp);
            //合并
            merge(arr,left,mid,right,temp);
        }
    }

    /**
     * 合并排序
     * @param arr   未排序的数组
     * @param left  左边有序子数组的初始索引
     * @param mid   中间索引
     * @param right 右边最大索引
     * @param temp  临时数组
     */
    public static void merge(int[] arr,int left,int mid,int right,int[] temp){
    
    
        // 左边指针索引
        int leftPoint = left;
        // 右边指针索引
        int rightPoint = mid+1;
        // 临时数据的指针
        int tempLeft = 0;

        // 两个序列都不为空时
        while (leftPoint <= mid && rightPoint <= right){
    
    
            //如果第一个序列的元素小于第二序列的元素,就将其放入temp中
            if (arr[leftPoint] <= arr[rightPoint]){
    
    
                temp[tempLeft] = arr[leftPoint];
                leftPoint++;
                tempLeft ++;
            }else{
    
    
                temp[tempLeft] = arr[rightPoint];
                rightPoint++;
                tempLeft ++;
            }
        }

        // 右序列为空,直接将做序列的所有元素填充进去
        while (leftPoint <= mid){
    
    
            temp[tempLeft] = arr[leftPoint];
            leftPoint++;
            tempLeft++;
        }

        // 左序列为空,直接将右序列的所有元素填充进去
        while (rightPoint <= right){
    
    
            temp[tempLeft] = arr[rightPoint];
            rightPoint++;
            tempLeft++;
        }

        //将临时数组中的元素放回数组arr中
        tempLeft = 0;
        leftPoint = left;
        while (leftPoint <= right){
    
    
            arr[leftPoint] = temp[tempLeft];
            leftPoint++;
            tempLeft++;
        }


    }
}



radix sort

1 Introduction

Radix sort (radix sort) belongs to "distribution sort", also known as "bucket sort" or bin sort. As the name suggests, it distributes the elements to be sorted through partial information of key values To some "buckets", in order to achieve the role of sorting, the radix sorting method is a stable sorting, and its time complexity is O (nlog®m), where r is the base used, and m is the number of heaps, At some point, radix sort is more efficient than other stability sorts.

2. Thinking analysis

  • Unify all the values ​​to be compared (positive integers) into the same digit length, and zero-padded numbers with shorter digits
  • Starting from the lowest bit, sort them one by one
  • Sorting from the lowest digit to the highest digit (ones digit -> tens digit -> hundreds digit -> ... -> highest digit) after the sorting is completed, the number sequence becomes an ordered sequence
  • The number of digits we need to get the maximum number
    • You can change the maximum number into a String type, and then find its length

3. Diagram

First, there must be 10 buckets representing [0-9]

3.1 The first round is put into the bucket according to the units

insert image description here
Then take them out one by one. If there are multiple elements in a bucket, the one that goes in first will be taken out first.
insert image description here

3.2 The second round is put into the bucket according to tens

insert image description here
If there is no tens digit, add 0 in front of the ones digit

insert image description here

3.3 The third round is put into the barrel according to the hundreds place

insert image description here

After taking out one by one
insert image description here

3.34 The fourth round is put into the bucket according to thousands

insert image description here

Take it out to get:

insert image description here

4. Code implementation


/**
 * 基数排序
 * @author 尹稳健~
 * @version 1.0
 * @time 2022/9/13
 */
public class BaseSorted {
    
    
    public static void main(String[] args) {
    
    
        int[] arr = {
    
    43, 52, 1, 89, 190};
        sort(arr);
        for (int i = 0; i < arr.length; i++) {
    
    
            System.out.print(arr[i] + " ");
        }
    }

    public static void sort(int[] arr){
    
    
        int maxLength = getMaxLength(arr);
        // 定义个二维数组桶,存储元素
        int[][] bucket = new int[10][arr.length];
        // 存储每个桶中有多少个元素
        int[] elementCounts = new int[10];
        for (int times = 1,step = 1; times < maxLength + 1; times++,step *= 10) {
    
    
            // 遍历数组,将元素存入桶中
            for (int i = 0; i < arr.length; i++) {
    
    
                // 获取位数上的数
                int digits = arr[i] / step % 10;
                bucket[digits][elementCounts[digits]] = arr[i];
                elementCounts[digits] ++;
            }

            //将桶中的元素重新放回到数组中
            //用于记录应该放入原数组的哪个位置
            int index = 0;
            for (int i = 0; i < 10; i++) {
    
    
                // 从桶中按放入顺序依次取出元素,放入原数组
                int position = 0;
                while ( elementCounts[i] > 0){
    
    
                    arr[index] = bucket[i][position];
                    position++;
                    elementCounts[i]--;
                    index++;
                }
            }



        }

    }

    /** 获取数组中元素长度最长的长度 */
    public static int getMaxLength(int[] arr){
    
    
        int max = arr[0];
        for (int i = 1; i < arr.length; i++) {
    
    
            if (arr[i] > max ){
    
    
                max = arr[i];
            }
        }
        return (max + "").length();
    }
}

Guess you like

Origin blog.csdn.net/weixin_46073538/article/details/126802732