"Clasificación de montón" y "Top-k"

Tabla de contenido

Editar

Prefacio:

Acerca de la "clasificación del montón":

Paso 1: construye una pila

Paso 2: ordenar

"Problema Top-K"

Respecto a las preguntas Top-k:


Prefacio:

En el blog anterior, ya teníamos un concepto preliminar de "Heap", luego podemos usar "Heap" para resolver los problemas de nuestra vida diaria. En este artículo, presentamos dos escenarios de aplicación de uso común, respectivamente: "Ordenar " y "Problema Top-k". El blog anterior está en: Implementación de simulación de "Heap" -Blog CSDN

 

Acerca de la "clasificación del montón":

#define _CRT_SECURE_NO_WARNINGS  1
#include<stdio.h>

void swap(int* a, int* b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}

void AdjustDown(int* arr, int sz, int parent)
{
	int child = parent * 2 + 1;
	while (child < sz)
	{
		if (child + 1 < sz && arr[child] < arr[child + 1])
		{
			child++;
		}

		if (arr[child] > arr[parent])
		{
			swap(&arr[child], &arr[parent]);
			parent = child;
			child = 2 * parent + 1;
		}
		else
		{
			break;
		}
	}
}

void AdjustUp(int* arr, int sz, int child)
{
	while (child > 0)
	{
		int parent = (child - 1) / 2;
		if (arr[parent] < arr[child])
		{
			swap(&arr[parent], &arr[child]);
		}
		child = parent;
	}
}

int main()
{
	int arr[] = { 2, 6, 9, 3, 1, 7 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	for (int i = (sz - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(arr, sz, i);
	}//向下调整算法
	

	//for (int i = 1; i<sz; i++)
	//{
	//	AdjustUp(arr, sz, i);
	//}//向上调整算法

	int end = sz - 1;
	while (end > 0)
	{
		swap(&arr[0], &arr[end]);
		AdjustDown(arr, end, 0);
		--end;
	}
	return 0;
}

Paso 1: construye una pila

El uso de "Montón" puede facilitarnos la clasificación de una determinada matriz desordenada. Primero, debemos seleccionar un montón grande para la operación de clasificación.

¿Por qué no elegimos usar un montón pequeño para construir un montón?

Según la explicación anterior del blog sobre "Montón", un montón pequeño significa que el elemento superior es el elemento más pequeño y el número de otros nodos es menor que el primer elemento, por lo que si es un montón pequeño, el número más pequeño ya es el primer elemento. Si desea encontrar el siguiente elemento más pequeño, debe crear un montón entre los elementos restantes y repetir el ciclo para completar la clasificación. Esto tiene una alta complejidad de tiempo y no es propicio para la clasificación.

Por lo tanto, elegimos usar un montón grande para construir un montón. Después de lograr un montón grande, intercambiamos el primer y el último elemento, y luego usamos el método de ajuste hacia abajo para ajustar los n-1 elementos restantes y luego intercambiarlos. puede lograr Ordenar.

    int arr[] = { 2, 6, 9, 3, 1, 7 };
	int sz = sizeof(arr) / sizeof(arr[0]);

	for (int i = 1; i<sz; i++)
	{
	   AdjustUp(arr, sz, i);
	}

Ajuste la matriz como se muestra en la figura hacia arriba para construir un montón:

 

Paso 2: ordenar

 Primero intercambiamos el primer y el último elemento:

Ajuste hacia abajo en todos menos el último elemento para continuar en una pila grande.

 

 

 

 

Repita los pasos anteriores

El montón final es:

 

Esto completa la clasificación del montón.

 

"Problema Top-K"

Respecto a las preguntas Top-k:

Es decir, encontrar los primeros K elementos más grandes o más pequeños en una combinación de datos. Generalmente, la cantidad de datos es relativamente grande .

Por ejemplo: los 10 mejores profesionales, Fortune 500, lista de ricos, los 100 mejores jugadores activos del juego, etc. Tomemos el ejemplo de encontrar los primeros K elementos más grandes en n datos para ilustrar: (asumiendo n=10000) (asumiendo k=10)

 

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
const char* file = "data.txt";
void swap(int* a, int* b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}

void AdjustDown(int* arr, int sz, int parent)
{
	int child = 2 * parent + 1;
	while (child < sz)
	{
		if (child + 1 < sz && arr[child + 1] < arr[child])
		{
			child++;
		}

		if (arr[child] < arr[parent])
		{
			swap(&arr[child], &arr[parent]);
			parent = child;
			child = 2 * parent + 1;
		}
		else
		{
			break;
		}
	}
}

void CreateFile()
{
	//创建随机数的种子
	srand((unsigned int)time(NULL));
	FILE* Fin = fopen(file, "w");
	if (Fin == NULL)
	{
		perror("Fopen error");
		exit(-1);
	}

	int n = 10000000;
	for (int i = 0; i < n; i++)
	{
		int x = (rand() + i) % n;
		fprintf(Fin, "%d\n", x);
	}

	fclose(Fin);
	Fin = NULL;
}

void Print()
{
	FILE* Fout = fopen(file, "r");
	if (Fout == NULL)
	{
		perror("Fout error");
		exit(-1);
	}

	//取前k个数进小堆
	int* minheap = (int*)malloc(sizeof(int) * 5);
	if (minheap == NULL)
	{
		perror("minheap -> malloc");
		return;
	}


	for (int i = 0; i < 5; i++)
	{
		fscanf(Fout, "%d", &minheap[i]);
	}

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

	//读取数据
	int x = 0;
	while (fscanf(Fout, "%d", &x) != EOF)
	{
		if (minheap[0] < x)
		{
			minheap[0] = x;
		}
		AdjustDown(minheap, 5, 0);
	}

	for (int i = 0; i < 5; i++)
	{
		printf("%d ", minheap[i]);
	}

	fclose(Fout);
	Fout = NULL;
}

int main()
{
	//CreateFile();
	Print();
	return 0;
}

Primero, creamos 10000000 números aleatorios, luego modificamos los números, seleccionamos aleatoriamente 5 números y los modificamos como

10000001,10000002,10000003,10000004,10000005

Construye otra pila pequeña . ¡Ten en cuenta que debe ser una pila pequeña!

Si construimos un montón grande, si primero buscamos los datos y encontramos 10000005, entonces el número debe estar en la parte superior del montón. Cuando encontramos el siguiente número más pequeño, no podemos ingresar al montón, por lo que usamos un montón pequeño. !

 Luego coloque los primeros 5 elementos de los datos en el montón pequeño,

Luego recorra y compare los 9999995 números restantes. Si son mayores que el elemento superior del montón, reemplácelos directamente.

Después del reemplazo, ajuste hacia abajo nuevamente y después de atravesar todos los datos, se insertará el montón.

 10000001,10000002,10000003,10000004,10000005

Supongo que te gusta

Origin blog.csdn.net/weixin_72917087/article/details/135478100
Recomendado
Clasificación