[Estructura de datos - lenguaje C] Heap se da cuenta del problema Top-K. Resulta que la clasificación de la gloria del rey se realiza de esta manera, y el conocimiento ha aumentado nuevamente.

Tabla de contenido

1. ¿Qué es un problema Top-K?

1.1 Idea básica de Top-K

2. Análisis lógico de problemas Top-K

2.1 Construya un montón, un pequeño montón de tamaño K

2.2 Compare los elementos N - K restantes con los elementos superiores a su vez, y reemplácelos si son mayores

2.3 Montón de impresión

3. Código de implementación de TopK

4. El código completo del problema Top-K

La pantalla de resultados:


La introducción de la pregunta de TopK:
todos se han encontrado con un héroe número xxx en la ciudad xxx y un héroe xxx número xxx en el distrito xxx al jugar King of Glory. O si queremos comer una determinada comida cuando ordenemos comida para llevar hoy, abrimos Meituan/Ele.me, elegimos la opción más cercana a nosotros o la opción con la puntuación más alta, y se ordenarán los primeros x nombres de la tienda que elijas. fuera en orden. Top 10 en la lista de Forbes, top 5 en la lista rica de Hurun, etc. Estos problemas requieren clasificar una gran cantidad de datos y seleccionar los más grandes de K. Aquí, el algoritmo TopK se usa para resolver este tipo de problema.

1. ¿Qué es un problema Top-K?

Problema TOP-K: Encuentre los K elementos más grandes o los elementos más pequeños en la combinación de datos Generalmente, la cantidad de datos es relativamente grande.
Por ejemplo: los 10 mejores jugadores profesionales, los 500 mejores del mundo, la lista completa, los 100 mejores jugadores activos en el juego, etc.

Para el problema de Top-K, la forma más sencilla y directa que se puede pensar es la clasificación, pero: si la cantidad de datos es muy grande, la clasificación no es recomendable (puede que no sea posible cargar todos los datos en la memoria al mismo tiempo)
. una vez). La mejor manera es usar el montón para resolverlo.La idea básica es la siguiente:

1.1 Idea básica de Top-K

(1) Use los primeros K elementos en el conjunto de datos para construir un montón.
        Si son los primeros k elementos más grandes, construya un montón pequeño.
        Si son los primeros k elementos más pequeños, construya un montón grande.

(2) Use los elementos NK restantes para compararlos con los elementos superiores a su vez (estamos aquí para encontrar el K más grande como ejemplo), estamos construyendo un montón pequeño, por lo que el elemento superior del montón es el más pequeño en este pequeño Los elementos NK restantes se comparan primero con la parte superior del montón. Si es mayor que el elemento superior del montón, reemplace el elemento superior del montón y ajuste hacia abajo para reconstruir el montón pequeño. Si es más pequeño que el elemento superior del montón, no lo reemplace y deje que el siguiente elemento se compare con la parte superior del montón, los elementos NK restantes se comparan a su vez y este paso se repite.
(3) Después de comparar los elementos NK restantes con los elementos superiores del montón a su vez, los elementos K restantes en el montón son los primeros K elementos más pequeños o más grandes buscados.

2. Análisis lógico de problemas Top-K

(1) Primero use la primera K para construir montones pequeños;

(2) Compare los elementos N - K restantes con los elementos superiores a su vez y reemplácelos si son más grandes;

(3) Montón de impresión.

Esta es nuestra gran lógica, vamos a analizar estos tres pasos paso a paso:

2.1 Construya un montón, un pequeño montón de tamaño K

proceso:

1. Primero abrimos un espacio de tamaño k;

2. Ajuste los primeros datos K hacia abajo para formar una pila pequeña. (Para aquellos que no entienden cómo ajustar hacia abajo, pueden hacer clic aquí para revisar )

el código se muestra a continuación:

int* kminheap = (int*)malloc(sizeof(int) * k);
if (NULL == kminheap)
{
    perror("malloc fail:");
    return;
}

for (int i = 0; i < k; i++)
{
    fscanf(fout, "%d", &kminheap[i]);
}

