(1.2.5.6)堆

堆的概述

堆作为一种树形结构,也是二叉树的一种应用。二叉搜索树是规定了节点之间的大小关系:左孩子<根节点<右孩子。而堆中规定的节点之间的次序是:根节点<左孩子,根节点<右孩子;根节点>左孩子,根节点>右孩子。前者我们称之为小顶堆,后者是大顶堆。不同的逻辑定义,会得到不同的性质。关于堆的一些性质描述,我们在选择排序:堆排序中已详细介绍过。

堆的存储结构

堆是一种特殊的完全二叉树。通常所说的堆,就是指二叉堆。特殊是指它的节点大小次序是有规定的,但其本质还是一棵完全二叉树。而完全二叉树最常用的是顺序存储结构。如下图;


//默认构造方法
MinHeap::MinHeap()
{
	elemsize = 0;
	array = new ElemType[DEFAULTSIZE];
	if (!array)
	{
		cerr << "分配内存失败!" << endl;
		exit(0);
	}
}
//拷贝构造方法
MinHeap::MinHeap(MinHeap& heap)
{
	//若原堆中有元素,则清空
	if (array)
		delete[]array;
	array = new ElemType[heap.heapsize];
	if (!array)
	{
		cerr << "分配内存失败!" << endl;
		exit(0);
	}
	MinHeap(heap.array, heap.elemsize);
}
//指定数组构造堆
MinHeap::MinHeap(ElemType* a, int n)
{
	elemsize = n;
	heapsize = DEFAULTSIZE;
	while (heapsize < n)
		heapsize += INCREMENT;
	array = new ElemType[heapsize];
	if (!array)
	{
		cerr << "分配内存失败!" << endl;
		exit(0);
	}
	//赋值
	memcpy(array, a, n*sizeof(ElemType));
	//堆化数组
	for (int i = (elemsize - 2) / 2; i >= 0; i--)
		siftDown(i);
}
//插入新的元素
void MinHeap::insertHeap(ElemType data)
{
	/*
	新元素总是先加到最后,再调整堆
	所以插入操作总是可以成功的(相对于内存大小)
	*/
	//若堆内存已用完,则扩充堆内存
	if (elemsize >= heapsize)
	{
		heapsize += INCREMENT;
		array = (ElemType*)realloc(array, heapsize);
	}
	array[elemsize] = data;
	siftUp(elemsize);
	elemsize++;
}
//删除指定位置元素
bool MinHeap::deleteHeap(int pos)
{
	//堆空或位置不对
	if (empty() || pos<0 || pos>=elemsize)
		return false;
	//删除时,总是用最后一个元素填充待删除的位置
	array[pos] = array[elemsize - 1];
	elemsize--;
	//从该位置向下调整堆
	siftDown(pos);
}
//获取堆顶元素
ElemType MinHeap::top()
{
	if (empty())
		return NULL;
	return array[0];
}
//向上调整
void MinHeap::siftUp(int pos)
{
	int i, j;
	//i为j的父亲
	j = pos, i = (pos - 1) / 2;
	while (i>=0)
	{
		if (array[j] >= array[i])
			break;
		swap(array[i], array[j]);
		j = i;
		i = (j-1) / 2;
	}
}
//向下调整
void MinHeap::siftDown(int pos)
{
	int i, j;
	i = pos, j = 2 * i + 1;
	while (j < elemsize)
	{
		if (j + 1 < elemsize && array[j + 1] < array[j])
			j++;
		if (array[i] <= array[j])
			break;
		swap(array[i], array[j]);
		i = j;
		j = 2 * i + 1;
	}
}
//遍历堆
void MinHeap::traverse()
{
	if (empty())
		return;
	for (int i = 0; i < elemsize; i++)
		cout << setw(4) << array[i];
	cout << endl;
}
//堆排序
void MinHeap::heapSort()
{
	if (empty())
		return;
	ElemType *a = new ElemType[elemsize];
	if (!a)
	{
		cerr << "分配内存失败!" << endl;
		exit(0);
	}
	memcpy(a, array, elemsize*sizeof(ElemType));
	int n = elemsize;
	while (n >= 1)
	{
		//把最小的元素调到最后
		swap(a[0], a[n - 1]);
		n--;
		//从堆顶向下调整
		int i, j;
		i = 0, j = 1;
		while (j < n)
		{
			if (j + 1 < n && a[j + 1] < a[j])
				j++;
			if (a[i] <= a[j])
				break;
			swap(a[i], a[j]);
			i = j;
			j = 2 * i + 1;
		}
	}
	//打印
	for (int i = elemsize - 1; i >= 0; i--)
		cout << setw(4) << a[i];
	cout << endl;
	//释放内存
	delete[]a;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值