堆
首先堆不是内存中的一片区域,而是一种数据结构。
1.堆的概念:如果有一个关键码的集合K = {k0,k1, k2,…,kn-1},把它的所有元素按完全二叉树的顺序存储方式存储 在一个一维数组中,并满足:Ki <= K2i+1 且 Ki<= K2i+2 (Ki >= K2i+1 且 Ki >= K2i+2) i = 0,1,2…,则称为 小堆(或大堆)。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。
2.堆的性质:
- 堆是一颗完全二叉树
- 常常用数组实现
- 堆中某个节点的值总是不大于或者不小于其父节点的值
- 堆的基本功能:找最值
3.数据结构中堆与内存堆区的区别:数据结构中的堆:堆是一种经过排序的树形数据结构,每个节点都有一个值。通常我们所说的堆的数据结构是指二叉树。堆的特点是根节点的值最小(或最大),且根节点的两个树也是一个堆。
内存中的堆:堆是由new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便。
4.堆的图示
5.堆的实现
(1)创建堆
创建堆过程:在创建堆是就是把数组的元素建成一个完全二叉树,然后利用向下调整,使二叉树成为最大堆或者最小堆。
代码实现:
//向下调整
void heapify( int* array, int size,int index)
{
int left = 2 * index + 1;//该节点左孩子的下标
int right = 2 * index + 2;//该节点右孩子的下标
if (left >= right)
{
return;
}
int min = left;
if (right < size && array[right] < array[left])
{
min = right;
}
if (array[index] <= array[min])
{
return;
}
int t = array[min];
array[min] = array[index];
array[index] = t;
index = min;
heapify(array, size, min);
}
// 创建堆
void CreatHeap( int* array, int size)
{
for (int i = (size - 2)/2; i >= 0; i--)
{
heapify(array, size, i);
}
}
(2)堆的初始化
void InitHeap(Heap* hp,int* array,int size)
{
for (int i = 0; i < size; i++) {
hp->_array[i] = array[i];
}
hp->_size = size;
createHeap(hp->_array, hp->_size);
}
(3)向堆中插入值为data的元素
// 向堆中插入值为data的元素
void InsertHeap(Heap* hp, DataType data)
{
if (hp == NULL)
{
return;
}
hp->_array[hp->_size++] = data;
heapify(hp->_array, hp->_size,hp->_size - 1);
}
(4)删除堆顶元素
删除堆是删除堆顶的数据,将堆顶的数据根最后一个数据一换,然后删除数组最后一个数据,再进行向下调整算法。
// 删除堆顶元素
void EraseHeap(Heap* hp)
{
assert(hp->_size > 0);
if (hp == NULL)
{
return;
}
hp->_array[0] = hp->_array[hp->_size - 1];
hp->_size--;
heapify(hp->_array, hp->_size, 0);
}
(5)获取堆中有效元素
// 获取堆中有效元素个数
int SizeHeap(Heap* hp)
{
if (hp == NULL)
{
return;
}
return hp->_size;
}
(6)检测堆是否为空
// 检测堆是否为空
int EmptyHeap(Heap* hp)
{
if (hp == NULL)
{
return;
}
return hp->_size = 0 ? 1 : 0;
}
(7)获取堆顶元素
// 获取堆顶元素
DataType TopHeap(Heap* hp)
{
assert(hp->_size > 0);
return hp->_array[0];
}
(8)销毁堆
// 销毁堆
void DestroyHeap(Heap* hp)
{
if (hp == NULL)
{
return;
}
hp->_size = 0;
}
6.堆的应用
(1)堆排序
基本思想:堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。它是通过堆来进行选择数据。排升序要建大堆,排降序建小堆。
排序展示:
代码实现:
//堆排序
//1.建大堆
void swap(int *a, int *b) {
int t = *a;
*a = *b;
*b = t;
}
void heapify(int array[], int size, int index)
{
int left = 2 * index + 1;
int right = 2 * index + 2;
if (left >= size)
{
return;
}
int max = left;
if (right < size &&array[right] > array[left])
{
max = right;
}
if (array[index] >= array[max])
{
return;
}
int t = array[max];
array[max] = array[index];
array[index] = t;
index = max;
heapify(array, size, max);
}
void createHeap(int array[], int size)
{
for (int i = (size - 2) / 2; i >= 0; i--)
{
heapify(array, size, i);
}
}
void heapSort(int array[], int size)
{
createHeap(array, size);
for (int i = 0; i < size; i++)
{
int t = array[0];
array[0] = array[size - i-1];
array[size - 1 - i] = t;
heapify(array, size - i - 1, 0);
}
}
(2)topK问题
TopK问题是指从大量数据(源数据)中获取最大(或最小)的K个数据。
获取最大值:建小堆
获取最小值:建大堆