About various sorting and related problems (continuous update)

Sorting problem

One: Bubble sorting
1. The bubble sorting is O (n ^ 2) time complexity, and the extra space complexity is O (1)
2. Bubble thinking: find a maximum value each time and put it in the last position , And the next time you look for it again, ignore the last position, and then put the second largest value in the penultimate position, and so on, when there is only one number left, there is no need to re-rank.
3. Bubbling programming ideas: The first layer of loop sets the end point of the sorting, and then decreases to the position of 1, in turn, because the comparison process involves two positions, so the end point and the start point do not need to coincide, you can complete the comparison, In fact, the starting point does not need to go to the end point, as long as it reaches the end point -1 position, it has already been compared. , The second cycle is from 0 to less than the end point set by the first layer, and does not need to coincide with the end point. The reason is as above. In the second layer cycle, as long as the i-th number is greater than i + 1, it will be exchanged to ensure that The maximum value before the final position is swapped to the final position.
4. Code:

 public static void bubbleSort(int[] arr) {
        if (arr == null || arr.length < 2) {
            //如果数组为空或者只要一个,就不用排序
            return ;
        }
        for (int end = arr.length - 1; end > 0; end--) {//end表示从后往前开始的排序好的数字
            for (int i = 0; i < end; i++) {//由于这是基于前一个数字,比较后一个数字,所以end所在位置的数字
                //是最后也要用于比较的,所以不需要担心,end=arr.length-1的时候,最后一个位置无法比较的情况。
                if (arr[i] > arr[i + 1]) {//当第i个数比i+1大,就交换,目的就是将最大的数字,往后一直排
                    swap(arr,i,i+1);
                }
            }
        }
    }

    public static void swap(int[] arr, int i, int j) {//交换数组内的数
        int temp=arr[i];
        arr[i]=arr[j];
        arr[j]=temp;

    }

Two: selection sorting
1. The time complexity of selection sorting is O (n ^ 2), the complexity of extra space is O (1)
2. The idea of ​​selection sorting: find the minimum value every time and put it in the first position, Then start from the second position, the second minimum value is placed in the second position, and so on, and the last value is placed in his own position
. 3. The programming idea of ​​sorting: similar to bubbling, the first Layer loop, increasing from 0 to the penultimate position (when only two numbers are left, assuming that the first number is the minimum value, then it will have traversed to the last position, and the penultimate number and The last one is compared, so there is no need to go to the end, when there is only one number left, it must be the minimum value among the remaining numbers, because there is only it. In the previous loop, we can guarantee that All the values ​​before it are smaller than it) . In the first-level loop, the initial position is assumed to be the minimum value. The second-level loop starts from the initial position set by the first-level loop and goes down to the last number, as long as The minimum value of is Change (into the initial position), and then until the end.
4. Code:

  public static void selectionSort(int[] arr) {
        if (arr == null || arr.length < 2) {
            return ;
        }//数组为空或者只有一个数字,直接返回

        for (int i = 0; i < arr.length - 1; i++) {//排序位置从0开始,代表已排好的,直到最后一个
           //i作为起始位置,如果直接在最后一个位置arr[arr.length-1]中出现,那么j=i+1就会越界,因为我们
            //是从i的下一个位置开始找所有的数字和最小的进行比较
            int minIndex=i;//假设第一个位置的数字是最小的
            for (int j = i + 1; j < arr.length; j++) {//初始的时候,由于假设了第一个是最小的,所以就
                //不存在遗漏了第一个的情况,可以直接从i+1开始
                minIndex=arr[j]<arr[minIndex]?j:minIndex;
                //当前值arr[j]是否小于最小值,如果小,就返回当前值的下标,否则不变
            }
            swap(arr, i, minIndex);
        }
    }

    public static void swap(int[] arr, int i, int j) {//数组内交换数字
        int temp=arr[i];
        arr[i]=arr[j];
        arr[j]=temp;
    }

