[Estructura de datos--Algoritmo de clasificación manual Parte 4] Clasificación de montones, un artículo lo llevará a comprender la clasificación de montones

Tabla de contenido

1. Aplicación de montón -- clasificación de montón

1.1 Análisis de la idea de heap sorting

2. Construye un montón

2.1 Ajuste hacia arriba para construir el montón: O(N*logN)

2.1.1 Ajustar el código hacia arriba

2.1.2 Ajuste hacia arriba del código de construcción de montones

2.2 Ajustando el montón hacia abajo: O(N)

2.2.1 Ajustar el código hacia abajo

2.2.2 Ajustar el código de construcción de montón hacia abajo

3. Código de implementación de clasificación de almacenamiento dinámico

4. Prueba de ordenación en montón


1. Aplicación de montón -- clasificación de montón

El montón es un árbol binario completo, y el árbol binario completo utiliza matrices para almacenar datos de manera óptima.

Heap sorting es usar la idea de heap para ordenar Se divide en dos pasos:
1. Construir un montón

Orden ascendente: construye una pila grande

Orden descendente: construir un montón pequeño

2. Usa la idea de la eliminación del montón para ordenar

El ajuste descendente se utiliza tanto en la creación como en la eliminación de almacenamiento dinámico, por lo que la clasificación del almacenamiento dinámico se puede completar dominando el ajuste descendente.

1.1 Análisis de la idea de heap sorting

En este artículo, usamos un montón pequeño para explicar, y la clasificación del montón pequeño está en orden descendente.

Los estudiantes que no saben mucho sobre montón pueden echar un vistazo al artículo de montón: haga clic aquí para saltar

1. Primero ajustamos los elementos de la matriz hacia abajo para construir un montón pequeño;

2. El elemento superior del montón pequeño debe ser el más pequeño de la matriz, por lo que intercambiamos el elemento superior (el primer elemento de la matriz) con el último elemento de la matriz y consideramos el elemento faltante al final de la matriz. como un elemento en la matriz (tamaño-- ) , luego comience desde la parte superior del montón para ajustar y reconstruir el montón pequeño, y repítalo para lograr una clasificación descendente (el orden ascendente se puede lograr cambiando el montón pequeño a un montón grande ).

2. Construye un montón

Podemos usar el ajuste hacia arriba para construir montones, o usar el ajuste hacia abajo para construir montones.¿Cómo debemos elegir?

Luego debo elegir el que tenga la complejidad de tiempo más baja. A continuación, analicemos la complejidad de tiempo de los dos montones:

2.1 Ajuste hacia arriba para construir el montón: O(N*logN)

2.1.1 Ajustar el código hacia arriba

void AdjustUp(HPDataType* a, int child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		if (a[child] < a[parent])//这里控制大小堆
		{
			Swap(&a[child], &a[parent]);

			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}

2.1.2 Ajuste hacia arriba del código de construcción de montones

//建堆 -- 向上调整,时间复杂度:O(N*log(N))
for (int i = 0; i < size; i++)
{
	AdjustUp(a, i);
}

Dibujemos una imagen para analizar la complejidad temporal de la construcción del montón de ajuste ascendente:

El montón es un árbol binario completo, y el árbol binario completo también es un árbol binario completo. Por lo tanto, tomamos el árbol binario completo como ejemplo para deducir que la complejidad temporal del ajuste ascendente y la construcción del montón es O(N*logN ).

2.2 Ajustando el montón hacia abajo: O(N)

2.2.1 Ajustar el código hacia abajo

void AdjustDown(HPDataType* a, int size, int parent)
{
	int child = parent * 2 + 1;
	while (child < size)//当child大于了数组大小就跳出循环
	{
		//找出左右孩子中小/大的那个(假设法)
		if (child + 1 < size && a[child + 1] < a[child])
		{
			child++;
		}

		if (a[child] < a[parent])
		{
			Swap(&a[parent], &a[child]);

			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

2.2.2 Ajustar el código de construcción de montón hacia abajo

for (int i = (size - 1 - 1) / 2; i >= 0; i--)
{
    AdjustDown(a, size, i);
}

Dibujemos una imagen para analizar la complejidad temporal de la construcción del montón de ajuste descendente:

Ajuste la complejidad del tiempo de construcción del montón hacia abajo: O (N).

Después de dicho análisis, podemos saber que la mejor opción es ajustar la pila positiva hacia abajo.

3. Código de implementación de clasificación de almacenamiento dinámico

//堆排序时间复杂度O(N + N*logN)
void HeapSort(int* a, int size)
{
	//升序 -- 建大堆
	//降序 -- 建小堆

	//建堆 -- 向上调整,时间复杂度:O(N*log(N))
	//for (int i = 0; i < size; i++)
	//{
	//	AdjustUp(a, i);
	//}

	//建堆 -- 向下调整,时间复杂度:O(N)
	//倒着调整
	//叶子节点不需要处理
	//倒数第一个非叶子节点:最后一个节点的父亲开始调整
	for (int i = (size - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(a, size, i);
	}

	//O(N*log(N))
	int end = size - 1;
	while (end)
	{
		//1.先交换
		Swap(&a[0], &a[end]);
		//2.再调整,选出当前大小的数组中最小数
		AdjustDown(a, end, 0);

		end--;
	}
}

4. Prueba de ordenación en montón

Construimos un montón pequeño, por lo que la fila final está en orden descendente.

*** Fin del artículo ***

Supongo que te gusta

Origin blog.csdn.net/Ljy_cx_21_4_3/article/details/131065900
Recomendado
Clasificación