Binary heap [turn]

What is the binary heap?

Binary heap is a special heap. It has the following characteristics:

  1. It features a full complement binary tree.
  2. Any value of a parent node of the heap is greater than a value approximately equal to its child nodes (max heap), which is about equal to or less than the value of the child node (minimum heap).

This is the maximum heap:

image

The minimum heap:

image

We call it the root of a binary heap top of the heap. The characteristics of the binary heap, or to go to top of the stack is the largest element of the entire heap, the smallest element to be incorrect.

It should be noted however that in the binary heap such a structure, for deleting a node, we generally deleted is the root node.

Suppose the "first element" array index is 0, then the positional relationship between the parent and child nodes as follows:

  1. Index i left the child's index is (2 * i + 1);
  2. The right child index i is the index (2 * i + 2);
  3. Index i is the parent node is an index floor ((i-1) / 2);

image

Suppose the "first element" in the array index is 1, then the positional relationship between the parent and child nodes as follows:

  1. Index i left the child's index is (2 * i);
  2. The right child index i is the index (2 * i + 1);
  3. Index i is the parent node is an index floor (i / 2);

image

Graphic parsing binary heap

In front, we have learned that: "The biggest heap" and "minimum heap" is a symmetrical relationship. This also means, of which one can understand. Graphic resolve this section is based on "maximum heap" be introduced.

Binary heap is the core of the "Add node" and "delete node", understand these two algorithms, binary heap will basically mastered. Here they are introduced.

1. Add

Assuming the maximum stack [90,80,70,60,40,30,20,10,50] species adding 85, you need to perform the following steps:

image

As shown above, when adding data to the maximum heap: first data is added to the end of the maximum heap, as this element is then moved up until it stops move!

Once added to the [90,80,70,60,40,30,20,10,50] 85, it becomes the maximum heap [90,85,70,60,80,30,20,10,50, 40].

The maximum stack insertion code (C language)

/*
 * 最大堆的向上调整算法(从start开始向上直到0,调整堆)
 *
 * 注:数组实现的堆中,第N个节点的左孩子的索引值是(2N+1),右孩子的索引是(2N+2)。
 *
 * 参数说明:
 *     start -- 被上调节点的起始位置(一般为数组中最后一个元素的索引)
 */
static void maxheap_filterup(int start)
{
    int c = start;            // 当前节点(current)的位置
    int p = (c-1)/2;        // 父(parent)结点的位置 
    int tmp = m_heap[c];        // 当前节点(current)的大小

    while(c > 0)
    {
        if(m_heap[p] >= tmp)
            break;
        else
        {
            m_heap[c] = m_heap[p];
            c = p;
            p = (p-1)/2;   
        }       
    }
    m_heap[c] = tmp;
}
  
/* 
 * 将data插入到二叉堆中
 *
 * 返回值:
 *     0,表示成功
 *    -1,表示失败
 */
int maxheap_insert(int data)
{
    // 如果"堆"已满,则返回
    if(m_size == m_capacity)
        return -1;
 
    m_heap[m_size] = data;        // 将"数组"插在表尾
    maxheap_filterup(m_size);    // 向上调整堆
    m_size++;                    // 堆的实际容量+1

    return 0;
}

Effect maxheap_insert (data) of: adding data to the maximum data stack.

When the stack is full, it attaches failure; otherwise data added to the end of the largest heap. Then re-adjust the array by up-regulating algorithm, making it the largest heap again.

2. Delete

Remove the stack 90 from assuming the maximum [90,85,70,60,80,30,20,10,50,40], the following steps need to be performed:

image

After you remove 90 from [90,85,70,60,80,30,20,10,50,40], the maximum heap becomes [85,80,70,60,40,30,20,10,50] .

As shown above, when the maximum data is deleted from the stack: to delete the data, and then insert the element with the largest gap of the last stack; Subsequently, this "gap" moved up as far as possible, until the remaining data into one of the biggest heap.

Note: Consider [90,85,70,60,80,30,20,10,50,40] deleted 60 from the maximum heap, simple steps can not be used to replace its child nodes; and must take into account " If the tree is replaced still the largest heap "!

image

The largest heap of removing the code (C language)

