Algoritmo clásico de clasificación y resumen (implementación de Python)

1. Los conceptos básicos y la clasificación de la clasificación.

La llamada clasificación es hacer una serie de registros, de acuerdo con el tamaño de una o algunas palabras clave, la operación de aumentar o disminuir. El algoritmo de clasificación es cómo hacer que los registros se organicen de acuerdo con los requisitos.

Estabilidad de clasificación:

Después de cierta clasificación, si los dos registros tienen el mismo número de serie y el orden de los dos registros en los registros originales no ordenados permanece sin cambios, se dice que el método de clasificación utilizado es estable, de lo contrario es inestable.

Clasificación interna y externa

Clasificación interna: durante la clasificación, todos los registros que se ordenarán se colocan en la memoria
Clasificación externa: durante la clasificación, se utiliza el almacenamiento externo.
Por lo general, la discusión está dentro de la clasificación.

Tres factores que afectan el rendimiento del algoritmo de clasificación interno:

  • Complejidad del tiempo: es decir, el rendimiento del tiempo, el algoritmo de clasificación eficiente debe tener la menor cantidad posible de comparaciones de palabras clave y movimientos grabados
  • Complejidad del espacio: principalmente el espacio auxiliar requerido para ejecutar el algoritmo, cuanto menos mejor.
  • Algoritmo de complejidad. Se refiere principalmente a la complejidad del código.

De acuerdo con las operaciones principales utilizadas en el proceso de clasificación, la clasificación interna se puede dividir en:

  • Insertar ordenación
  • Orden de cambio
  • Seleccionar orden
  • Ordenar fusión

Según la complejidad del algoritmo, se puede dividir en dos categorías:

  • Algoritmo simple: incluye clasificación de burbujas, clasificación de selección simple y clasificación de inserción directa
  • Algoritmo mejorado: incluye clasificación de Hill, clasificación de montón, clasificación de combinación y clasificación rápida

Los siguientes siete algoritmos de clasificación son solo los más clásicos entre todos los algoritmos de clasificación, pero no todos.

2. Bubble Sort BubbleSort

Introducción

El principio del ordenamiento de burbujas es muy simple: visita repetidamente la secuencia a ordenar, compara dos elementos a la vez y los intercambia si su orden es incorrecto.

Pasos:

  1. Compara elementos adyacentes. Si el primero es más grande que el segundo, intercambie ambos.
  2. Haga lo mismo para los datos 0th a n-1th. En este momento, el número más grande "flota" hasta la última posición de la matriz.
  3. Repita los pasos anteriores para todos los elementos excepto el último.
  4. Continúe repitiendo los pasos anteriores para cada vez menos elementos hasta que no haya pares de números para comparar.

Implementación de Python

def bubble_sort(arr):
    n = len(arr)
    # 遍历所有数组元素
    for i in range(n):
        for j in range(0, n - i - 1):
            if arr[j] > arr[j + 1]:		#如果前者比后者大
                arr[j], arr[j + 1] = arr[j + 1], arr[j]		 #则交换两者
    return print(arr)

arr = [64, 34, 25, 12, 22, 11, 90]

bubble_sort(arr)

3. Selección de selección SelectionSort

Introducción

La clasificación por selección es, sin duda, la clasificación más simple e intuitiva. Funciona de la siguiente manera.

Pasos:

  1. Encuentre el elemento más pequeño (grande) en la secuencia no ordenada y guárdelo al comienzo de la secuencia ordenada.
  2. Luego, continúe buscando el elemento más pequeño (grande) de los elementos no ordenados restantes y luego colóquelo al final de la secuencia ordenada.
  3. Y así sucesivamente, hasta que todos los elementos estén ordenados.

Implementación de Python

def select_sort(arr):
    n = len(arr)
    for i in range(n):
        min = i  # 最小元素下标标记
        for j in range(i + 1, n):
            if arr[j] < arr[min]:
                min = j  # 找到最小值的下标
        arr[min], arr[i] = arr[i], arr[min]  # 交换两者
    return print(arr)

arr = [64, 34, 25, 12, 22, 11, 90]
select_sort(arr)

4. Insertar Ordenar Insertar Ordenar

Introducción

El principio de funcionamiento de la ordenación por inserción es que para cada dato no ordenado, escanea de atrás hacia adelante en la secuencia ordenada, encuentra la posición correspondiente e inserta.

Pasos:

  1. A partir del primer elemento, se puede considerar que el elemento ha sido ordenado
  2. Tome el siguiente elemento y escanee de atrás hacia adelante en la secuencia de elementos ordenados
  3. Si el elemento escaneado (ordenado) es más grande que el nuevo elemento, mueva el elemento hacia atrás un bit
  4. Repita el paso 3 hasta que encuentre la posición del elemento ordenado menor o igual que el nuevo elemento
  5. Después de insertar el nuevo elemento en esta posición
  6. Repita los pasos 2 ~ 5

Demostración de clasificación:

img

Implementación de Python

def inset_sort(arr):
    n = len(arr)
    for i in range(1,n):
        if arr[i] < arr[i-1]:
            temp = arr[i]
            index = i  # 待插入的下标
            for j in range(i-1,-1,-1):   # 从i-1 循环到 0 包括0
                if arr[j] > temp:
                    arr[j+1] = arr[j]
                    index = j   # 记录待插入的下标
                else:
                    break
            arr[index] = temp
    return print(arr)

arr = [64, 34, 25, 12, 22, 11, 90]
inset_sort(arr)

5. Hill Sort ShellSort

Introducción

La ordenación en pendiente, también denominada algoritmo de ordenación incremental descendente , consiste esencialmente en agrupar la ordenación por inserción. Propuesto por Donald Shell en 1959. La clasificación en pendientes es un algoritmo de clasificación inestable.

La idea básica de la clasificación de Hill es listar la matriz en una tabla e insertar y ordenar las columnas por separado. Repita este proceso, pero cada vez con una columna más larga (el tamaño del paso es más largo y el número de columnas es menor). . Finalmente, toda la tabla tiene solo una columna. La conversión de la matriz a la tabla es para comprender mejor el algoritmo, el algoritmo en sí mismo todavía utiliza la matriz para ordenar.

Por ejemplo, supongamos que existe tal conjunto de números [ 13 14 94 33 82 25 59 94 65 23 45 27 73 25 39 10 ], si comenzamos a ordenar con un tamaño de paso de 5, podemos describir mejor el algoritmo colocando esta lista en una tabla con 5 columnas, por lo que deberían verse así:

13 14 94 33 82
25 59 94 65 23
45 27 73 25 39
10

Luego clasificamos cada columna:

10 14 73 25 23
13 27 94 33 39
25 59 94 65 82
45

Cuando las anteriores cuatro líneas de números, que se reúnen en secuencia: [ 10 14 73 25 23 13 27 94 33 39 25 59 94 65 82 45 ]. En este momento, 10 se movió a la posición correcta y luego se ordenó en pasos de 3:

10 14 73
25 23 13
27 94 33
39 25 59
94 65 82
45

Después de ordenar se convierte en:

10 14 13
25 23 33
27 25 59
39 65 73
45 94 82
94

Finalmente, ordene por 1 paso (este es un tipo de inserción simple).

Implementación de Python

def shell_sort(ary):
    n = len(ary)
    gap = round(n/2)       #初始步长 , 用round四舍五入取整
    while gap > 0 :
        for i in range(gap,n):        #每一列进行插入排序 , 从gap 到 n-1
            temp = ary[i]
            j = i
            while ( j >= gap and ary[j-gap] > temp ):    #插入排序
                ary[j] = ary[j-gap]
                j = j - gap
            ary[j] = temp
        gap = round(gap/2)                     #重新设置步长
    return print(ary)
ary = [13, 14, 94, 33, 82, 25, 59, 94, 65, 23, 45, 27, 73, 25, 39, 10]
shell_sort(ary)

6. Combinar Ordenar Combinar Ordenar

Introducción

El tipo de fusión es una aplicación muy típica del método de dividir y conquistar. 归并La idea de ordenar es 递归descomponer la matriz primero y luego fusionarla.

Primero considere fusionar dos matrices ordenadas. La idea básica es comparar el primer número de las dos matrices. Quien sea más joven tomará la primera, y después de tomarla, el puntero correspondiente retrocederá un bit. Luego compare nuevamente hasta que una matriz esté vacía, y finalmente copie el resto de la otra matriz.

Considere la descomposición recursiva, la idea básica es la de romper en una matriz lefty right, si se ordenan los dos conjuntos de datos internas, a continuación, puede utilizar el método anterior de combinación de las dos matrices de matrices se fusionan tipo. ¿Cómo hacer estos dos arreglos ordenados internamente? Se puede volver a dividir en dos hasta que el grupo descompuesto contenga solo un elemento. En este momento, se considera que hay un orden dentro del grupo. Luego puede fusionar y ordenar los dos grupos adyacentes.

Demostración de clasificación:

img

Implementación de Python

def merge_sort(ary):
    if len(ary) <= 1:
        return ary
    num = int(len(ary) / 2)  # 二分分解
    left = merge_sort(ary[:num])
    right = merge_sort(ary[num:])
    return merge(left, right)  # 合并数组

def merge(left, right):
'''合并操作,
将两个有序数组left[]和right[]合并成一个大的有序数组
'''
l, r = 0, 0 # left与right数组的下标指针
result = []
while l < len(left) and r < len(right):
if left[l] < right[r]:
result.append(left[l])
l += 1
else:
result.append(right[r])
r += 1
result += left[l:]
result += right[r:]
return result

ary = [13, 14, 94, 33, 82, 25, 59, 94, 65, 23, 45, 27, 73, 25, 39, 10]
merge_sort(ary)

7. Clasificación rápida

Introducción: la
ordenación rápida suele ser obviamente más rápida que otros algoritmos con el mismo Ο (n log n) , por lo que a menudo se usa, y la ordenación rápida adopta la idea del método de dividir y conquistar , por lo que en muchas entrevistas escritas, a menudo puede ver la ordenación rápida. Sombra Se puede ver que la importancia de dominar pelotón rápido.

Pasos:

  1. Elija un elemento de la serie como el número base.
  2. En el proceso de partición, los más grandes que el número de referencia se colocan a la derecha, y los números menores o iguales a él se colocan a la izquierda.
  3. Luego, realice recursivamente el segundo paso en los intervalos izquierdo y derecho hasta que cada intervalo tenga solo un número.

Demostración de clasificación:

img

Implementación de Python

def quick_sort(ary):
    return qsort(ary, 0, len(ary) - 1)

def qsort(ary, left, right):
# 快排函数,ary为待排序数组,left为待排序的左边界,right为右边界
if left >= right:
return ary
key = ary[left] # 取最左边的为基准数
lp = left # 左指针
rp = right # 右指针
while lp < rp:
while ary[rp] >= key and lp < rp:
rp -= 1
while ary[lp] <= key and lp < rp:
lp += 1
ary[lp], ary[rp] = ary[rp], ary[lp]
ary[left], ary[lp] = ary[lp], ary[left]
qsort(ary, left, lp - 1)
qsort(ary, rp + 1, right)
return ary

ary = [13, 14, 94, 33, 82, 25, 59, 94, 65, 23, 45, 27, 73, 25, 39, 10]
quick_sort(ary)

def quick_sort(a, start, end):
    if start < end:
        i, j = start, end  # 记录当前索引值
        base = a[i]  # 设置基准

        while i < j:
            while (i < j) and (a[j] >= base):
                j -= 1
            a[i] = a[j]

            while (i < j) and (a[i] <= base):
                i += 1
            a[j] = a[i]
        a[i] = base
        quick_sort(a, start, i - 1)
        quick_sort(a, j + 1, end)
    return print(a)


a = [13, 14, 94, 33, 82, 25, 59, 94, 65, 23, 45, 27, 73, 25, 39, 10]
quick_sort(a, 0, len(a) - 1)

8. HeapSort

Introducción

La ordenación del montón se usa con frecuencia en los principales problemas de K. La ordenación del montón se implementa utilizando una estructura de datos de bifurcación binaria, aunque es esencialmente una matriz unidimensional. El montón binario es un árbol binario aproximadamente completo.

