Ordenación por fusión y ordenación rápida Implementación de Java y comparación en profundidad

"Algoritmo" en la cuarta edición: la clasificación recursiva y la clasificación rápida reflejan la idea de dividir y conquistar. Sin embargo, el cálculo de la fusión se consume principalmente en la operación de fusión de sub-vectores, pero la ordenación rápida es lo contrario.
Este artículo usa Java para dar el código y luego realizar una comparación en profundidad

Ordenación rápida

Primero da el pseudocódigo de ideas:

void quick_sort(⼀个数组) {
     if (可以很容易处理) *用插入排序;
     quick_sort(左半个数组);
     quick_sort(右半个数组);
     partition(左半个数组, 右半个数组);
}

Implementación específica (puede ejecutar la prueba IDE)

public class QuickSort{
    //先找切分左右子序列的index,将它的初始位置优化
    //好处是:序列里随机分布的大量重复元素可不必重新递归调用
    public static void quickSort(int[] arr,int lo ,int hi){
        if(lo<hi) {
            int index = partition(arr, lo, hi);
            quickSort(arr, lo, index - 1);
            quickSort(arr, index + 1, hi);
        }
    }
    //先通过partition方法将切分元素index的左右子序列进行排序
    public static int partition(int[] arr,int lo,int hi){
        //取左位为基准元素,则先从右边开始对比
        int key=arr[lo];
        //这里不用交换直接赋值
        while(lo<hi){
            //从序列右端开始,向左遍历,直到找到小于base的数
            while(arr[hi]>=key && hi>lo){ hi--; }
            arr[lo]=arr[hi]; //找到了比base小的元素,放到最左边
            //从序列左端开始,向右遍历,直到找到大于base的数
            while(arr[lo]<=key && hi>lo){ lo++; }
            arr[hi]=arr[lo]; //找到了比base大的元素,放到最右边
        }
        arr[lo]=key;//将备份的切分元素放回左右子序列之间
        return lo; // 此时lo=hi,切分元素给arr[lo]和arr[hi]一样
    }

    public static void main(String[] args) {
        int[] arr = new int[50];
        for (int i = 49; i >=0; i++) {
            arr[i] = i;
            quickSort(arr,0,arr.length);
        }
        quickSort(arr,0,arr.length-1);
        System.out.println(Arrays.toString(arr));
    }
}

Ordenar fusión

Primero da el pseudocódigo de ideas:

void merge_sort(⼀个数组) {
     if (可以很容易处理) return;
     merge_sort(左半个数组);
     merge_sort(右半个数组);
     merge(左半个数组, 右半个数组);
}

Implementación específica (puede ejecutar la prueba IDE):

public class MergeSort {
    public static void mergeSort(int[] arr){
    //在排序前,先建好一个长度等于原数组长度的临时数组,避免递归中频繁开辟空间
        int []temp = new int[arr.length];
        sort(arr,0,arr.length-1,temp);
    }
    private static void sort(int[] arr,int left,int right,int []temp){
        if(left<right){
            int mid = (left+right)/2;
            sort(arr,left,mid,temp);//左边归并排序,使得左子序列有序
            sort(arr,mid+1,right,temp);//右边归并排序,使得右子序列有序
            merge(arr,left,mid,right,temp);//将两个有序子数组合并操作
        }
    }
    private static void merge(int[] arr,int left,int mid,int right,int[] temp){
        int i = left;//左序列指针
        int j = mid+1;//右序列指针
        int t = 0;//临时数组指针
        while (i<=mid && j<=right){
            if(arr[i]<=arr[j]){
                temp[t++] = arr[i++];
            }else {
                temp[t++] = arr[j++];
            }
        }
        while(i<=mid){//将左边剩余元素填充进temp中
            temp[t++] = arr[i++];
        }
        while(j<=right){//将右序列剩余元素填充进temp中
            temp[t++] = arr[j++];
        }
        t = 0;//指针回到临时数组首位
        //将temp中的元素全部拷贝到原数组中
        while(left <= right){
            arr[left++] = temp[t++];
        }
    }
    public static void main(String []args){
        int []arr = {9,8,7,6,5,4,3,2,1};
        mergeSort(arr);
        System.out.println(Arrays.toString(arr));
    }
}

La única diferencia entre el método recursivo de fusión y la ordenación rápida es que la fusión es recursiva y luego ordenada. Quicksort se clasifica primero en segmentación recursiva.

Comparación de dos tipos

  • Similitudes: en comparación con otras clasificaciones primarias, ambas clasificaciones usan segmentación en lugar de transversal directo
  • Diferencias:
    (1) El orden de fusión es asintóticamente óptimo. Asegúrese de que el peor de los casos sea O (nlgn), que no puede hacerse de otro tipo. La limitación es que el espacio es O (n) y no está ordenado en su lugar.
    (2) La clasificación rápida es muy adecuada para secuencias de distribución aleatoria convencionales. La mayoría de los casos son O (nlogn), solo O (logn) en el espacio. Pero es algo inestable. Cuando se incluyen elementos repetidos, la segmentación de tres vías se utiliza para optimizar la complejidad.

Si te resulta útil, por favor dame un visto bueno. Si tienes alguna pregunta, bienvenido a comunicarte, trabajaré más duro para compartir contenido de alta calidad con todos ~~

Publicado 29 artículos originales · elogiado 4 · visitas 2194

Supongo que te gusta

Origin blog.csdn.net/smile001isme/article/details/105430302
Recomendado
Clasificación