Classificação básica de mesclagem de Java, classificação rápida não recursiva

1. Otimização recursiva de classificação rápida

  • A primeira ideia de otimização :

1. Em primeiro lugar, a classificação rápida é para uma grande quantidade de dados, como dez mil como unidade de medida, então a complexidade do tempo e a complexidade do espaço da classificação rápida são as melhores em comparação com outros tipos, então para uma pequena quantidade de dados como 10, 100, a classificação rápida obviamente não é a melhor;
2. Em seguida, a classificação rápida sempre após procurar um benchmark, de modo que os dados tendam lentamente à ordem, desta vez quando os dados entre baixo e alto são menores que um dado valor Quando, por exemplo, 100, podemos chamar entre inserir classificação para classificação;

public static void quick(int[] arr,int low,int high){
    
    
        if(low > high){
    
    
            return;
        }
        //第一个优化:当low,high之间的数据个数少于某一个范围,可以调用直接插入排序
        if(high-low+1 < 100){
    
    
            insertsort2(arr,low,high);
            return;
        }
    }
    //用来优化的的直接插入排序
    public static void insertsort2(int[] arr,int low,int high){
    
    
        for(int i = low+1;i <= high;i++) {
    
    
            int tmp = arr[i];
            int j = i-1;
            for (;j >= low;j--){
    
    
                if (arr[j] > tmp) {
    
    
                    arr[j+1] = arr[j];
                }else{
    
    
                    break;
                }
            }
            arr[j+1] = tmp;
        }
    }
   
  • A segunda otimização :

1. Por exemplo, para o grupo de dados {1, 2, 3, 4, 5}, cada vez que os dados com o subscrito 0 à esquerda são tomados como referência, cada vez que a posição de referência é determinada, haverá situações extremas, e os dados estão todos na referência. Para determinar a posição do benchmark, todos pensam que é bom ter dados à esquerda e à direita do benchmark toda vez que ele é determinado, ou os casos extremos são classificados, então é óbvio que é bom quando ambos os lados estão;
2. Então, o que? A fim de garantir que haja dados em ambos os lados de cada benchmark, pegamos o mais baixo à esquerda e o mais alto à direita sempre, e o subscrito do meio meio = (alto + baixo) / 2. Esses três subscritos correspondem à mediana dos dados., que é (arr [mid] <arr [baixo] <arr [alto]), o último subscrito baixo é a mediana. Não importa qual a posição é encontrada nessas três posições, você só precisa comparar com a posição baixa do câmbio, então a baixa sempre colocará essa mediana;

public static void quick(int[] arr,int low,int high){
    
    
        if(low > high){
    
    
            return;
        }
        }
        //第二次优化,取三个数中位数,这样的基准就不会出现极端情况
        mid(arr,low,high);
        //par是基准
        int par = parttion(arr,low,high);
        quick(arr,low,par-1);
        quick(arr,par+1,high);
    }
    //优化的取三个数字的中位数
    public static void mid(int[] arr,int low,int high){
    
    
        /*int mid = (high+low)/2;
        if (arr[low] < arr[mid] && arr[mid] < arr[high]){
            int tmp = arr[low];
            arr[low] = arr[mid];
            arr[mid] =tmp;
            System.out.println(low);
        }else if(arr[high] > arr[low] && arr[high] < arr[mid]) {
            int tmp = arr[high];
            arr[high] = arr[low];
            arr[low] =tmp;
            System.out.println(low);
        }else{
            System.out.println(low);
            return;
        }*/
        int mid = (low+high)/2;
        //array[mid] < array[low] < array[high]
        if(arr[low] >= arr[high]) {
    
    
            swap(arr,low,high);
        }
        if(arr[low] <= arr[mid]) {
    
    
            swap(arr,low,mid);
        }
        if(arr[mid] >= arr[high]) {
    
    
            swap(arr,low,mid);
        }
    }
  • Todo o código para ambas as otimizações
