[Estructura de datos] Árbol binario - Clasificación de montón

La complejidad temporal de la clasificación del montón por matriz la última vez es O(NlogN), y la complejidad espacial es O(N).

Después de la optimización, la complejidad del tiempo es O(NlogN) y la complejidad del espacio es O(1).

Considere el esquema de optimización:

1. Ajuste el montón de construcción hacia abajo.

2. Ajuste el montón de construcción hacia arriba.

Un montón se construye solo para encontrar el elemento más grande o más pequeño en el montón.

1. Ajustar el montón hacia arriba

Use el ajuste hacia arriba, la idea de insertar datos para construir un montón.

El esquema de optimización esencialmente no abre nuevo espacio para el procesamiento en la matriz original, por lo que su complejidad espacial se convierte en O(1).

void HeapSort2(int* a,int n)
{
	for (int i = 1; i < n; i++)
	{
		AdjustUp(a, i);
	}
	for(int i= 0;i<n;i++)
		printf("%d ", a[i]);
	printf("\n");
}

Ahora calcule su complejidad de tiempo Para la conveniencia del cálculo, se usa un árbol binario completo para el cálculo.

Los peores escenarios se consideran a continuación:

La segunda capa: 2^1 nodos, ajustados por 1 capa;

La tercera capa: 2^2 nodos, subir 2 capas;

……

La capa h-ésima: 2^(h-1) nodos, suba la capa h-1.

Luego, el número de nodos que deben moverse:

T(n) = 2^1 * 1+ 2^2*2 +…+ 2^(h-1)*(h-1)

De acuerdo con la fórmula de suma del método de resta de dislocaciones de secuencia, se puede saber que

T(n) = (N+1) * ( log(N+1) - 2 )+2 cuando n->infinito T(n) = NlogN

La complejidad temporal de la construcción del montón es O(N*logN).

2. Ajuste hacia abajo para construir un montón

Requisitos previos: el par debe ser un montón grande o un montón pequeño.

Así que primero ajuste la matriz.

Comience con el penúltimo nodo que no sea hoja (el padre del último nodo).

Porque el nodo de hoja se puede considerar como un montón grande o pequeño por sí mismo.

Dibujo:

Tiempos de ajuste: 4 veces

Código:

void HeapSort3(int* a, int n)
{
	for (int i = (n - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(a, n, i);
	}

	for (int i = 0; i < n; i++)
		printf("%d ", a[i]);
	printf("\n");
}

Complejidad espacial: O(1), complejidad temporal O(N)

Ahora pruebe la complejidad del tiempo:

La primera capa: 2^0 nodos, necesita moverse hacia abajo en la capa h-1.

La segunda capa: 2^1 nodos, necesita moverse hacia abajo en la capa h-2.

La tercera capa: 2^2 nodos, necesita ajustar la capa h-3 hacia abajo.

……

La capa h-1th, 2^(h-2) nodos, necesita moverse 1 capa hacia abajo.

Así que el número total de movimientos:

T(n) = 2^0 *(h-1) + 2^1 *(h-2) + …+ 2^(h-2)* 1

Según el método de sustracción de dislocaciones, se puede obtener:

T(n) = 2^h - 1 - h

y n = 2^h - 1

T(n) = n - log(n+1) 

Cuando n es infinito, se aproxima que T(n) = n

La prueba está completa.

Dado que ya existen dos métodos para construir un montón hacia arriba y hacia abajo, ¿cuál es más adecuado para construir un equipo y cuál es más adecuado para ver un montón grande? ?

Ascendente : construye un montón

Motivo: si el número más pequeño de pequeños montones en orden ascendente ya está en la primera posición, el resto de las relaciones están todas desordenadas y el montón debe reconstruirse Números, por lo que la complejidad temporal de O(N) no es tan fácil como el recorrido directo.

En resumen, construir montones pequeños en orden ascendente es ineficiente y complicado.

Descendente : construye un montón pequeño

Entonces, ¿cómo construir un montón grande para completar la clasificación?

La esencia de construir un montón grande es mantener la estabilidad del montón tanto como sea posible.

Después de encontrar el número más grande, intercambie el número en la posición raíz con el último número, ajuste hacia abajo en el grupo de datos n-1, encuentre el siguiente número más pequeño e intercambie la raíz con el número en la posición n-1, así que implementan orden ascendente.

Código relevante:

void HeapSort4(int* a, int n)
{
	for (int i = (n - 1 - 1) / 2; i >= 0; i--)
	{
		//建大堆
		AdjustDown(a, n, i);
	}
	//找到最后一个数的下标
	int end = n - 1;
	while (end > 0)
	{
		//交换根和最后一个位置的值
		Swap(&a[0], &a[end]);
		AdjustDown(a, end, 0);
		end--;
		
	}
	for (int i = 0; i < n; i++)
		printf("%d ", a[i]);
	printf("\n");
}

Problema de k superior

Encuentre los k elementos más grandes o los elementos más pequeños en la combinación de datos En general, la cantidad de datos es relativamente grande.

El método más simple en Top-k es la clasificación, si la cantidad de datos es muy grande, la clasificación tendrá problemas (los datos no se pueden cargar en la memoria al mismo tiempo), pero la clasificación en montón puede resolverlo.

1. Utilice el primer elemento de la matriz para crear un montón.

Encuentra el más grande para construir un montón pequeño y encuentra el más pequeño para construir un montón grande.

Similar al principio de construir montones grandes en orden ascendente y montones pequeños en orden descendente.

2. Reemplace el elemento superior comparando los elementos nk restantes con el elemento superior.

Recuerde ajustar hacia abajo.

void TopK(int* a,int n,int k)
{
	//建小堆
	int* topk = (int*)malloc(sizeof(int) * k);
	assert(topk);
	for (int i = 0; i < k; i++)
	{
		topk[i] = a[i];
	}
	//向下调整建堆
	for (int i = (k - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(topk, k, i);
	}
	for (int j = k; j < n; j++)
	{
		if (topk[0] < a[j])
		{
			topk[0] = a[j];
			AdjustDown(topk, k, 0);
		}
	}
	for (int i = 0; i < k; i++)
	{
		printf("%d ", topk[i]);
	}
	printf("\n");
	free(topk);
}
int main()
{    
	int n = 10000;
	int* a = (int*)malloc(sizeof(int) * n);
	assert(a);
	srand(time(0));
	for (int i = 0; i < n; i++)
	{
		a[i] = rand() % 10000;
	}
	a[0] = 100001;
	a[101] = 100002;
	a[159] = 123456;
	a[7459] = 100003;
	a[7412] = 100009;
	a[7826] = 111111;
	a[7712] = 222222;
	a[9635] = 999999;
	TopK(a,n,8);
	return 0;
}

Complejidad del tiempo O( K+ K*log(NK) )

Complejidad del espacio: O(K)

Cuando K<<N, la eficiencia también es bastante alta.

Si hay algo mal, por favor indíquelo. 

Supongo que te gusta

Origin blog.csdn.net/weixin_61932507/article/details/124082628
Recomendado
Clasificación