[Estrutura de dados -- linguagem C] Heap percebe o problema Top-K. Acontece que a classificação da glória do rei é realizada dessa maneira e o conhecimento aumentou novamente.

Índice

1. O que é um problema Top-K?

1.1 Ideia básica do Top-K

2. Análise lógica de problemas Top-K

2.1 Construa uma pilha, uma pequena pilha de tamanho K

2.2 Compare os elementos N - K restantes com os elementos superiores por sua vez e substitua-os se forem maiores

2.3 Pilha de Impressão

3. Código de implementação do TopK

4. O código completo do problema Top-K

A exibição do resultado:


A introdução da pergunta TopK:
Todo mundo encontrou um herói número xxx na cidade xxx e um herói xxx número xxx no distrito xxx ao jogar King of Glory. Ou se quisermos comer uma determinada comida quando pedirmos takeaway hoje, abrimos o Meituan/Ele.me, escolhemos a opção mais próxima de nós ou a opção com a pontuação mais alta, e os x nomes da loja que você escolher serão classificados fora em ordem. Top 10 na lista da Forbes, top 5 na lista dos ricos do Hurun, etc. Esses problemas requerem a ordenação de uma grande quantidade de dados e a seleção dos maiores top K. Aqui, o algoritmo TopK é usado para resolver esse tipo de problema.

1. O que é um problema Top-K?

Problema TOP-K: Encontre os maiores elementos ou os menores elementos principais K na combinação de dados. Geralmente, a quantidade de dados é relativamente grande.
Por exemplo: os 10 melhores jogadores profissionais, os 500 melhores do mundo, a lista dos ricos, os 100 melhores jogadores ativos no jogo, etc.

Para o problema Top-K, a forma mais simples e direta que pode ser pensada é a ordenação, mas: se a quantidade de dados for muito grande, a ordenação não é aconselhável (talvez não seja possível carregar todos os dados na memória
em uma vez). A melhor maneira é usar o heap para resolvê-lo. A ideia básica é a seguinte:

1.1 Ideia básica do Top-K

(1) Use os primeiros K elementos no conjunto de dados para construir uma pilha.
        Se forem os primeiros k elementos maiores, construa uma pilha pequena.
        Se forem os primeiros k elementos menores, construa uma pilha grande.

(2) Use os elementos NK restantes para comparar com os elementos superiores (estamos aqui para encontrar o maior K como exemplo), estamos construindo um pequeno heap, então o elemento superior do heap é o menor neste pequeno pilha, então começamos de Os elementos NK restantes são primeiro comparados com o topo da pilha. Se for maior que o elemento superior da pilha, substitua o elemento superior da pilha e ajuste para baixo para reconstruir a pilha pequena. Se é menor que o elemento superior da pilha, não o substitua e deixe o próximo elemento Comparado com o topo da pilha, os elementos NK restantes são comparados por sua vez e esta etapa é repetida.
(3) Depois de comparar os elementos NK restantes com os elementos do topo da pilha, os K elementos restantes na pilha são os primeiros K menores ou maiores elementos procurados.

2. Análise lógica de problemas Top-K

(1) Primeiro use o primeiro K para construir pequenas pilhas;

(2) Compare os elementos N - K restantes com os elementos superiores por sua vez e substitua se forem maiores;

(3) Pilha de impressão.

Essa é a nossa grande lógica, vamos analisar essas três etapas passo a passo:

2.1 Construa uma pilha, uma pequena pilha de tamanho K

processo:

1. Primeiro abrimos um espaço de tamanho k;

2. Ajuste os primeiros K dados para baixo para formar uma pequena pilha. (Para quem não entende como ajustar para baixo, pode clicar aqui para revisar )

código mostra como abaixo:

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 os elementos N - K restantes com os elementos superiores por sua vez e substitua-os se forem maiores

processo:

1. Como somos os maiores dados do top K, construímos um pequeno heap. O elemento superior do pequeno heap é o menor elemento do heap e os elementos NK restantes são comparados com o topo do heap;

2. Se este elemento for maior que o topo da pilha, vamos deixá-lo substituir o elemento superior da pilha, se for menor que isso, não vamos trocá-lo e passar para os seguintes elementos por sua vez para comparar;

3. Se for trocado, comece pelo topo da pilha e ajuste para baixo para reconstruir a pilha, e o topo da pilha será o menor elemento novamente;

4. Quando os elementos NK são comparados sequencialmente, os K elementos no heap são os primeiros K maiores elementos a serem encontrados.

código mostra como abaixo:

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

2.3 Pilha de Impressão

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

3. Código de implementação do 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");

}

Nosso código aqui lê os dados do arquivo e armazenamos os dados preparados no arquivo.

4. O código completo do problema Top-K

Estamos primeiro criando 1.000 números, armazenando os números em um arquivo e, em seguida, pegando esses números do arquivo ao buscar 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");

}

A exibição do resultado:

Técnica de verificação rápida : escrevemos no arquivo aqui. Para verificar rapidamente se o código está escrito corretamente, chamamos a interface que gera os dados, comentamos, entramos no arquivo data.txt e alteramos os cinco maiores dados e, em seguida, vá para imprimir, para que você possa verificar rapidamente.

Compare as duas imagens e imprima os 5 maiores valores.

*** Fim do artigo ***

Acho que você gosta

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