public static void quicksort(int[] arr){
    
    
        quick(arr,0,arr.length-1);

    }
    //
    public static void quick(int[] arr,int low,int high){
    
    
        if(low > high){
    
    
            return;
        }
        //第一个优化:当low,high之间的数据个数少于某一个范围,可以调用直接插入排序
        if(high-low+1 < 100){
    
    
            insertsort2(arr,low,high);
            return;
        }
        //第二次优化,取三个数中位数,这样的基准就不会出现极端情况
        mid(arr,low,high);
        //par是基准
        int par = parttion(arr,low,high);
        quick(arr,low,par-1);
        quick(arr,par+1,high);
    }
    //用来优化的的直接插入排序
    public static void insertsort2(int[] arr,int low,int high){
    
    
        for(int i = low+1;i <= high;i++) {
    
    
            int tmp = arr[i];
            int j = i-1;
            for (;j >= low;j--){
    
    
                if (arr[j] > tmp) {
    
    
                    arr[j+1] = arr[j];
                }else{
    
    
                    break;
                }
            }
            arr[j+1] = tmp;
        }
    }
    //优化的取三个数字的中位数
    public static void mid(int[] arr,int low,int high){
    
    
        /*int mid = (high+low)/2;
        if (arr[low] < arr[mid] && arr[mid] < arr[high]){
            int tmp = arr[low];
            arr[low] = arr[mid];
            arr[mid] =tmp;
            System.out.println(low);
        }else if(arr[high] > arr[low] && arr[high] < arr[mid]) {
            int tmp = arr[high];
            arr[high] = arr[low];
            arr[low] =tmp;
            System.out.println(low);
        }else{
            System.out.println(low);
            return;
        }*/
        int mid = (low+high)/2;
        //array[mid] < array[low] < array[high]
        if(arr[low] >= arr[high]) {
    
    
            swap(arr,low,high);
        }
        if(arr[low] <= arr[mid]) {
    
    
            swap(arr,low,mid);
        }
        if(arr[mid] >= arr[high]) {
    
    
            swap(arr,low,mid);
        }
    }
    public static void swap(int[] arr,int low,int high){
    
    
        int tmp = arr[low];
        arr[low] = arr[high];
        arr[high] = tmp;
    }
    //划分函数
    public static int parttion(int[] arr,int start,int end){
    
    
        //申请一个tmp空间用来放基准的值(基准一般选择的是边上的值)
        int tmp = arr[start];//这里取的是最左边的值,那么一会就先从最右边开始找[end]位置
        while(start < end){
    
    
            while(start < end && arr[end] >= tmp){
    
    
                end--;
            }
            //到了这里,从while出来有俩种情况,不满足start < end或者不满足arr[end] >= tmp
            if (start >= end){
    
    
                //arr[start] = tmp;
                break;//直接退出,因为已经遍历完毕
            }else{
    
    //else就是arr[end] < tmp
                arr[start] = arr[end];
            }
            while(start < end && arr[start] <= tmp){
    
    
                start++;
            }
            //到了这里,同样从while出来有俩种情况,不满足start < end或者不满足arr[start] <= tmp
            if (start > end){
    
    
                //arr[end] = tmp;
                break;
            }else{
    
    
                arr[end] = arr[start];
            }
        }
        arr[start] = tmp;
        return start;//返回基准移动到位置,这样基准的左边全小于它,右边全都大于它
    }


2. Classificação rápida não recursiva

  • Idéias :

1. Use uma pilha para ajudar a obter uma classificação rápida não recursiva;
2. Para o seguinte conjunto de dados, após a posição de referência ser encontrada pela primeira vez, há um quadrado vermelho (subscrito nº 5),
3. Para recursão , a esquerda deve ser deixada? Execute a mesma determinação da posição de referência com a da direita. Em seguida, para a não recursão, colocamos o subscrito baixo (nº 0) dos dados à esquerda na pilha primeiro, alto (nº 4) na pilha e coloque o novo baixo (6) Empurre a pilha e empurre o novo alto (9) na pilha;
4. Em seguida, primeiro avalie se a pilha está vazia. Se não estiver vazio, atribua o topo da pilha como alto e o segundo como baixo, e também encontre a posição, E então empurre para a pilha, pule para fora da pilha, até que a pilha esteja vazia, então ela será organizada;

Insira a descrição da imagem aqui

//非递归实现快速排序(需要一个栈)
    public static void quicksort1(int[] arr){
    
    
        Norquick(arr,0,arr.length-1);

    }
    //非递归实现快速排序
    public static void Norquick(int[] arr,int low,int high){
    
    
        Stack<Integer> stack = new Stack<>();
        int par = parttion(arr,low,high);
        if (par > low+1){
    
    
            stack.push(low);
            stack.push(par-1);
        }
        if (par < high-1){
    
    
            stack.push(par+1);
            stack.push(high);
        }
        while(!stack.empty()){
    
    
            int end = stack.pop();
            int start = stack.pop();
            par = parttion(arr,start,end);
            if (par > start+1){
    
    
                stack.push(start);
                stack.push(par-1);
            }
            if (par < end-1){
    
    
                stack.push(par+1);
                stack.push(end);
            }
        }
    }

3. Mesclar classificação

  • Conforme mostrado na figura abaixo: divida primeiro e depois mescle;
    Insira a descrição da imagem aqui
//归并排序
    public static void mergesort(int[] arr){
    
    
        mergeSortInternal(arr,0,arr.length-1);
    }
    //分割
    public static void mergeSortInternal(int[] arr,int low,int high){
    
    
        if(low >= high){
    
    
            return;
        }
        int mid = (low + high)/2;
        mergeSortInternal(arr,low,mid);
        mergeSortInternal(arr,mid+1,high);
        //分割完成,就开始合并

        merge(arr,low,high,mid);
    }
    //合并方法
    public static void merge(int[] arr,int low,int high,int mid){
    
    
        int s1 = low;
        int s2 = mid+1;
        int[] tmp = new int[high-low+1];//临时存放合并后的数据
        //开始合并
        int k = 0;//tmp开始下标
        while(s1 <= mid && s2 <= high){
    
    //俩个段都有数据
            if (arr[s1] <= arr[s2]){
    
    
                tmp[k++] = arr[s1++];

            }else{
    
    
                tmp[k++] = arr[s2++];
            }
        }
        //第一个归并段还有很多数据
        while(s1 <= mid){
    
    //第一个还有若干个数据
            tmp[k++] = arr[s1++];
        }
        while(s2 <= high){
    
    //第二个还有若干个数据
            tmp[k++] = arr[s2++];
        }
        //此时就有序了
        for (int i = 0;i < tmp.length;i++){
    
    
            arr[low+i] = tmp[i];//将临时存放好的数据给人家放回去;
        }
    }

Acho que você gosta

Origin blog.csdn.net/qq_45665172/article/details/109678230
Recomendado
Clasificación