数据结构:堆
堆是一种满足堆属性的特殊的树,对最小堆来说,父节点的键值小于或等于子节点,而最大堆来说,父节点要大于或等于子节点。下面我将以二叉堆的形式来介绍,所以树中的每个节点至多有两个孩子。
wikipedia链接:二 叉堆一般用数组来表示。如果根节点在数组中的位置是1,第n个位置的子节点分别在2n和 2n+1。因此,第1个位置的子节点在2和3,第2个位置的子节点在4和5。以此类推。这种基于1的数组存储方式便于寻找父节点和子节点如果存储数组的下标基于0,那么下标为i的节点的子节点是2i + 1与2i + 2;其父节点的下标是⌊floor((i − 1) ∕ 2)⌋。函数floor(x)的功能是“向下取整”,或者说“向下舍入”,即取不大于x的最大整数(与“四舍五入”不同,向下取整是直接取按照数轴上最接近要求值的左边值,即不大于要求值的最大的那个值)。比如floor(1.1)、floor(1.9)都返回1
- 二叉堆具有以下两个属性:
- 1)形状属性:二叉堆是一颗完全二叉树,
- 2)堆属性:
- 最大堆:每个节点存储的值或大于或等与它的子节点
- 小根堆:每个节点存储的值小于或等于它的子节点
我们以数组{3,1,6,5,2,4}为例建造堆,从空堆开始,然后不断插入数组中的数到堆中。
Williams Algorithm: top down
while not end of array,
if heap is empty,
place item at root;
else,
place item at bottom of heap;
while (child < parent)
swap(parent, child);
go to next array element;
end
我们对以上数组按照下面的算法,构建最小堆的步骤如下:
![](https://img.haomeiwen.com/i15565446/6e9b1675f629e316.png)
对应的c++代码如下:
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
void minheap();
using namespace std;
int arr[8] = { 53,17,78,9,45,65,87,23 };
int *a = new int[8];//保存小根堆
int index = 0;
int main()
{
minheap();
cout << "建立的最小堆为:" << endl;
for (int i = 0; i < 8; i++)
{
cout << a[i] <<" ";
}
system("pause");
}
void minheap()
{
while (index < 8)
{
if (index == 0)
{
a[index] = arr[index];//初始化
index++;
}
else
{
a[index] = arr[index];
int parent = floor((index - 1) / 2);
int flag = index;
while (a[parent] > a[flag])//小根堆:父节点大的话需要交换
{
int temp = a[parent];//交换
a[parent] = a[flag];
a[flag] = temp;
flag = parent;//迭代看之前的是否需要调整
parent = floor((flag - 1) / 2);
}
index++;
}
}
}
网友评论