/* 
 * 返回data在二叉堆中的索引
 *
 * 返回值:
 *     存在 -- 返回data在数组中的索引
 *     不存在 -- -1
 */
int get_index(int data)
{
    int i=0;

    for(i=0; i<m_size; i++)
        if (data==m_heap[i])
            return i;

    return -1;
}

/* 
 * 最大堆的向下调整算法
 *
 * 注:数组实现的堆中,第N个节点的左孩子的索引值是(2N+1),右孩子的索引是(2N+2)。
 *
 * 参数说明:
 *     start -- 被下调节点的起始位置(一般为0,表示从第1个开始)
 *     end   -- 截至范围(一般为数组中最后一个元素的索引)
 */
static void maxheap_filterdown(int start, int end)
{
    int c = start;          // 当前(current)节点的位置
    int l = 2*c + 1;     // 左(left)孩子的位置
    int tmp = m_heap[c];    // 当前(current)节点的大小

    while(l <= end)
    {
        // "l"是左孩子,"l+1"是右孩子
        if(l < end && m_heap[l] < m_heap[l+1])
            l++;        // 左右两孩子中选择较大者,即m_heap[l+1]
        if(tmp >= m_heap[l])
            break;        //调整结束
        else
        {
            m_heap[c] = m_heap[l];
            c = l;
            l = 2*l + 1;   
        }       
    }   
    m_heap[c] = tmp;
}

/*
 * 删除最大堆中的data
 *
 * 返回值:
 *      0,成功
 *     -1,失败
 */
int maxheap_remove(int data)
{
    int index;
    // 如果"堆"已空,则返回-1
    if(m_size == 0)
        return -1;

    // 获取data在数组中的索引
    index = get_index(data); 
    if (index==-1)
        return -1;

    m_heap[index] = m_heap[--m_size];        // 用最后元素填补
    maxheap_filterdown(index, m_size-1);    // 从index位置开始自上向下调整为最大堆

    return 0;
}

Role maxheap_remove (data): Maximum heap delete data from the data.

When the stack is already empty when the delete fails; otherwise dealt with position data in the largest heap array. After finding the first to the last element to be replaced by removing elements; and then re-adjust the array by down algorithm, making it the largest heap again.

The "Complete code sample" and "the minimum heap related codes", refer to the implementation of a binary heap below.

C achieve binary heap (full source code)

Binary heap implementation includes both "maximum heap" and "minimum stack", which are symmetrical relation; appreciated that one, the other is very easy to understand.

Binary heap (max heap) implementation file (max_heap.c)

/**
 * 二叉堆(最大堆)
 *
 * @author skywang
 * @date 2014/03/07
 */

#include <stdio.h>
#include <stdlib.h>

#define LENGTH(a) ( (sizeof(a)) / (sizeof(a[0])) )

static int m_heap[30];        // 数据
static int m_capacity=30;    // 总的容量
static int m_size=0;        // 实际容量(初始化为0)
 
/* 
 * 返回data在二叉堆中的索引
 *
 * 返回值:
 *     存在 -- 返回data在数组中的索引
 *     不存在 -- -1
 */
int get_index(int data)
{
    int i=0;

    for(i=0; i<m_size; i++)
        if (data==m_heap[i])
            return i;

    return -1;
}

/* 
 * 最大堆的向下调整算法
 *
 * 注:数组实现的堆中,第N个节点的左孩子的索引值是(2N+1),右孩子的索引是(2N+2)。
 *
 * 参数说明:
 *     start -- 被下调节点的起始位置(一般为0,表示从第1个开始)
 *     end   -- 截至范围(一般为数组中最后一个元素的索引)
 */
static void maxheap_filterdown(int start, int end)
{
    int c = start;          // 当前(current)节点的位置
    int l = 2*c + 1;     // 左(left)孩子的位置
    int tmp = m_heap[c];    // 当前(current)节点的大小

    while(l <= end)
    {
        // "l"是左孩子,"l+1"是右孩子
        if(l < end && m_heap[l] < m_heap[l+1])
            l++;        // 左右两孩子中选择较大者,即m_heap[l+1]
        if(tmp >= m_heap[l])
            break;        //调整结束
        else
        {
            m_heap[c] = m_heap[l];
            c = l;
            l = 2*l + 1;   
        }       
    }   
    m_heap[c] = tmp;
}

