La expectativa del algoritmo de clasificación es el algoritmo de selección de tiempo lineal (versión Java)

Antes de comprender el algoritmo de selección, estamos familiarizados con un término 顺序统计量. En el conjunto, el i-ésimo se 数序统计量refiere al i-ésimo elemento más pequeño del conjunto.
El problema que trata el algoritmo de selección es encontrar el i-ésimo 顺序统计量problema en el conjunto de n elementos . Si i=3necesita encontrar el tercer elemento más pequeño del conjunto

Idea básica

Usando la idea de divide y vencerás, basada 快速排序en el algoritmo de partición en, se 顺序统计量resuelve de forma recursiva según la ubicación que se busque .

  • Descomposición del problema: utilice el algoritmo de partición (consulte el 快速排序capítulo) para particionar la matriz, determine la posición de partición de i y proceda de forma recursiva.
  • Manejo de problemas: cuando la ubicación de la muestra de partición es igual a i, devuelve el resultado.

Código

La 快速排序diferencia con el algoritmo de partición del medio es que el algoritmo de partición aquí agrega una función de muestreo aleatorio; consulte el código para obtener más detalles.

    /**
     * 获取数组任意位置的顺序统计量
     * @param array 输入数组
     * @param pos 查询位置
     * @param start 起始位置
     * @param end 结束位置
     * @return 元素值
     */
    private static int randomSelection(int[] array, int pos, int start, int end) {
    
    
        //获取随机分区的样本位置
        int mid = randomPartition(array, start, end);
        //递归结束点,当要获取的 pos=mid 时
        if (pos == mid) {
    
    
            return array[mid];
        }
        System.out.println("start:" + start + "|end:" + end + "|pos:" + pos + "|mid:" + mid);
        //递归情况
        if (pos < mid) {
    
    
            return randomSelection(array, pos, start, mid - 1);
        } else {
    
    
            return randomSelection(array, pos, mid + 1, end);
        }
    }

    /**
     * 随机分区
     * @param array 分区数组
     * @param start 起始位置
     * @param end 结束位置
     * @return 样本位置
     */
    private static int randomPartition(int[] array, int start, int end) {
    
    
        //计算随机样本位置
        int samplePos = random(start, end);
        //将随机样本放到数组尾部
        int temp = array[end];
        array[end] = array[samplePos];
        array[samplePos] = temp;

        int sample = array[end];
        //左侧区域默认为空
        int leftEnd = start - 1;
        //检测到小于样本值的数据,放入左侧区域
        for (int i = start; i < end; i++) {
    
    
            if (array[i] <= sample) {
    
    
                leftEnd++;
                temp = array[leftEnd];
                array[leftEnd] = array[i];
                array[i] = temp;
            }
        }
        //将样本中放到中间区域
        temp = array[end];
        array[end] = array[leftEnd + 1];
        array[leftEnd + 1] = temp;

        return leftEnd + 1;
    }

Conclusión

La idea de dividir y conquistar es realmente buena, pero este código no está completamente 算法导论implementado y StackOverflowse encuentra una excepción en el medio Parece que la capacidad del algoritmo debe mejorarse.

Supongo que te gusta

Origin blog.csdn.net/lijie2664989/article/details/85042685
Recomendado
Clasificación