[2023] Java implements common sorting algorithms

1. Binary search method

  1. Prerequisite: An array that has been sorted is required
  2. Define the left boundary L and the right boundary R, ​​confirm the search range, and perform binary search in a loop (3, 4)
  3. Get intermediate index M = Floor((L+R)/2)
  4. The value A[M] of the value of the intermediate index is compared with the value T to be searched,
    1. A[M] == T means found, returns the middle index
    2. A[M]>T, ​​the other elements on the right side of the middle value are greater than T (the searched value), without comparison, set the middle index M-1 as the right boundary, and search again;
    3. A[M]>T, ​​the other elements on the left side of the middle value are smaller than T (the searched value), no need to compare, set the middle index M-1 as the right boundary, and search again;

When using binary search, the odd binary takes the middle value,

Even dichotomy takes middle left value

/**
     *二分查找
*@parama查找数组
*@paramt查找的值
*@return
*/
private static int binarySearch1(int[] a,int t) {
    
    
//        l:左边索引,r右边索引,中间索引
        int l = 0 ,r=a.length -1,m;
        int i=1;
        while (l<=r){
    
    
            m=(l+r)>>>1;
            System.out.println("第"+i+"轮:左边下标--"+l+",右边下标--"+r+",中间下标--"+m+"中间下标的值--"+a[m]);
            if (a[m] == t){
    
    
                return m;  //表示查找到了
            }else if (a[m] >t){
    
    
                r=m-1;   //把右边界设置为中间索引-1
            }else {
    
    
                l=m+1;   //把左边界设置为中间索引+1
            }
            i++;
        }
        return -1;
    }

2. Bubble sorting

  • concept:

    1. Each time two adjacent numbers are compared, if a[j]>a[j+1] element, then the two elements are exchanged, and both are compared again, which is called a round of bubbling. The result is to let the largest element Arrange to the far right
    2. Repeat the above steps until the entire array is sorted
  • Optimization method:

    • During each round of bubbling, the last exchange index can be used as the number of comparisons for the next round of bubbling. If this value is 0, it means that the entire array is in order and the outer loop is exited directly.
  • Option One:

    /**
         *冒泡排序
    *@parama
    */
    public static void bubble(int[] a){
          
          
    //        循环次数
            for (int j = 0; j < a.length-1; j++) {
          
          
                boolean swapped = false;
    //          比较次数
    //            因为每次都会有一位排好序的数,所有比较次数可以设置为每次都比上一次少1,以此减少比较次数
                for (int i = 0; i < a.length-1-j; i++) {
          
          
                    System.out.println("比较次数:"+i);
    
    //             每一次交换,把swapped改为true
                    if (a[i] > a[i+1]){
          
          
    										swap(a,i,i+1);
                        swapped = true;
                    }
                }
                System.out.println("第"+j+"轮,循环"+Arrays.toString(a));
    //          没产生交换时退出循环
                if (!swapped){
          
          
                    break;
                }
            }
        }
    
  • Option II:

    /**
         *冒泡排序
    *@parama
    */
    public static void bubble(int[] a){
          
          
    //        每一轮交换次数
            int n = a.length-1;
    //        循环次数
            while (true){
          
          
                boolean swapped = false;
                int last = 0;  //表示最后异常交换的下标
    
    //          比较次数
    //            因为每次都会有一位排好序的数,所有比较次数可以设置为每次都比上一次少1,以此减少比较次数
                for (int i = 0; i < n; i++) {
          
          
                    System.out.println("比较次数:"+i);
                    if (a[i] > a[i+1]){
          
          
    swap(a,i,i+1);
                        last = i;  //每一轮比较的交换次数
                    }
                }
                n = last;  //把最后一轮比较的下标赋给n
    
                System.out.println("第n轮,循环"+Arrays.toString(a));
    //            当最后一轮比较的下标是0时,代表比较完毕,没有产生交换,退出循环
                if (n == 0){
          
          
                    break;
                }
            }
        }
    

3. Select sorting

  • Overview:

    • Divide the array into two subsets, sorted and unsorted. In each round, select the smallest element from the unsorted subset and put it into the sorted subset.
    • Repeat the above steps until the entire array is sorted
  • Compare with bubble sort

    • The average complexity of both is O ( n 2 ) O(n^2)O ( n2)
    • Selection sort is generally faster than bubble sort because it requires fewer exchanges.
    • But if the set is highly ordered, bubbling will be better than selection, because during bubble comparison, you can record whether there is an exchange to determine whether the set is ordered, but selection sorting cannot
    • Bubble is a stable sort, and there will be no exchange when the values ​​are the same, while selection is an unstable sort.

