`
chentingk
  • 浏览: 19029 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

教你玩转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-->
  • 大小: 19.5 KB
  • 大小: 12.7 KB
  • 大小: 22.8 KB
  • 大小: 26.8 KB
  • 大小: 27.3 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics