教你玩转min_heap && 指针queue


 一
.Min_heap的建立

   堆是一种数据结构,分为最大值堆和最小值堆;

   堆的内部结构是一个完全二叉树;

   最大值堆的根节点是树中最大的元素,而父节点比任意一个子节点都要大;

   最小值堆的根节点是树中最小的元素,父节点比任意一个子节点都要小;

   我们用以下数组为建堆的材料:int testH[]={24,63,23,47,232,46,12,57,24,74};

   逻辑中,我们对数组的结构可以这样设计:

 

 

-----图有点错了,最后两个是8和9

  我们要建立一个堆,最重要的是三点:初始化堆,堆内调整算法,插入/删除;

设节点的下标为i(i!=0),孩子为2*i,2*i+1.

如果heap[i]>min(heap[2*i],heap[2*i+1])则交换节点,然后调整比如heap[2*i]与其孩子heap[2*2*i],heap[2*2*i+1].

节点规则:heap[i]<heap[2*i],heap[i]<heap[2*i+1];

 

(1)初始化堆我们的思想是从一个最小单元开始排序,就是最后一个父节点开始向前排序,而父节点的父节点是重叠子问题,只要最后一个父节点是最优的结构,往上解最优的时候就会获得全局最优的解集。

(2)当我们调整一个节点的时候,我们只需要往那个交换的节点的子节点进行调整。最小堆的一个规则,最简单的结构到复杂的结构的特点都是唯一的,也就是父节点比任意一个子节点都小。例如

 

 

我们要调整55这个节点,44,和46已经调整好了(从后往前调整),55>46>44,则交换55和44这两个节点。这是不必调整46和它的子节点,理由很简单,它是个稳定的结构,没有进行节点调整,所以程序不必理会,而交换的44节点的结构变换了,要向下调整。所以建堆的思路是:从父节点往前调整,每一次调整深度优先。

 

初始化算法:

//初始化
void inith(int *a)
{
	for(int i=0;i<hlength;i++)
	{
		heap[i]=*(a+i);
	}
	cout<<endl;
}
//建立堆
void build()
{
	for(int i=hlength/2;i>=0;i--)
	{
		down(i);

	}
}
//从上往下调整法
void down(int p)
{
	int q=p*2;
	int a=heap[p];

	while(q<hlength)
	{
		if(q<hlength && heap[q]>heap[q+1])
		{
			q++;		
		}

		if(heap[q]>=a)
		{
			break;
		}
		else{
			heap[p]=heap[q];

			p=q;
			q=p*2;	
		}
		heap[p]=a;
		
	}
	
		

}

 

代码虽然很简单,但是思路确实很烦躁,要理解每一步的关键

最后形成的堆是:

 

 

 

 -------更新 2014-11-15 22:00

实现最小堆的目的:堆排序

 

堆排序可以对大量的数据进行查找top k 而不占用大量的内存,原因是不用把数据加载到内存中,读入-堆比较-调整堆,这个流程,只要维护一个最小堆,top k不在话下

 思路:利用最小值堆找出海量数据的前 k个最大值,比堆顶小的数据舍弃,比堆顶大的数据则替换掉堆顶并且向下调整,最后找出top k

#include <iostream>
#include "heap_sort_min.h"
using namespace std;

void main()
{
	int test[]={34,22,145,23,2,35,155,3245,1341,345,889,536,567,3546,786,468,468,464,48,646};
	//int testH[]={24,63,23,47,232,46,12,57,24,74};
	inith(test);
	build();
	for(int i=9;i<20;i++)
		HeapSort(test[i]);
	for(int i=0;i<10;i++)
		cout<<heap[i]<<"  ";
	cout<<endl;

}

 

 

/*堆排序模块*/
void HeapSort(int a)
{
	if(a<heap[0])
		return;
	heap[0]=a;
	down(0);
}

 

 

 

 

 二.指针queue

