Sete algoritmos de classificação baseados em comparação (JAVA)

Índice

Tipo de bolha

otimização:

Classificação de pilha

ordenação por inserção

Tipo de colina

classificação por mesclagem

Ordenação rápida

otimização

ordenação por seleção 


 Estabilidade do algoritmo de classificação : se elementos do mesmo tamanho tiverem a mesma posição relativa antes e depois da classificação, isso é chamado de classificação estável .

Nota: Uma classificação que é inerentemente estável pode ser implementada como uma classificação instável; mas, inversamente, uma classificação que é inerentemente instável não pode ser implementada como uma classificação estável.

Algoritmo de classificação estável : classificação por inserção, classificação por bolha, classificação por mesclagem

Tipo de bolha

Complexidade de tempo: o(n^2) Se otimização for adicionada, o melhor caso é O(N)
Complexidade de espaço: O(1)
Estabilidade: Estável

    public static void bubbleSort(int[] array){

        for (int i = 0; i < array.length-1; i++) {
            for (int j = 0; j < array.length-1; j++) {
                if (array[j] > array[j+1]) {
                    swap(array, j, j+1);
                }
            }
        }
    }

    private static void swap(int[] array, int minIndex, int i) {
        int tmp = array[i];
        array[i] = array[minIndex];
        array[minIndex] = tmp;
    }

otimização:

     public static void bubbleSort(int[] array) {
        for (int i = 0; i < array.length-1; i++) {
            boolean flg = false;
            for (int j = 0; j < array.length-1-i; j++) {
                if(array[j] > array[j+1]) {
                    swap(array,j,j+1);
                    flg = true;
                }
            }
            if(!flg) {
                return;
            }
        }
    }

Classificação de pilha

Complexidade de tempo: O(n*logN) N^1,3 -->
Complexidade de espaço: O(1)
Estabilidade: Instável
Quando a quantidade de dados é muito grande, a classificação de heap deve ser mais rápida do que o

princípio de classificação de heap de Hill:

  1. Trocar o elemento superior de um heap raiz grande pelo último elemento
  2. Diminuir o comprimento de uma matriz em um
  3. Depois de reajustar o heap em um grande heap raiz

    public static void heapSort(int[] array){

        createHeap(array);
        for (int i = 0; i < array.length - 1; i++) {
            swap(array, 0, array.length-1-i);
            shiftDown(array, 0, array.length-1-i);
        }
    }

    private static void createHeap(int[] array) {
        for (int i = (array.length-1-1)/2; i >= 0; i--) {
            shiftDown(array, i, array.length);
        }
    }

    private static void shiftDown(int[] array, int i, int length) {//length个元素
        int child = i * 2 + 1;
        while (child < length) {
            if (child + 1 < length && array[child] < array[child+1]) {
                child++;
            }
            if (array[child] > array[i]) {
                swap(array, child, i);
                i = child;
            }else {
                break;
            }
            child = i * 2 + 1;
        }
    }
    private static void swap(int[] array, int minIndex, int i) {
        int tmp = array[i];
        array[i] = array[minIndex];
        array[minIndex] = tmp;
    }

ordenação por inserção

Complexidade de tempo:
        Melhor caso: O(N) quando os dados estão completamente ordenados
        Pior caso: O(N^2) quando os dados estão completamente em ordem inversa
Complexidade do espaço: O(1)
Estabilidade: Estável


O princípio da classificação por inserção

  1. Faça os códigos-chave um por um, começando pelo primeiro à esquerda
  2. Da esquerda para a direita, insira os registros a serem classificados na sequência classificada à esquerda, um por um, de acordo com o tamanho de seus valores-chave.
  3. Até que todos os registros sejam inseridos, uma nova sequência ordenada é obtida
    public static void insertSort(int[] array){

        for (int i = 1; i < array.length; i++) {
            int tmp = array[i];
            int j = i - 1;
            for (; j >= 0 ; j--) {
                //如果此处改为array[j] >= tmp就会变成不稳定排序
                if (array[j] > tmp) {
                    array[j+1] = array[j];
                }else{
                    break;
                }
            }
            array[j+1] = tmp;
        }
    }

Tipo de colina

Complexidade de tempo:
             aproximadamente igual a: n^1,3 - n^1,5
Complexidade: O(1)
Estabilidade: instável

A classificação por colina é na verdade uma otimização da classificação por inserção

Fundamental:

  1. Primeiro divida a matriz em vários grupos de acordo com o tamanho do passo
  2. Classificação de inserção para cada grupo
  3. Reduza o tamanho do passo e repita as etapas acima

    public static void shellSort(int[] array){

        int gap = array.length;
        while (gap > 1) {
            gap = gap / 2;
            shell(array, gap);
        }
    }

    private static void shell(int[] array, int gap) {
        for (int i = gap; i < array.length; i++) {
            int tmp = array[i];
            int j = i-gap;
            for (; j >= 0; j -= gap) {
                if (array[j] > tmp) {
                    array[j+gap] = array[j];
                }else {
                    break;
                }
            }
            array[j+gap] = tmp;
        }
    }

classificação por mesclagem

Complexidade de tempo: 0(N*logN)
Complexidade de espaço: O(n)
Estabilidade: Estável

Merge sort é um algoritmo de classificação eficaz baseado em operações de mesclagem.Este algoritmo é uma aplicação muito típica do método dividir e conquistar. Mesclar as subsequências já ordenadas para obter uma sequência completamente ordenada; isto é, primeiro torne cada subsequência ordenada e depois ordene os segmentos da subsequência.

Consulte: icon-default.png?t=N7T8http://t.csdnimg.cn/Yd62c

    public void mergerSort(int[] nums, int left, int right) {//right:数组长度减一
        if (left >= right) {
            return;
        }
        int mid = (left + right) / 2;
        mergerSort(nums, left, mid);
        mergerSort(nums, mid + 1, right);
        merger(nums, left, mid, right);
    }

    private void merger(int[] nums, int left, int mid, int right) {
        int[] tmp = new int[right-left+1];
        int i = 0;
        int l = left;
        int r = mid + 1;
        while (l <= mid && r <= right) {
            if (nums[l] < nums[r]) {
                tmp[i++] = nums[l++];
            }else {
                tmp[i++] = nums[r++];
            }
        }
        while (l <= mid) {
            tmp[i++] = nums[l++];
        }
        while (r <= right) {
            tmp[i++] = nums[r++];
        }
        i = 0;
        for (int j = 0; j < tmp.length; j++) {
            nums[left++] = tmp[j];
        }
    }

Ordenação rápida

Complexidade de tempo:
        Melhor caso: O(N*logN) árvore binária completa/árvore binária completa
        Pior caso: O(N^2) árvore de ramo único
Complexidade de espaço:
        Melhor caso: O(logN) árvore binária completa/árvore binária completa
        Pior caso: O(N) árvore de galho único
Estabilidade: instável

Princípios básicos de classificação rápida

  1. Pegue qualquer elemento na sequência de elementos a ser classificado como o valor base
  2. Divida o conjunto a ser classificado em duas subsequências de acordo com este código de classificação.Todos os elementos na subsequência esquerda são menores que o valor de referência e todos os elementos na subsequência direita são maiores que o valor de referência.
  3. Repita este processo para cada subsequência até que todos os elementos estejam organizados na posição correspondente

Existem o método Hoare, o método de escavação e o método do ponteiro frontal e traseiro,
aqui apresentamos apenas o método Hoare .

    public static void quickSort(int[] array){

        quick(array, 0, array.length-1);
    }

    private static void quick(int[] array, int left, int right) {
        if (left >= right) {
            return;
        }
        int Index = findSwap(array, left, right);
        quick(array, left, Index-1);
        quick(array, Index+1, right);

    }
    
    private static int findSwap(int[] array, int left, int right) {
        int key = array[left];
        int keyIndex = left;
        while (left < right) {
            //必须right先走
            //如果是left先走,两个相遇的地方一定比key大
            while (left < right && array[right] >= key) {
                right--;
            }
            while (left < right && array[left] <= key) {
                left++;
            }
            swap(array, right, left);
        }
        if (left == right) {
            swap(array, keyIndex, left);
        }
        return left;
    }

    private static void swap(int[] array, int minIndex, int i) {
        int tmp = array[i];
        array[i] = array[minIndex];
        array[minIndex] = tmp;
    }

otimização

Use o método dos três números para evitar a formação de galhos (tente reduzir a altura da árvore)

    public int[] sortArray(int[] nums) {
        //快速排序
        quickSort(nums, 0, nums.length-1);
        return nums;
    }

    private void quickSort(int[] nums, int left, int right) {
        if (left >= right) {
            return;
        }
        //三数取中法
        swap(nums, left, threeNumMid(nums, left, right));
        //也可以在这里加一个判断当左右之间的数据个数小于一定值然后调用插入排序
        //因为在排序过程中数组会趋近于有序所以插入排序的效率会很快
        int pivot = quick(nums, left, right);
        quickSort(nums, left, pivot-1);
        quickSort(nums, pivot+1, right);
    }

    private int threeNumMid(int[] nums, int left, int right) {
        int mid = (left + right) / 2;
        if (nums[left] > nums[right]) {
            if (nums[mid] > nums[left]) {
                return left;
            }else if (nums[mid] < nums[right]) {
                return right;
            }else {
                return mid;
            }
        }else {
            if (nums[mid] < nums[left]) {
                return left;
            }else if (nums[mid] > nums[right]) {
                return right;
            }else {
                return mid;
            }
        }
    }

    private int quick(int[] nums, int left, int right) {
        int index = left;
        int key = nums[left];
        while (left < right) {
            while (left < right && nums[right] >= key) {
                right--;
            }
            while (left < right && nums[left] <= key) {
                left++;
            }
            swap(nums, right, left);
        }
        swap(nums, index, left);
        return left;
    }

    private void swap(int[] nums, int left, int right) {
        int tmp = nums[left];
        nums[left] = nums[right];
        nums[right] = tmp;
    }

ordenação por seleção 

Complexidade de tempo: O (n ^ 2)
Complexidade de espaço: O (1)
Estabilidade: classificação instável

Princípios básicos de classificação por seleção:

  1. Selecione o menor (ou maior) elemento dos elementos de dados a serem classificados sempre da esquerda para a direita.
  2. Coloque-o no início dos elementos a serem ordenados e no final dos elementos ordenados
  3. Repita as etapas acima até que todos os elementos de dados a serem classificados estejam organizados.
    public static void selectSort(int[] array){

        for (int i = 0; i < array.length; i++) {
            int minIndex = i;
            for (int j = i+1; j < array.length; j++) {
                if (array[minIndex] > array[j]) {
                    minIndex = j;
                }
            }
            swap(array, minIndex, i);
        }
    }

    private static void swap(int[] array, int minIndex, int i) {
        int tmp = array[i];
        array[i] = array[minIndex];
        array[minIndex] = tmp;
    }

Acho que você gosta

Origin blog.csdn.net/2302_76339343/article/details/133498231
Recomendado
Clasificación