Three: Insert sort
1. The time complexity of insert sort involves the best time complexity, the worst time complexity and the average time complexity. Compared with the first two sorts, the fixed time complexity is O (n ^ 2 ), If the array is already sorted, the insertion sort algorithm is O (n), if it is completely reversed, it is O (n ^ 2). The extra space complexity is O (1)
2. The idea of ​​insertion sort: similar to sort Card, if I only have one card, then it is already ordered, ( expand the ordered position until all ), so when a new card is taken, there are two possibilities , smaller than the first card, or greater than or equal to, if If it is bigger or equal to the first card, then put it in your hand (in the array) and continue to look at the next card from the chaotic pile. If it is smaller than the first card, then compare it forward, but because it is already the first card , So, there is no larger number in front of it , so swap the position of the first card and the second card, continue to look at the third card, and so on until the end
3. Programming ideas: to look at the first card To the last card, it takes a loop to get a card, And in front of the numbers compare, not only than the first card, a card rather than to the front than it is small so far, so two cycles; the first cycle: from 1 to the last card. ( To understand the meaning of each variable, the variables in the first cycle are the cards that need to be compared with the sorted cards, so there is only one card in the first card, there is no need to compare ) The second cycle, because The i-th position needs to be compared, then the i-1 position must be the first number to be compared with i, if you need to continue, then i-1 then-, so the second loop is represented by j i-1, then as long as j is in the array, and the number of j positions is greater than i, then continue to
4. Code:

 /*思想:如果我只有一张牌,那么它就是排好序的,所以第一个牌不用管,然后拿下一个
     * 数字和第一个牌比较,如果比第一个小,就交换,如果大就直接走到下一个位置,接下
     * 来就是普遍情况,也就是,这个位置的数字要和已经排序好的数字的最后的数字进行比较,
     * 如果大,就不管,如果小,就要一直交换到它在已经排序好的位置的前一个数比他小,为止*/
    public static void insertionSort(int[] arr) {
        if (arr == null || arr.length < 2) {
            return ;
        }//数组为空或者只有一个,就不需要排了
        for (int i = 1; i < arr.length; i++) {//0位置只有一张牌,所以
            //不需要排序,然后已经排序好的位置要走到最后一个位置才结束;
            /*i位置表示即将排序的位置,j表示与i进行比较的位置,这个j从i的前一个
            * 一直到0位置,我们的目的是i比j大,才可以,所以,一旦j比i大,就交换i和j位置的数字
            * 此时,j位置的数字,就是我们要排序的位置的数字,也就是原来的i,所以,再
            * j--,让j位置继续表示要和要排序的位置进行比较的位置。当j=0时,如果i仍然
            * 比j要小,那么交换,然后j无法递减,从而结束*/
            for (int j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--) {
                //其中之所以用j+1表示i,就是因为要排序的位置,可能会一直变,所以
                //需要用j+1表示,方便j递减的时候,让j+1一直表示将要排序的位置
                swap(arr,j,j+1);
            }

        }
    }

    public static void swap(int[] arr, int i, int j) {
        int temp=arr[i];
        arr[i]=arr[j];
        arr[j]=temp;
    }

