Knowledge literacy-algorithm-sorting algorithm

img

Bubble Sort

The core idea of ​​bubble sort is:从无序队列的头部开始,进行两两比较,根据大小交换位置,直到最后将最大(小)元素放在队列的尾部,从而成为有序队列的一部分

Bubble sort maintains two for loops, the first for loop controls the number of times, and the second for loop controls pairwise comparisons. , It should be noted: Where does the bubble sort come from? Generally, it will emerge from the right, which means that the right (the tail of the queue) is an ordered queue

public void bullleSort(int[] nums){
    
    
    for(int i = 0;i < nums.length - 1;i++){
    
    
        for(int j = 1;j < nums.length  - i;j++){
    
    
            if(nums[j - 1] < nums[j]){
    
    
                int temp = nums[j - 1];
                nums[j - 1] = nums[j];
                nums[j] = temp;
            }
        }
    }
}

Code explanation: The first for loop controls the number of times, then it is clear that the initial value of i is 0, and the upper limit (obtained) is num.length-2. Thinking: Can I start with another number (1)? If it is just a simple control of the number of times, it is not a big problem from the beginning, but in the subsequent for loop, i also assumes an important role: the number of elements that have been sorted. As mentioned earlier, it starts from the head of the unordered queue and ends at the tail. How do you know where the tail is? Rely on this i variable

The second for loop controls the pairwise comparison. Because I am used to comparing i and i -1, the initial value is 1, and the upper limit (obtained) is nun.length-i-1

optimization

For the sequence {2,1,3,4,5,} the sequence is already in order when the first comparison is made, but subsequent comparisons will continue, so optimization can be performed

public void bullleSort(int[] nums){
    
    
    boolean flag = true;
    for(int i = 0;i < nums.length - 1 && flag;i++){
    
    
        flag = false;
        for(int j = 1;j < nums.length  - i;j++){
    
    
            if(nums[j - 1] > nums[j]){
    
    
                int temp = nums[j - 1];
                nums[j - 1] = nums[j];
                nums[j] = temp;
                flag = true;
            }
        }
    }
}

Performance analysis

Time complexity: the minimum time is O(n) to run once, the worst case needs to be compared (n-1), then according to the summation formula to get O(n(n-1) / 2), so the average complexity is O(N2)

Space complexity: just need a temp variable O(1)

Stability: It is a stable algorithm because> is used

Select sort

Basic idea:每一趟从待排序序列中选择一个最大或者最小的元素放在没有排序的尾部

public void selectionSort(int[] nums){
    
    
    for(int i = 0;i < nums.length - 1;i++){
    
    
        int minIndex = i;
        for(int j = i;j < nums.length;j++){
    
    
            if(nums[j] < nums[minIndex]){
    
    
                minIndex = j;
            }
        }
        int temp = nums[minIndex];
        nums[minIndex] = nums[i];
        nums[i] = temp;
    }
}

Performance analysis

Time complexity: O(N2)

Space complexity: O(1)

Stability: Unstable, such as {_7,7,1,2}, because the first choice is 1, so it becomes {1,7_7,2}, so it is unstable

Insertion sort

Basic idea:每趟将一个元素,插入到已经排好序的正确位置

public void insertionSort(int[] nums){
    
    
    for(int i = 1;i < nums.length;i++){
    
    
        int temp = nums[i];
        int j;
        for(j = i - 1;j >= 0 && temp < nums[j];j--){
    
    
            nums[j + 1] = nums[j];
        }
        nums[j + 1] = temp;	//注意这里是j+1 因为上面for循环最后还是进行了j--
    }
}

The same is two for loops, the first for controls the number of insertions, the second for controls the position to be inserted, moves some elements back, and inserts the current element into the correct position

Performance analysis

Time complexity: O(N2)

Space complexity: O(1)

Stability: stable

Hill sort

Basic idea:在插入排序的基础上进行分组排序,插入排序是将所有元素看做一个组,而希尔排序是没隔一个步长分为一个组,组内进行插入排序,有了插入排序的思想应该很好理解

