堆的相关操作与堆排序

堆中插入、删除元素

先看图解:


堆的插入与删除图解

堆中插入元素

插入元素总是插入在数组中的最后一个位置,然后从其父节点依次向上调整堆,执行元素“上浮”操作。

//在最小堆中加入新的数据nNum
void addNumber(int[] a, int n, int nNum)
{
    a[n] = nNum;
    fixup(a, n);
}

//  新加入i结点  其父结点为(i - 1) / 2
void fixup(int[] a, int i)
{
    int j, temp;
    
    
    j = (i - 1) / 2;      //父结点
    while (j >= 0 && i != 0)     
    {
        if (a[j] <= a[i])       
            break;
        //父节点比当前节点大
        swap(a,i,j);    //当前节点与它的父节点交换,上浮

        i = j;      //继续向上调整堆
        j = (i - 1) / 2;
    }
    
}
//更简洁的写法:
void fixup2(int[] a, int i)
{
    for (int j = (i - 1) / 2; 
           (j >= 0 && i != 0)&& a[i] > a[j];
            i = j, j = (i - 1) / 2)

        swap(a, i, j);
}

堆中删除元素

删除元素时,总是删除堆顶元素,后将堆中最后一个元素放置对顶,从堆顶到叶子节点依次向下调整堆,执行元素“下沉操作”。

//在最小堆中删除数
void deleteNumber(int[] a, int n)
{
    swap(a[0], a[n - 1]);
    fixdown(a, 0, n - 1);
}
//  从i节点开始调整,n为节点总数 从0开始计算 i节点的子节点为 2*i+1, 2*i+2
void fixdown(int[] a, int i, int n)
{
    int j, temp;
 
    temp = a[i];
    j = 2 * i + 1;
    while (j < n)
    {
        if (j + 1 < n && a[j + 1] < a[j]) //在左右孩子中找最小的
            j++;
 
        if (a[j] >= temp)
            break;
 
        swap(a,i,j);   //与左右孩子中最小的交换,下沉

        i = j;            //继续向下调整堆
        j = 2 * i + 1;
    }

}

堆的初始化

有了堆的插入和删除后,再考虑下如何对一个数据进行堆化操作。
从最后一个非叶子结点,直至根节点,自底向上,对以这些节点为根节点的子树逐渐执行元素下沉操作。

//建立最小堆
void MakeMinHeap(int[] a, int n)
{
    for (int i = n / 2 - 1; i >= 0; i--)
        fixdown(a, i, n);
}

堆排序的完整代码

void minHeapSort(int[] a, int n)
{
    makeMinHeap(a,n);
    for (int i = n - 1; i >= 1; i--)
    {
        swap(a[i], a[0]);
        fixdown(a, 0, i);
    }
}

void makeMinHeap(int[] a, int n)
{
    for (int i = n / 2 - 1; i >= 0; i--)
        fixdown(a, i, n);
}

void fixdown(int[] a, int i, int n)
{
    int j, temp;
 
    temp = a[i];
    j = 2 * i + 1;
    while (j < n)
    {
        if (j + 1 < n && a[j + 1] < a[j]) //在左右孩子中找最小的
            j++;
 
        if (a[j] >= temp)
            break;
 
        swap(a,i,j);   //与左右孩子中最小的交换,下沉

        i = j;            //继续向下调整堆
        j = 2 * i + 1;
    }

}

你可能感兴趣的:(堆的相关操作与堆排序)