Four: merge sort
1. merge sort: time complexity is O (n * logn), extra space complexity is O (n) (for efflux)
2. The idea of ​​merge sort: if you want to sort an array, put This array is divided into two. If both the left and right are sorted, then you only need to arrange the two arrays in an outer row , which is to arrange the two ordered arrays into an ordered array. The merge sort is a good use of the already sorted parts. It is done. The comparison between each data can be used efficiently.
3. The programming idea of ​​merge sort: we use the word "if", that is, if someone To arrange the left and right for us, we only need to merge the two ordered arrays, but the problem is that no one helps us turn the two sub-arrays into an ordered array , but our own purpose is not to change this large array Is it an ordered array? Therefore, I think that you can use recursion ( as long as you can use recursion, you can use a loop to solve, it is nothing more than pushing the stack yourself, this problem will be discussed in other articles in the future ), if we continue to divide the array, we will eventually divide the array Each number becomes a separate array. If the array has only one number, there is no need to sort, so the set return condition is if the starting point of the sorting == end point, then return directly , then the division process is resolved Now, the point is, how to merge the two ordered arrays into one. First, we used the help array. This number should just accommodate all the numbers of the two arrays. If it does? First of all, we must know that nm means the difference between the two. This difference is often the number from [m, n) or (m, n] from m to n, but what we want is [m, n] That is, we need both positions, so the size of this help array is: R-L + 1, Next, set two pointers to point to two arrays, from zero to the last position, constantly compare the two pointed values, whoever is small, we put who in the help array, which also means The number pointed to is meaningless, so ++ points to the next number, but the number pointed to by another pointer has not been put into help, so it still makes sense, and continue to compare. In the end, there must be a pointer that will cross the boundary, meaning two One of the "arrays" has been completely put out, then we only need to put all the other arrays into the help, because it is obvious that all the remaining values ​​are larger than the previous ones. Finally, because the two arrays are assumed by us, in fact, the two arrays are just a fragment in the middle of the large array, so we need to use help to cover the entire fragment , so how to cover? The help array is from zero to help.length-1, the original array we have intercepted the fragments from L to R, then we only need the original array from L + 0 to L + arr.length-1 position, just cover with help, That's it , this is to find the connection between the two arrays.
4. Code:

  //归并的开头,用于检验是否需要排序
    public static void mergeSort(int[] arr) {
        if (arr.length < 2 || arr == null) {
            return ;
        }
        sortProcess(arr, 0, arr.length - 1);
    }

    public static void sortProcess(int[] arr, int L, int R) {
        //当起点等于终点的时候,意味着不需要继续分,已经排序号了
        if (L == R) {
            return ;
        }
        /*
        * 在数组很大的时候,那么L+R很有可能越界,会超过这个类型承载的限度,所以需要修改*/
//        int mid = (L + R)/2;//找到这次排序的中点位置
        int mid=L+(R-L)/2;
        sortProcess(arr, L, mid);//排序左边
        sortProcess(arr, mid + 1, R);//排序右边
        merge(arr,L,mid,R);
    }

    public static void merge(int[] arr, int L,int mid, int R) {
        int[] help=new int[R-L+1];//由于传的值是左闭,右闭的[L,R],
        //但是R-L则是有一个闭合,有一个开,例如2~4,4-2=2,但是[2,4]
        //有三个数字,所以,当两个值都是闭合的,那么就要+1;
        //所以此时help数组,正好存储[L,R],那么只需要将help填满,然后再
        //覆盖到原数组即可
        int i=0;//表示help数组的指针
        int p1=L;//表示左边起点
        int p2=mid+1;//表示右边起点
        while(p1<=mid && p2<=R){//当两个都没有越界的时候,
            help[i++]=arr[p1]<arr[p2]? arr[p1++] :arr[p2++];
            /*help数组i位置的值,等于左,右较小的值,选中了哪边,那边的指针
            * 就要++,方便下次比较*/
        }
        //两个指针必有一个最终会越界,哪个越界了,我们将剩下那部分的余下全部
        //copy到help中
        while (p1 <= mid) {
            help[i++] = arr[p1++];
        }
        while (p2 <= R) {
            help[i++]=arr[p2++];
        }
        //至此,help数组填写完成,接下来,要将这部分,覆盖到原
        //数组的L~R部分
        for (int j = 0; j < help.length; j++) {
            arr[L+j]=help[j];
            /*精髓在于,help数组与arr差异在于,要开始的位置,
            * 恰好和arr数组相差L,也就是说,L+j,且j=0,正好对应arr[L]
            * 的位置,所以找到这两个数组的联系,就很好解决这段代码*/
        }
    }