//建小堆
for (int i = (k - 1 - 1) / 2; i >= 0; i--)
{
    AdjustDown(kminheap, k, i);
}

2.2 Compare los elementos N - K restantes con los elementos superiores a su vez, y reemplácelos si son mayores

proceso:

1. Debido a que somos los K datos más grandes de la parte superior, construimos un montón pequeño. El elemento superior del montón pequeño es el elemento más pequeño del montón, y los elementos NK restantes se comparan con la parte superior del montón a su vez;

2. Si este elemento es más grande que la parte superior del montón, dejaremos que reemplace el elemento superior del montón, si es más pequeño que eso, no lo intercambiaremos, e iremos a los siguientes elementos a su vez para comparar;

3. Si se intercambia, comience desde la parte superior de la pila y ajuste hacia abajo para reconstruir la pila, y la parte superior de la pila volverá a ser el elemento más pequeño;

4. Cuando los elementos NK se comparan secuencialmente, los elementos K en el montón son los primeros elementos K más grandes que se encuentran.

el código se muestra a continuación:

int val = 0;
while (!feof(fout))
{
    fscanf(fout, "%d", &val);
    if (val > kminheap[0])
    {
        kminheap[0] = val;
        AdjustDown(kminheap, k, 0);
    }
}

2.3 Montón de impresión

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

3. Código de implementación de TopK

void PrintTopK(int k)
{
	const char* file = "data.txt";
	FILE* fout = fopen(file, "r");
	if (NULL == fout)
	{
		perror("fopen error:");
		return;
	}

		int* kminheap = (int*)malloc(sizeof(int) * k);
		if (NULL == kminheap)
		{
			perror("malloc fail:");
			return;
		}

		for (int i = 0; i < k; i++)
		{
			fscanf(fout, "%d", &kminheap[i]);
		}

		//建小堆
		for (int i = (k - 1 - 1) / 2; i >= 0; i--)
		{
			AdjustDown(kminheap, k, i);
		}

	int val = 0;
	while (!feof(fout))
	{
		fscanf(fout, "%d", &val);
		if (val > kminheap[0])
		{
			kminheap[0] = val;
			AdjustDown(kminheap, k, 0);
		}
	}

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

}

Nuestro código aquí lee datos del archivo y almacenamos los datos preparados en el archivo.

4. El código completo del problema Top-K

Primero estamos creando 1000 números, almacenando los números en un archivo y luego tomando estos números del archivo cuando buscamos Top-K.

void CreateNData()
{
	//造数据
	int n = 1000;
	srand((unsigned int)time(NULL));
	const char* file = "data.txt";
	FILE* fin = fopen(file, "w");
	if (NULL == fin)
	{
		perror("fopen error:");
		return;
	}

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

	fclose(fin);
}
void PrintTopK(int k)
{
	const char* file = "data.txt";
	FILE* fout = fopen(file, "r");
	if (NULL == fout)
	{
		perror("fopen error:");
		return;
	}

		int* kminheap = (int*)malloc(sizeof(int) * k);
		if (NULL == kminheap)
		{
			perror("malloc fail:");
			return;
		}

		for (int i = 0; i < k; i++)
		{
			fscanf(fout, "%d", &kminheap[i]);
		}

		//建小堆
		for (int i = (k - 1 - 1) / 2; i >= 0; i--)
		{
			AdjustDown(kminheap, k, i);
		}

	int val = 0;
	while (!feof(fout))
	{
		fscanf(fout, "%d", &val);
		if (val > kminheap[0])
		{
			kminheap[0] = val;
			AdjustDown(kminheap, k, 0);
		}
	}

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

}

La pantalla de resultados:

Técnica de verificación rápida : Lo hemos escrito en el archivo aquí. Para verificar rápidamente si el código está escrito correctamente, llamamos a la interfaz que genera los datos, luego lo comentamos, ingresamos el archivo data.txt y cambiamos los cinco más grandes. datos, y luego Ir a imprimir, para que pueda verificar rápidamente.

Compare las dos imágenes e imprima los 5 valores más altos.

*** Fin del artículo ***

Supongo que te gusta

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