66 - classificação por inserção

Índice

1. Classificação por inserção direta

2. Classificação de inserção binária

3. Use a classificação por inserção no array arr[l...r]


Semelhante a jogar pôquer, ao classificar as cartas, as cartas aleatórias são inseridas na classificação de inserção natural de cartas já codificadas.

1. Classificação por inserção direta

Selecione o primeiro elemento do intervalo não ordenado a cada vez, insira-o na posição apropriada do intervalo ordenado e repita esse processo até que toda a matriz esteja em ordem. O intervalo inteiro é dividido em um intervalo ordenado [0, i) e um intervalo não ordenado [i, n).

 /**
  * 直接插入排序 稳定的
  * 每次选择无序区间的第一个元素,插入到有序区间的合适位置
  * @param arr
  */
public static void insertionSortBase(int[] arr) {
    //有序区间[0,i) [0,1)
    //默认第一个元素就是有序
    for (int i = 1; i < arr.length; i++) {
        //每次选择无序区间的第一个元素,插入到有序区间的合适位置
        //无序区间[i, n)
        for (int j = i; j > 0 && arr[j] < arr[j - 1]; j--) {
            swap(arr, j, j-1);
            //arr[j] > arr[j - 1]此时循环直接终止
            //arr[j - 1]已经是有序区间元素,大于前面的所有值
        }
    }
}

Estabilidade: Estável.

arr[j] > arr[j - 1] o loop é encerrado, portanto, a ordem dos elementos iguais antes e depois da classificação não será alterada.

desempenho:

Complexidade de tempo: n * 1 + (n - 1) * 2 + (n - 2) * 3 + ... + 2 * (n - 1) + 1 * n => O(n ^ 2)

A maior diferença entre classificação por inserção e classificação por seleção é: se arr[j] >= arr[j - 1], o loop pode ser encerrado diretamente e arr[j - 1] já é um elemento de intervalo ordenado.

A classificação por inserção funciona muito bem em tamanhos de dados pequenos, em matrizes quase ordenadas. É frequentemente usado como um método de otimização para algoritmos de classificação avançados.

2. Classificação de inserção binária

Ao selecionar a posição onde os dados devem ser inseridos em um intervalo ordenado, devido à ordem do intervalo, pode-se utilizar a ideia de busca binária (binary search) para localizar rapidamente a posição de inserção.

/**
 * 折半插入排序
 * @param arr
 */
public static void insertionSortBS(int[] arr) {
    for (int i = 1; i < arr.length; i++) {
        //无序区间第一个值
        int val = arr[i];
        //有序区间[0,i)
        int low = 0;
        int high = i;
        while(low < high) {
            int mid = (low + high) >> 1;
            //将相等的值放在左半区间,保证稳定性
            if(val >= arr[mid]) {
                low = mid + 1;
            }else{
                //右区间取不到,不用 -1
                high = mid;
            }
        }
        //数据搬移
        for (int j = i; j > low; j--) {
            arr[j] = arr[j - 1];
        }
        //low就是元素插入位置
        arr[low] = val;
    }
}

Estabilidade: Estável.

Complexidade de tempo: n * logn + n * (1...n) => O(N^2)

A classificação por inserção binária (comparar e trocar um por um, O(logn)) é mais rápida do que a classificação por inserção direta (mover elementos após encontrar a posição de inserção, O(n)) principalmente na pesquisa (pesquisa de intervalo ordenado).

O número de movimentos == o número de trocas (porque a posição final de inserção é a mesma).

3. Use a classificação por inserção no array arr[l...r]

/**
 * 在数组arr[l...r]上使用插入排序
 * @param arr
 * @param l
 * @param r
 */
private static void insertBase(int[] arr, int l, int r) {
    //有序的区间[l...i]
    //无序的区间[i...r]
    for (int i = l + 1; i <= r; i++) {
        for (int j = i; j > l && arr[j] < arr[j - 1]; j--) {
            swap(arr, j, j - 1);
        }
    }
}

Acho que você gosta

Origin blog.csdn.net/WWXDwrn/article/details/130027659
Recomendado
Clasificación