puboic void shellSort(int[] nums){
    
    
    //控制分组
    for(int gap = nums.length/2; gap > 0;gap /= 2){
    
    
        //和插入排序一样只是上步长为1改为gap
        for(int i = gap;i < nums.length;i++){
    
    
            int temp = nums[i];
            int j;
            for(j = i - gap;i >= 0;temp < nums[j];j -= gap){
    
    
                nums[j + gap] = nums[j];
            }
            nums[j + gap] = nums[j];
        }
    }
}

Performance analysis

Time complexity: The complexity of Hill sorting depends on the choice of gap, but it must be less than O(N2)

Space complexity: O(1)

Stability: stable

Merge sort

Merge sort is a typical divide-and-conquer idea. First divide the array into each group with only one element, because an element is ordered by default, and then close it up and look at the code directly

public int[] sortArray(int[] nums) {
    
    
    int[] temp = new int[nums.length];
    mergeSort(nums, 0, nums.length - 1, temp);
    return nums;
}
public void mergeSort(int[] nums, int left, int right, int[] temp){
    
    
    if(left >= right)	return;
    int mid = (left + right) >> 1;
    mergeSort(nums, left, mid, temp);
    mergeSort(nums, mid + 1, right, temp);
    int k = left, p = mid + 1, t = 0;
    while(k <= mid || p <= right){
    
    
        if(p > right || (k <= mid && nums[k] < nums[p])){
    
    
            temp[t++] = nums[k++];
        }else{
    
    
            temp[t++] = nums[p++];
        }
    }
    for(int q = 0; q < t;q++){
    
    
        nums[left + q] = temp[q];
    }
}

Performance analysis

Time complexity: O(nlogn)

Space complexity: O(n)

Stability: stable

Heap sort

Basic idea: create a large top pile or a small top pile, and then use the element with a subscript of 0 to exchange with the last element of the large top pile (small top pile), the key points:

  • The last non-leaf node subscript of the complete binary tree: nums.length / 2-1
  • If the root node subscript is k, the left subtree node of the node: 2k + 1, the right subtree: 2k + 2
public int[] sortArray(int[] nums) {
    
    
    heapSort(nums);
    return nums;
}
public void heapSort(int[] nums){
    
    
    for(int i = nums.length / 2 - 1;i >= 0;i--){
    
    
        adjustHeap(nums, i, nums.length);
    }
    for(int j = nums.length - 1;j > 0;j--){
    
    
        int temp = nums[j];
        nums[j] = nums[0];
        nums[0] = temp;
        adjustHeap(nums, 0, j);
    }
}
public void adjustHeap(int[] nums, int i, int length){
    
    
    int temp = nums[i];
    for(int k = 2 * i + 1; k < length;k = k * 2 + 1){
    
    
        if(k + 1 < length && nums[k] < nums[k + 1]){
    
    
            k++;
        }
        if(nums[k] > temp){
    
    
            nums[i] = nums[k];
            i = k;
        }else break;
    }
    nums[i] = temp;
}

Quick sort

The basic idea of ​​quick sort is to use the divide-and-conquer method to find the correct position of each reference number in the array, so that the number on the left of the reference number is smaller than the number, and the number on the right is larger than the number, and then divide and conquer the Recursive quick sort on the left and right of the number

public void quickSort(int[] nums, int left, int right){
    
    
    if(left >= right)	return;
    //基准数
    int temp = nums[left];
    int i = left;
    int j = right;
    while(i != j){
    
    
        while(i < j && nums[j] >= temp)	j--;
        while(i < j && nums[i] <= temp)	i++;
        if(i < j){
    
    
            int t = nums[i];
            nums[i] = nums[j];
            nums[j] = t;
        }
    }
    nums[left] = nums[i];
    nums[i] = temp;
    quickSort(nums, left, i - 1);
    quickSort(nums, i + 1, right);
}


Guess you like

Origin blog.csdn.net/weixin_44706647/article/details/115105501