类似Java的数组队列,而我所称的数组队列并不是严格的FIFO规则,只是一个可增长的动态数组,而指针的细节在于替代了原始地址要释放空间,不然会造成内存泄露

 

 

/*
数组队列
*/

int *array;

int size=10;
int capacity=0;
void queue()
{
	array=new int[10];
}
void add(int data)
{
	int *temp;
	int *at=array;
	if(capacity==size)
	{
		temp=new int[++size];
		for(int i=0;i<capacity;i++)
			temp[i]=array[i];
		temp[size-1]=data;
		array=temp;
		delete[] at;
		capacity++;
	}else{
		array[capacity++]=data;
	
	}


}

 最后一句:人生在于不停地奋斗,没有妹子就要孤独地写代码

<!--EndFragment-->
template <typename PointType> class KD_TREE { // using MANUAL_Q_ = MANUAL_Q<typename PointType>; // using PointVector = std::vector<PointType>; // using MANUAL_Q_ = MANUAL_Q<typename PointType>; public: using PointVector = std::vector<PointType, Eigen::aligned_allocator<PointType>>; using Ptr = std::shared_ptr<KD_TREE<PointType>>; struct KD_TREE_NODE { PointType point; int division_axis; int TreeSize = 1; int invalid_point_num = 0; int down_del_num = 0; bool point_deleted = false; bool tree_deleted = false; bool point_downsample_deleted = false; bool tree_downsample_deleted = false; bool need_push_down_to_left = false; bool need_push_down_to_right = false; bool working_flag = false; pthread_mutex_t push_down_mutex_lock; float node_range_x[2], node_range_y[2], node_range_z[2]; float radius_sq; KD_TREE_NODE *left_son_ptr = nullptr; KD_TREE_NODE *right_son_ptr = nullptr; KD_TREE_NODE *father_ptr = nullptr; // For paper data record float alpha_del; float alpha_bal; }; struct Operation_Logger_Type { PointType point; BoxPointType boxpoint; bool tree_deleted, tree_downsample_deleted; operation_set op; }; // static const PointType zeroP; struct PointType_CMP { PointType point; float dist = 0.0; PointType_CMP(PointType p = PointType(), float d = INFINITY) { this->point = p; this->dist = d; }; bool operator<(const PointType_CMP &a) const { if (fabs(dist - a.dist) < 1e-10) return point.x < a.point.x; else return dist < a.dist; } }; class MANUAL_HEAP { public: MANUAL_HEAP(int max_capacity = 100) { cap = max_capacity; heap = new PointType_CMP[max_capacity]; heap_size = 0; } ~MANUAL_HEAP() { delete[] heap; } void pop() { if (heap_size == 0) return; heap[0] = heap[heap_size - 1]; heap_size--; MoveDown(0); return; } PointType_CMP top() { return heap[0]; } void push(PointType_CMP point) { if (heap_size >= cap) return; heap[heap_size] = point; FloatUp(heap_size); heap_size++; return; } int size() { return heap_size; } void clear() { heap_size = 0; return; } private: PointType_CMP *heap; void MoveDown(int heap_index) { int l = heap_index * 2 + 1; PointType_CMP tmp = heap[heap_index]; while (l < heap_size) { if (l + 1 < heap_size && heap[l] < heap[l + 1]) l++; if (tmp < heap[l]) { heap[heap_index] = heap[l]; heap_index = l; l = heap_index * 2 + 1; } else break; } heap[heap_index] = tmp; return; } void FloatUp(int heap_index) { int ancestor = (heap_index - 1) / 2; PointType_CMP tmp = heap[heap_index]; while (heap_index > 0) { if (heap[ancestor] < tmp) { heap[heap_index] = heap[ancestor]; heap_index = ancestor; ancestor = (heap_index - 1) / 2; } else break; } heap[heap_index] = tmp; return; } int heap_size = 0; int cap = 0; }; 详细注释上述代码,详细到参数
最新发布
09-30
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值