/*
 * 删除最大堆中的data
 *
 * 返回值:
 *      0,成功
 *     -1,失败
 */
int maxheap_remove(int data)
{
    int index;
    // 如果"堆"已空,则返回-1
    if(m_size == 0)
        return -1;

    // 获取data在数组中的索引
    index = get_index(data); 
    if (index==-1)
        return -1;

    m_heap[index] = m_heap[--m_size];        // 用最后元素填补
    maxheap_filterdown(index, m_size-1);    // 从index位置开始自上向下调整为最大堆

    return 0;
}

/*
 * 最大堆的向上调整算法(从start开始向上直到0,调整堆)
 *
 * 注:数组实现的堆中,第N个节点的左孩子的索引值是(2N+1),右孩子的索引是(2N+2)。
 *
 * 参数说明:
 *     start -- 被上调节点的起始位置(一般为数组中最后一个元素的索引)
 */
static void maxheap_filterup(int start)
{
    int c = start;            // 当前节点(current)的位置
    int p = (c-1)/2;        // 父(parent)结点的位置 
    int tmp = m_heap[c];        // 当前节点(current)的大小

    while(c > 0)
    {
        if(m_heap[p] >= tmp)
            break;
        else
        {
            m_heap[c] = m_heap[p];
            c = p;
            p = (p-1)/2;   
        }       
    }
    m_heap[c] = tmp;
}
  
/* 
 * 将data插入到二叉堆中
 *
 * 返回值:
 *     0,表示成功
 *    -1,表示失败
 */
int maxheap_insert(int data)
{
    // 如果"堆"已满,则返回
    if(m_size == m_capacity)
        return -1;
 
    m_heap[m_size] = data;        // 将"数组"插在表尾
    maxheap_filterup(m_size);    // 向上调整堆
    m_size++;                    // 堆的实际容量+1

    return 0;
}
  
/* 
 * 打印二叉堆
 *
 * 返回值:
 *     0,表示成功
 *    -1,表示失败
 */
void maxheap_print()
{
    int i;
    for (i=0; i<m_size; i++)
        printf("%d ", m_heap[i]);
}
    
void main()
{
    int a[] = {10, 40, 30, 60, 90, 70, 20, 50, 80};
    int i, len=LENGTH(a);

    printf("== 依次添加: ");
    for(i=0; i<len; i++)
    {
        printf("%d ", a[i]);
        maxheap_insert(a[i]);
    }

    printf("\n== 最 大 堆: ");
    maxheap_print();

    i=85;
    maxheap_insert(i);
    printf("\n== 添加元素: %d", i);
    printf("\n== 最 大 堆: ");
    maxheap_print();

    i=90;
    maxheap_remove(i);
    printf("\n== 删除元素: %d", i);
    printf("\n== 最 大 堆: ");
    maxheap_print();
    printf("\n");
}

Binary heap (minimum heap) implementation file (min_heap.c)

/**
 * 二叉堆(最小堆)
 *
 * @author skywang
 * @date 2014/03/07
 */

#include <stdio.h>
#include <stdlib.h>

#define LENGTH(a) ( (sizeof(a)) / (sizeof(a[0])) )

static int m_heap[30];
static int m_capacity=30;    // 总的容量
static int m_size=0;        // 实际容量(初始化为0)
 
/* 
 * 返回data在二叉堆中的索引
 *
 * 返回值:
 *     存在 -- 返回data在数组中的索引
 *     不存在 -- -1
 */
int get_index(int data)
{
    int i=0;

    for(i=0; i<m_size; i++)
        if (data==m_heap[i])
            return i;

    return -1;
}

/* 
 * 最小堆的向下调整算法
 *
 * 注:数组实现的堆中,第N个节点的左孩子的索引值是(2N+1),右孩子的索引是(2N+2)。
 *
 * 参数说明:
 *     start -- 被下调节点的起始位置(一般为0,表示从第1个开始)
 *     end   -- 截至范围(一般为数组中最后一个元素的索引)
 */
