第三章:查找与排序(下)----------- 3.25 知其然知其所以然:小顶堆与topK的具体代码实现

本文介绍了一种高效解决海量数据TopK问题的算法,利用小顶堆(大顶堆)对数据进行实时处理,适用于数据量巨大无法一次性加载到内存的情况。通过动态创建数组并使用堆化操作,确保了堆顶元素始终是最小的TopK数值之一,从而实现了在线性时间内获取TopK元素的目标。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

小顶堆与topK的具体代码实现:

       求海量数据(正整数)按逆序排列的前k个数(TopK),因为数量太大,不能全部存储在内存中,只能一个一个地从磁盘或者网络上读取数据,请设计一个高效的算法来解决这个问题。

       第一行:用户输入K,代表要求得topK。

       随后的N(不限制)行,每一行是一个整数,代表用户输入的数据。

       用户输入-1代表输入终止。

       请输出topK,从小到大,空格分割。

       解决:大顶堆。

思路:

输入N个数据时,若n<k,依次添加到数组(堆)当中;当填入数据达到k时,立刻堆化

若n>k,比较要填入数与堆顶数据,若x>heap[0],将heap[0]赋值为x,并向下堆化。

ps:n:已填入数据的数量。

 代码:

#include<iostream>
using namespace std;

int* heap;  //全局变量 ===> 数组头指针(数组名) 
int size=0;
int k;  //输出前k个数	

/*******/ 
void deal(int x);
void makeMinHeap(int A[],int length); 
void MinHeapFixDown(int A[],int i,int n);
void printRs();
/*******/

int main(){
	std::ios_base::sync_with_stdio(false);
 	
	cin>>k;
	
	heap=new int[k]; // 动态创建数组 
	
	int x;  
	while((cin>>x)&&x!=-1){
		deal(x); //处理x 
	}	
	printRs();
			
	return 0;
}

/*
如果数据的数量小等于k,直接加入堆中
等于k的时候,进行堆化
*/ 
void deal(int x){
	if(size<k){
		heap[size++]=x;
		
		if(size==k){
			//堆化
		 	makeMinHeap(heap,k);
		}
	}
	else{
		//x和堆顶进行比较,如果x大于堆顶,x将堆顶挤掉,并向下调整 
		if(heap[0]<x){
			heap[0]=x;
			MinHeapFixDown(heap,0,k);
			printRs();
		}	
	}
	
} 

void printRs(){
	for(int i=0;i<k;i++){
		cout<<heap[i]<<" ";
	}
	cout<<endl;
}


void makeMinHeap(int A[],int length){
	int n=length;
	for(int i=n/2-1;i>=0;i--){
		MinHeapFixDown(A,i,n);
	}
} 
 
//向下调整函数 
void MinHeapFixDown(int A[],int i,int n){
	//找到左右孩子
	int left=2*i+1;
	int right=2*i+2;
	//左孩子已经越界,i就是叶子节点
	if(left>=n){
		return;
	} 
	 int min=left;
	 if(right>=n){
	 	min=left;
	 }
	 else{
	 	if(A[right]<A[left]){
	 		min=right;
	 	}
	 }
	 //min指向了左右孩子中较小的那个
	 
	 //如果A[i]比两个孩子都要小,不用调整
	 if(A[i]<A[min]){
	 	return;
	 } 
	 //否则,找到两个孩子中较小的,和i交换
	 int temp=A[i];
	 A[i]=A[min];
	 A[min]=temp;
	 
	 //小孩子那个位置的值发生了变化,i变更为小孩子的那个位置,递归调整
	 MinHeapFixDown(A,min,n);	 
}

 结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值