数组实现“堆”(数据结构)

“堆”是一种特殊的树形数据结构,他满足堆的特性:父节点一定不会小于子节点(或大于)。

所有的堆都有着完全二叉树的结构,与完全二叉树不同的就是堆的左子节点的值和右子节点的值没有特定的大小关系

数组实现堆相对于链表更好理解,但相应的也需要标记出数组的光标位置和数组的大小, 需要注意堆实际上是在数组下标为1处开始的,下标为0处存放一个超过数据界限的最大值。

下面以一个最大堆为例子:

结构体:

typedef struct Heap
{
    ElementType *data;
    int size;
    int MAX_SIZE;
}Heap, *hLink;


创建空堆:

hLink CreatHeap(int MAX_SIZE)
{
    hLink k = (hLink)malloc(sizeof(Heap));
    k->data = (ElementType*)malloc(sizeof(ElementType));
    k->MAX_SIZE = MAX_SIZE;
    k->size = 0;
    k->data[0] = 100;
    return k;
}


向该堆中插入一个值:

数组的插入位置决定了树上插入的位置,根据规律能得出:“每个节点的父母节点所在的数组位置” * 2 = 该节点位置

void Insert(hLink L, ElementType num)
{
    if(L->MAX_SIZE == L->size)
    {
        printf("Full!\n");
        return;
    }
    int i = ++L->size;
    for(; L->data[i/2] < num; i/=2)
    {
        L->data[i] = L->data[i/2];
    }
    L->data[i] = num;
}

从最大堆中删除一个最大值或最小堆中删除一个最小值(即删除堆顶元素)

删除就是:将根节点的值改为最后一个节点的值,size减一,然后一步一步的将在根节点的权值改到适合其所在的位置的过程。

ElementType Delete(hLink L)
{
    int Parent, Child;
    ElementType maxOne, mid;
    if(!L->size)
    {
        printf("Empty!\n");
        return -1;
    }
    maxOne = L->data[0];
    mid = L->data[size--];
    for(Parent = 1; Parent*2 <= L->size; Parent = Child)
    {
        Child = Parent * 2;
        if(Child < L->size&& L->data[Child] < L->data[Child + 1])
        {
            Child++;
        }
        if(L->data[Child] < mid)
        {
            break;
        }
        L->data[Parent] = L->data[Child];
    }
    L->data[Parent] = mid;
    return maxOne;
}

初始化一个堆

初始化一个堆的方法有两种,一种就是:

每读取一个元素,就以插入的形式插入一个堆中,但花费时间较多,时间为:O(N*log(N));

另一种方法即为:

先将元素存入data数组中,然后再将元素进行堆排序,这个方法用时较短,为O(log(N));

堆排序:

堆排序的思想就是:因为数组存的元素之间不能构成堆,故从最后一个拥有子节点的节点开始运行类似于删除节点的算法,然后逐步向前使得每个有子树的节点都满足堆的定义,最终形成堆。

void Ordering(hLink H, int pos)
{
    int Parent, Child;
    ElementType one;
    one = H->data[pos];
    for(Parent = pos; Parent * 2 <= H->size; Parent = Child)
    {
        Child = 2 * Parent;
        if(Child < H->size&& H->data[Child] < H->data[Child + 1])
        {
            Child++;
        }
        if(H->data[Child] < one)
        {
            break;
        }
        H->data[Parent] = H->data[Child];
    }
    H->data[Parent] = one;
}

void InitHeap(hLink H)
{
    int N;
    scanf("%d", &N);
    int i;
    ElementType mid;
    for(i = 1; i <= N; i++)
    {
        scanf("%d", &mid);
        H->data[i] = mid;
    }
    H->size = N;
    int pos = N / 2;
    for(; pos > 0; pos--)
    {
        Ordering(H, pos);
    }
}




猜你喜欢

转载自blog.csdn.net/qq_35859033/article/details/78488838