El montón binario tiene las siguientes propiedades:

  1. El valor clave del nodo primario siempre es mayor o igual que (menor o igual que) el valor clave de cualquier nodo secundario.
  2. Los subárboles izquierdo y derecho de cada nodo son un montón binario (tanto el montón más grande como el más pequeño).

Pasos:

  1. Generar almacenamiento dinámico máximo (Build_Max_Heap): si el rango del subíndice de la matriz es 0 ~ n, teniendo en cuenta que un solo elemento es un montón de raíz grande, entonces n/2los elementos que comienzan desde el subíndice son todos grandes montones de raíz. Por lo tanto, siempre que el n/2-1montón de raíz grande se construya en orden desde el principio, esto puede garantizar que cuando se construye un nodo, sus subárboles izquierdo y derecho ya sean grandes pilas de raíz.
  2. Heap sort (HeapSort): porque el montón se simula con una matriz. Después de obtener un montón de raíz grande, la matriz no está ordenada. Por lo tanto, la matriz colmada necesita ser ordenada. La idea es eliminar el nodo raíz y realizar la operación recursiva de ajuste de almacenamiento dinámico máximo. La primera vez heap[0]con el heap[n-1]cambio, y luego a heap[0...n-2]hacer el ajuste máximo del montón. La segunda será heap[0]el heap[n-2]cambio y, a continuación, a heap[0...n-3]realizar el ajuste máximo del montón. Repita esta operación hasta heap[0]e heap[1]intercambie. Como el número más grande se fusiona en el siguiente rango ordenado cada vez, se ordena toda la matriz después de la operación.
  3. Ajuste de almacenamiento dinámico máximo (Max_Heapify): este método se proporciona para los dos procedimientos anteriores. El propósito es ajustar los nodos secundarios al final del montón para que los nodos secundarios sean siempre más pequeños que el nodo primario.

Demostración de clasificación:

img

Implementación de Python

def heap_sort(ary):
    n = len(ary)
    first = int(n / 2 - 1)  # 最后一个非叶子节点
    for start in range(first, -1, -1):  # 构造大根堆
        max_heapify(ary, start, n - 1)
    for end in range(n - 1, 0, -1):  # 堆排,将大根堆转换成有序数组
        ary[end], ary[0] = ary[0], ary[end]
        max_heapify(ary, 0, end - 1)
    return print(ary)

最大堆调整:将堆的末端子节点作调整,使得子节点永远小于父节点

start为当前需要调整最大堆的位置,end为调整边界

def max_heapify(ary, start, end):
root = start
while True:
child = root * 2 + 1 # 调整节点的子节点
if child > end: break
if child + 1 <= end and ary[child] < ary[child + 1]:
child = child + 1 # 取较大的子节点
if ary[root] < ary[child]: # 较大的子节点成为父节点
ary[root], ary[child] = ary[child], ary[root] # 交换
root = child
else:
break

ary = [13, 14, 94, 33, 82, 25, 59, 94, 65, 23, 45, 27, 73, 25, 39, 10]
heap_sort(ary)

Comparación de rendimiento de siete algoritmos de clasificación

La siguiente es una comparación de los indicadores de siete algoritmos de clasificación clásicos:

img

  • Si la secuencia a ordenar se ordena básicamente, utilice un algoritmo simple directamente y no utilice un algoritmo mejorado complejo.
  • Aunque la ordenación por fusión y la ordenación rápida tienen un alto rendimiento, requieren más espacio auxiliar. De hecho, es usar el espacio para el tiempo.
  • Cuanto menor sea el número de elementos en la secuencia a clasificar, más adecuado es el método de clasificación simple; cuanto mayor sea el número de elementos, más adecuado es el algoritmo de clasificación mejorado.
  • Aunque la selección simple no es buena en términos de rendimiento de tiempo, tiene un alto rendimiento en la utilización del espacio. Es particularmente adecuado para ese tipo de elementos con una pequeña cantidad de datos y una gran cantidad de información en cada pieza de datos.

Supongo que te gusta

Origin www.cnblogs.com/sq1995liu/p/12756319.html
Recomendado
Clasificación