构造最小最大堆--从0开始建堆

数据结构:堆

堆是一种满足堆属性的特殊的树,对最小堆来说,父节点的键值小于或等于子节点,而最大堆来说,父节点要大于或等于子节点。下面我将以二叉堆的形式来介绍,所以树中的每个节点至多有两个孩子。

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

我们对以上数组按照下面的算法,构建最小堆的步骤如下:


heap.png

对应的c++代码如下:

#include
#include
#include
#include
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++;
        }
    }

}

你可能感兴趣的:(构造最小最大堆--从0开始建堆)