【2023】Java implementa algoritmos de classificação comuns

1. Método de pesquisa binária

  1. Pré-requisito: uma matriz classificada é necessária
  2. Defina o limite esquerdo L e o limite direito R, confirme o intervalo de pesquisa e execute a pesquisa binária em um loop (3, 4)
  3. Obtenha o índice do meio M = Floor((L+R)/2)
  4. O valor A[M] do valor do índice intermediário é comparado com o valor T a ser pesquisado,
    1. A[M] == T significa encontrado, retorne o índice intermediário
    2. A[M]>T, ​​​​outros elementos no lado direito do valor do meio são maiores que T (o valor pesquisado), não há necessidade de comparar, defina o índice do meio M-1 como o limite direito e pesquise novamente;
    3. A[M]>T, ​​​​outros elementos à esquerda do valor do meio são menores que T (o valor pesquisado), não há necessidade de comparar, defina o índice do meio M-1 para o limite direito e pesquise novamente;

Ao usar a pesquisa binária, o número binário ímpar é o valor do meio,

Divida um número par em dois e pegue o valor do meio à esquerda

/**
     *二分查找
*@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. Classificação por bolha

  • conceito:

    1. Cada vez que dois números adjacentes são comparados, se a[j]>a[j+1] for um elemento, os dois elementos são trocados e ambos são comparados novamente, o que é chamado de rodada de borbulhamento. O resultado é deixar o maior linha do elemento à direita
    2. Repita as etapas acima até que todo o array esteja classificado
  • Método de otimização:

    • Durante cada rodada de borbulhamento, o último índice de troca pode ser usado como o número de comparações para a próxima rodada de borbulhamento.Se este valor for 0, significa que toda a matriz está em ordem e o loop externo é encerrado diretamente.
  • Opção um:

    /**
         *冒泡排序
    *@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;
                }
            }
        }
    
  • Opção 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. Classificação de seleção

  • Visão geral:

    • Divida a matriz em dois subconjuntos, classificados e não classificados. Em cada rodada, selecione o menor elemento do subconjunto não classificado e coloque-o no subconjunto classificado.
    • Repita as etapas acima até que todo o array esteja classificado
  • Comparar com classificação por bolha

    • A complexidade média de ambos é O (n 2) O(n^2)Ó ( n2 )
    • A classificação por seleção é geralmente mais rápida do que a classificação por bolha porque requer menos trocas.
    • Mas se o conjunto for altamente ordenado, o borbulhamento é melhor que a seleção, porque durante a comparação de bolhas, você pode registrar se há uma troca para determinar se o conjunto está ordenado, mas a classificação por seleção não pode
    • A bolha é uma classificação estável e não haverá troca quando os valores forem iguais, enquanto a seleção é uma classificação instável.

4. Classificação rápida

  • Visão geral

    1. Cada rodada de classificação seleciona um ponto de referência para particionamento
      1. Deixe que os elementos menores que o ponto de referência entrem em uma partição e os elementos maiores que o ponto de referência entrem em outra partição.
      2. Quando o particionamento estiver concluído, a posição do elemento do ponto base será sua posição final
    2. Repita o processo acima na subpartição até que o número de elementos na subpartição seja menor ou igual a 1, o que significa que a classificação está concluída. Isso reflete principalmente a ideia de dividir para governar
  • Classificação:

    1. Classificação rápida cíclica unilateral
      1. Selecione o elemento mais à direita como o elemento do ponto base
      2. O ponteiro j é responsável por encontrar o elemento menor que o ponto de referência. Uma vez encontrado, ele é trocado por i
      3. O ponteiro i mantém o limite dos elementos menores que o ponto de referência e também é o índice alvo de cada troca
      4. Finalmente, o ponto de referência é trocado por i, que é a posição da partição.
    2. Classificação rápida de circulação bilateral
      1. Selecione o elemento mais à esquerda como o elemento do ponto base
      2. O ponteiro j é responsável por encontrar elementos menores que o ponto de referência da direita para a esquerda, e o ponteiro i é responsável por encontrar elementos maiores que o ponto de referência da esquerda para a direita. Uma vez encontrados os dois, eles são trocados até i e j cruzar.
      3. Finalmente, o ponto de referência é trocado por i (i e j são iguais neste momento), e i é a posição da partição.
      4. Pontos principais
        1. O ponto de referência está à esquerda e deve ser j primeiro e depois i
        2. while( i < j && a[j] > pv ) j-- // i < j deve ser adicionado
        3. while ( i < j && a[i] <= pv ) i++ //必须加≤

1. Implementação de código de classificação rápida unilateral

         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. Implementação de código de triagem rápida bilateral

           
   	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;
       
           }
       ```

Acho que você gosta

Origin blog.csdn.net/weixin_52315708/article/details/131581956
Recomendado
Clasificación