Five (1): Dutch national flag problem (Quick sorting primer)
1. Problem abstraction: divide a bunch of numbers into three parts, with m as the boundary, smaller than m on the left, as large as m in the middle, than m The big one is on the right side.
2. Problem solving idea: divide the array into three parts, less than the region, equal to the region, and greater than the region, and then gradually expand these three parts until the entire array
3. Programming idea: First, divide each region, All positions of the entire array are areas to be divided , so the previous position of the array is less than the starting position of the area, and the right side of the last position of the array is greater than the position of the beginning of the area, so is it equal to the area? Put the equal area on the right side of the less than area (currently empty) and then push the equal area forward. With the above ideas, start writing code, define the area, need pointer identification, so the identification is less than the area p1 and greater than the area p2, as for the area, since it can be pushed by less than the area, then you can use one less, and then use a pointer i traversing be divided areas , if the value is greater than the standard, an area larger than -1, the value of p2 and then to exchange position, and then continue to look at the relationship between this value and the standard value at position i ; if the value is less than the divided value, smaller than the area ++ , And then exchange the value of the p1 position with it. At this time, the value less than the area is still guaranteed to be less than the standard value, and the value of the position pointed to by i at this timeIt must have been traversed. Imagine a process where the position of i refers to the right side of the less than area at the beginning, so if the value pointed to by i is small, then the exchange process is equivalent to less than the area annexed forward Position, if i is not ++, then the area to be divided will overlap with the less than area, so ++ is required. If it is equal to the standard value, i ++, when it encounters less than the standard value again, please note: i and less than There is only one value of equal area in the middle of the area, that is to say, the equivalent value will be exchanged to the i position during the exchange, so the i position is still divided, that is, the process of pushing the area equal to the area is smaller ; so the i position must ++, because after the exchange is completed, the value pointed to by i is actually less than or equal to the area, which has already been divided; then, where does i go? If you reach the end of the array, it will be chaotic, because after encountering a greater than area, the value is greater than the standard value, so the greater than area expands, but because the left side of the greater area has been close to the area equal to or less than the area, once greater The expansion of the area will make the exchange process chaotic, so i will go to the front side of the area
. 4. Code:

  public static int[] flag(int[] arr, int L, int R, int num) {
         int less=L-1;//小于区域在需要判断的区域的左侧
         int more=R+1;//大于区域在需要判断的区域的右侧
         int index=L;//待定区域的指针
        while (index <more) {//指针走遍待定区域,重点是待定区域,如果走遍右侧,那么会把划分过的大于区域搞乱
            //index<=R是错误的
            if (arr[index] < num) {//当前值小于num
                swap(arr, ++less, index++);//将这个值与小于区域的后一个数字交换
            } else if (arr[index] > num) {//当前值大于num
                swap(arr,--more,index);//将这个值和大于区域的前一个数交换,
                //但是此时不清楚被交换的是什么数字,所以index不动
            }else {//当前值==num,则忽略,
                index++;
                //本质上,这是小于区域,推动着等于区域前进。
            }

        }
        return new int[]{less + 1, more - 1};  //返回等于区域的第一个值和最后一个值
        //当没有等于区域的时候,第一个值会大于第二个值,所以无效
    }

    public static void swap(int[] arr, int i, int j) {
        int temp=arr[i];
        arr[i]=arr[j];
        arr[j]=temp;
    }

Five (2): Quick sort
1. Time complexity of quick sort: The long-term expectation is O (n * logN) extra space complexity (random fast sort) is O (logN) because every breakpoint is a dichotomy, then dichotomy As many times as there are breakpoints
2. The idea of ​​quick sorting: With the Dutch flag problem as the antecedent, we understand the partition process (after division, what does it do), then it is unfinished, to be continued
six (1) Prerequisite knowledge of heap sorting
1. Complete binary tree and full binary tree
2. Array representation of complete binary tree
3. Concept of
heap 4. Power of heap (for example)
Six (2): Heap sorting
Seven: Bucket sorting (not based on comparison sort , Mainly to give an example)

Summary: Knowledge points involved
1. Recursive cognition
2. Logarithm
3. Small sum problem
4. Reverse ordinal number problem
5 Comprehensive sorting in engineering
6. Comparator
7. Random knowledge

Published 12 original articles · praised 0 · visits 138

Guess you like

Origin blog.csdn.net/weixin_44065691/article/details/105546528