嵌牛IT观察

堆与堆排序

2020-11-29  本文已影响0人  Ivan07

姓名:毛浩 学号:17029250003

【嵌牛导读】一道力扣题。

【嵌牛鼻子】力扣

【嵌牛提问】如何解决同位异构词

【嵌牛正文】

堆与堆排序

@(数据结构)[堆||排序]

以下代码不敢保证均对,须自己验证


[TOC]

二叉堆的定义

二叉堆是完全二叉树或者是近似完全二叉树。
二叉堆满足两个特性:

堆的存储

一般都用数组来表示堆,i结点的父结点下标就为(i – 1) / 2。它的左右子结点下标分别为2 * i + 1和2 * i + 2。如第0个结点左右子结点下标分别为1和2。

堆的操作

2.png

堆的插入

每次插入都是将新数据插入到数组末尾,在插入之前数组即为有序数组,现在的任务相当于将一个数插入到有序数组中,一个插入排序算法如下:

void MinHeapFixup(int a[], int i){
    int j, tmp;
    tmp = a[i];
    j = (i - 1) / 2;//父节点
    while(j >= 0 && i != 0){
        if(a[j] < tmp)
            break;
        a[i] = a[j];
        i = j;
        j = (i - 1) / 2;
    }
    a[i] = tmp;
}

更简短的表达为:

void MinHeapFixup(int a[], int i){
    for(int j=(i-1)/2; j>=0 && a[i]>a[j]; i=j, j=(i-1)/2){
        swap(a[i], a[j]);
    }
}

堆的删除

按定义,堆中每次都只能删除第0个数据。为了便于重建堆,实际的操作是将最后一个数据的值赋给根结点,然后再从根结点开始进行一次从上向下的调整。调整时先在左右儿子结点中找最小的,如果父结点比这个最小的子结点还小说明不需要调整了,反之将父结点和它交换后再考虑后面的结点。相当于从根结点将一个数据的“下沉”过程。下面给出代码:

//  从i节点开始调整,n为节点总数 从0开始计算 i节点的子节点为 2*i+1, 2*i+2
void MinHeapFixdown(int a[], int i, int n)  
{
    int k, j;
    for (j = 2 * i + 1, k = i; j < n; k = j, j = 2 * j + 1)
    {
        if (j + 1 < n && a[j + 1] < a[j]) //在左右孩子中找最小的  
            j++;
        if (a[j] >= a[k])
            break;
        Swap(a[k], a[j]);
    }
}

//在最小堆中删除数
void MinHeapDeleteNumber(int a[], int n)
{
    Swap(a[0], a[n - 1]);
    MinHeapFixdown(a, 0, n - 1);
}
上一篇 下一篇

猜你喜欢

热点阅读