4. Quick sort

  • Overview

    1. Each round of sorting selects a reference point for partitioning
      1. Let elements smaller than the reference point enter one partition, and elements larger than the reference point enter another partition.
      2. When partitioning is complete, the position of the base point element is its final position
    2. Repeat the above process in the sub-partition until the number of elements in the sub-partition is less than or equal to 1, indicating that the sorting is complete. This mainly reflects a divide and conquer idea
  • Classification:

    1. Unilateral loop quick arrangement
      1. Select the rightmost element as the datum element
      2. The j pointer is responsible for finding an element smaller than the reference point, and once found, it is exchanged with i
      3. The i pointer maintains the bounds of elements smaller than the reference point, and is also the target index for each swap
      4. Finally, the reference point is exchanged with i, and i is the partition position
    2. Bilateral cycle quick arrangement
      1. Select the leftmost element as the datum element
      2. The j pointer is responsible for finding elements smaller than the reference point from right to left, and the i pointer is responsible for finding elements larger than the reference point from left to right. Once the two are found, they are exchanged until i and j intersect.
      3. Finally, the reference point is exchanged with i (at this time, i and j are equal), and i is the partition position
      4. Main points
        1. The reference point is on the left, and j should be followed by i
        2. while( i < j && a[j] > pv ) j-- // must add i < j
        3. while ( i < j && a[i] <= pv ) i++ //必须加≤

1. Realization of unilateral quick sort code

         public static void quick(int[] a,int l,int h){
    
    
             if (l>=h){
    
    
                 return;
             }
     //        p:索引值 ,用于做子分区的左右边界
             int p =partition(a, l, h);
     quick(a, l,p-1); //         左边分区的范围确认
     quick(a, p+1,h); //        右边分区的范围确认
     
         }
     
     /**
          *@Description//TODO单边快排
     *@param:a数组
     *@param:l左边界
     *@param:h右边界
     *@return:int表示基准点元素所在的正确索引,用它确认下一轮分区的边界
     **/
     private static int partition(int[] a,int l,int h){
    
    
     
             int pv = a[h];  //      基准点的值
             int i = l;
             for (int j = l;j < h; j++){
    
    
                 if(a[j] < pv){
    
    
     
                     if (i != j){
    
      //当i和j指向的是同一个元素时,代表没必要交换,
     swap(a,i,j);
                     }
                     i++;
                 }
             }
             if (i != h){
    
    
     swap(a,h,i);
             }
             System.out.println("比较后的值:"+Arrays.toString(a)+" 基准点下标="+i);
             return i;
         }

2. Implementation of bilateral quick sorting code

           
   	public static void quick(int[] a,int l,int h){
    
    
               if (l>=h){
    
    
                   return;
               }
       //        p:索引值 ,用于做子分区的左右边界
               int p =partition(a, l, h);
       quick(a, l,p-1); //         左边分区的范围确认
       quick(a, p+1,h); //        右边分区的范围确认
       
           }
       
       /**
            *@Description//TODO双边快排
       *@param:a数组
       *@param:l左边界
       *@param:h右边界
       *@return:int表示基准点元素所在的正确索引,用它确认下一轮分区的边界
       **/
       private static int partition(int[] a,int l,int h){
    
    
               int pv = a[l];
               int i = l;
               int j = h;
               while (i < j){
    
    
       //          寻找的顺序也不能更改,必须先执行j从右向左,再执行i从左向右寻找
       
        //            j从右向左找小的 ,必须加i < j 条件,因为不加会出现i走过头,跑到比j大的位置取拿取元素
                   while (i < j && a[j] > pv){
    
    
                       j--;
                   }
       //            i从左向右找大的  ,a[i] <= pv必须加等于,因为a[i]最开始是从左边界开始,就是等于pv
                   while (i < j && a[i] <= pv){
    
    
                       i++;
                   }
       
       swap(a,i,j);
               }
       //          基准点和j交换位置,j代表分区位置
       swap(a,l,j);
               System.out.println(Arrays.toString(a)+" j="+j);
               return j;
       
           }
       ```

Guess you like

Origin blog.csdn.net/weixin_52315708/article/details/131581956