Falando sobre o problema principal

problema principal

Encontre o maior (menor) primeiro k entre os números N.
Cenas realistas, como: a classificação dos heróis da glória do rei (o 100º Hanxin no distrito de Chang'an) e a classificação de comerciantes externos (o segundo em vendas de Maocai no distrito de Chang'an)

1. Ideia 1: Classificação (classificação de heap)

A complexidade do tempo é: O (N * log 2 N )

Se quisermos encontrar os maiores k principais números, podemos classificar os N números em ordem decrescente e, em seguida, produzir os primeiros k números; em ordem decrescente, temos que construir um pequeno monte e, em seguida, combinar o nó raiz e o último nó folha Exchange, não considere o último número como dados no heap e, em seguida, faça ajustes para baixo; consulte a classificação do heap para uma análise específica

1.1 Implementação do código

//降序
void HeapSort(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)
	{
    
    
		int tem = a[end];
		a[end] = a[0];
		a[0] = tem;
		AdjustDown(a, end, 0);
		--end;
	}
}

1.2 teste

int main()
{
    
    
	int arr[] = {
    
     27, 28, 65, 25, 15, 34, 19, 49, 18, 37 };
	int n = sizeof(arr) / sizeof(int);
	printf("全部数据:");
	for (int i = 0; i < n; i++)
	{
    
    
		printf("%d ", arr[i]);
	}
	printf("\n");
	HeapSort(arr, n);
	printf("最大的前5个数:");
	for (int j = 0;j < 5; j++)
	{
    
    
		printf("%d ", arr[j]);
	}
	printf("\n");
	return 0;
}

Insira a descrição da imagem aqui

2. Ideia 2: Construir uma grande pilha, excluir a maior, ajustar a pilha e continuar a selecionar, até que k segundas maiores sejam selecionadas

A complexidade do tempo é: O (N + k * log 2 N )
Quando N é muito grande, a complexidade do tempo desta ideia se aproxima de O (N)

Como a primeira ideia não é eficiente, a segunda ideia é obtida após a otimização -------> Se quisermos encontrar os maiores números k, podemos construir uma grande pilha e, em seguida , excluir o nó raiz (máximo), Use o algoritmo de ajuste para baixo para selecionar o segundo maior número e, em seguida, exclua-o até que k segundos maiores números sejam selecionados

Esta ideia precisa construir uma complexidade de tempo de heap de O (N) e executar k vezes a complexidade de tempo do algoritmo de ajuste para baixo é O (k * log 2 N ), então a complexidade de tempo total dessa ideia é O (N + klog 2 N ), quando N é muito grande, log 2 N é muito plano e O (N) se aproxima do infinito, portanto, quando N é muito grande, a complexidade de tempo dessa ideia se aproxima de O (N)

3. Ideia três -> solução ideal (economia de espaço, eficiência relativamente alta) :

A complexidade de tempo é: O (k + (Nk) * log 2 k )
Quando N é muito grande, a complexidade de tempo desta ideia se aproxima de O (N)

Se N for muito grande, o número de N não cabe na memória. A ideia 2 não é viável e a otimização é obtida. Ideia 3 -------> Se quisermos encontrar os maiores números k, construa uma pequena pilha de números K, Os números NK restantes são comparados com os dados no topo da pilha, por sua vez. Se for maior do que os dados no topo da pilha, os dados no topo da pilha são substituídos ( diretamente sobrescrito) e, em seguida, ajustado para baixo, de modo que o maior número de K no final do loop seja Pilha

Esta ideia cria pilhas de k-números, a complexidade do tempo é O (k), e ajustes para baixo NK são necessários, então a complexidade do tempo é O ((Nk) * log 2 k ), então a complexidade do tempo total da ideia três é O (k + (Nk) * log 2 k ), em aplicações práticas, N é muito grande, ek é um valor muito pequeno comparado a N, então quando N é muito grande, a complexidade de tempo da ideia 3 também se aproxima de O (N )

3.1 Implementação do código

void TopK(int* a,int k,int n)
{
    
    
	//开辟k个大小的空间
	int* heapA = (int*)malloc(k * sizeof(int));
	for (int i = 0; i < k; ++i)
	{
    
    
		heapA[i] = a[i];
	}
	//建k个数大小的小堆
	for (int i = (k - 2) / 2; i >= 0; --i)
	{
    
    
		AdjustDown(heapA, k, i);
	}
	//从第K个位置开始和heapA[0]比较,大就覆盖heapA[0],
	//然后继续调整,heapA[0]始终是堆里最小的数
	for (int i = k; i < n; i++)
	{
    
    
		if (a[i] > heapA[0])
		{
    
    
			heapA[0] = a[i];
			AdjustDown(heapA, k, 0);
		}
	}
	//打印
	for (int i = 0; i < k; i++)
	{
    
    
		printf("%d ", heapA[i]);
	}
	printf("\n");
	free(heapA);
}

3.2 Teste

int main()
{
    
    
	int arr[] = {
    
     27, 28, 65, 25, 15, 34, 19, 49, 18, 37 };
	int n = sizeof(arr) / sizeof(int);
	printf("全部数据:");
	for (int i = 0; i < n; i++)
	{
    
    
		printf("%d ", arr[i]);
	}
	printf("\n");
	TopK(arr, 5, n);
	return 0;
}

Insira a descrição da imagem aqui

Acho que você gosta

Origin blog.csdn.net/weixin_50886514/article/details/114928789
Recomendado
Clasificación