static void minheap_filterdown(int start, int end)
{
    int c = start;          // 当前(current)节点的位置
    int l = 2*c + 1;     // 左(left)孩子的位置
    int tmp = m_heap[c];    // 当前(current)节点的大小

    while(l <= end)
    {
        // "l"是左孩子,"l+1"是右孩子
        if(l < end && m_heap[l] > m_heap[l+1])
            l++;        // 左右两孩子中选择较小者,即m_heap[l+1]
        if(tmp <= m_heap[l])
            break;        //调整结束
        else
        {
            m_heap[c] = m_heap[l];
            c = l;
            l = 2*l + 1;   
        }       
    }   
    m_heap[c] = tmp;
}
 
/*
 * 删除最小堆中的data
 *
 * 返回值:
 *      0,成功
 *     -1,失败
 */
int minheap_remove(int data)
{
    int index;
    // 如果"堆"已空,则返回-1
    if(m_size == 0)
        return -1;

    // 获取data在数组中的索引
    index = get_index(data); 
    if (index==-1)
        return -1;

    m_heap[index] = m_heap[--m_size];        // 用最后元素填补
    minheap_filterdown(index, m_size-1);    // 从index号位置开始自上向下调整为最小堆

    return 0;
}

/*
 * 最小堆的向上调整算法(从start开始向上直到0,调整堆)
 *
 * 注:数组实现的堆中,第N个节点的左孩子的索引值是(2N+1),右孩子的索引是(2N+2)。
 *
 * 参数说明:
 *     start -- 被上调节点的起始位置(一般为数组中最后一个元素的索引)
 */
static void filter_up(int start)
{
    int c = start;            // 当前节点(current)的位置
    int p = (c-1)/2;        // 父(parent)结点的位置 
    int tmp = m_heap[c];        // 当前节点(current)的大小

    while(c > 0)
    {
        if(m_heap[p] <= tmp)
            break;
        else
        {
            m_heap[c] = m_heap[p];
            c = p;
            p = (p-1)/2;   
        }       
    }
    m_heap[c] = tmp;
}
  
/* 
 * 将data插入到二叉堆中
 *
 * 返回值:
 *     0,表示成功
 *    -1,表示失败
 */
int minheap_insert(int data)
{
    // 如果"堆"已满,则返回
    if(m_size == m_capacity)
        return -1;
 
    m_heap[m_size] = data;        // 将"数组"插在表尾
    filter_up(m_size);            // 向上调整堆
    m_size++;                    // 堆的实际容量+1

    return 0;
}
  
/* 
 * 打印二叉堆
 *
 * 返回值:
 *     0,表示成功
 *    -1,表示失败
 */
void minheap_print()
{
    int i;
    for (i=0; i<m_size; i++)
        printf("%d ", m_heap[i]);
}

void main()
{
    int a[] = {80, 40, 30, 60, 90, 70, 10, 50, 20};
    int i, len=LENGTH(a);

    printf("== 依次添加: ");
    for(i=0; i<len; i++)
    {
        printf("%d ", a[i]);
        minheap_insert(a[i]);
    }

    printf("\n== 最 小 堆: ");
    minheap_print();

    i=15;
    minheap_insert(i);
    printf("\n== 添加元素: %d", i);
    printf("\n== 最 小 堆: ");
    minheap_print();

    i=10;
    minheap_remove(i);
    printf("\n== 删除元素: %d", i);
    printf("\n== 最 小 堆: ");
    minheap_print();
    printf("\n");
}

Binary heap of C test program

Test procedures have been included in the corresponding implementation file, and will not repeat here the explanation.

The maximum heap (max_heap.c) operating results:

== 依次添加: 10 40 30 60 90 70 20 50 80 
== 最 大 堆: 90 80 70 60 40 30 20 10 50 
== 添加元素: 85
== 最 大 堆: 90 85 70 60 80 30 20 10 50 40 
== 删除元素: 90
== 最 大 堆: 85 80 70 60 40 30 20 10 50

The minimum heap (min_heap.c) operating results:

== 依次添加: 80 40 30 60 90 70 10 50 20 
== 最 小 堆: 10 20 30 50 90 70 40 80 60 
== 添加元素: 15
== 最 小 堆: 10 15 30 50 20 70 40 80 60 90 
== 删除元素: 10
== 最 小 堆: 15 20 30 50 90 70 40 80 60

Guess you like

Origin www.cnblogs.com/linhaostudy/p/11517408.html