堆的实现和习题

 二叉树

完全二叉树---->满二叉树。

左孩子下标都是奇数,右孩子下标都是偶数。

应用:

1堆排序 N*logN;(冒泡:N^2)

2topk;

3优先级队列;

实现代码

Heap.h


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

typedef int HPDataType;
typedef struct Heap
{
    HPDataType* a;
    int size;
    int capacity;
}HP;

void HeapInit(HP* php);
void HeapDestroy(HP* php);
void HeapPush(HP* php, HPDataType x);
void HeapPop(HP* php);
void AdjustUp(int* a,  int child);
void AdjustDown(int* a, int n, int parent);
HPDataType HeapTop(HP* php);
bool HeapEmpty(HP* php);
int HeapSize(HP* php);

Heap.c

#include "Heap.h"
void HeapInit(HP* php)
{
    assert(php);
    php->a = NULL;
    php->size = 0;
    php->capacity = 0;
}

void Swap(HPDataType* p1, HPDataType* p2)
{
    HPDataType tmp = *p1;
    *p1 = *p2;
    *p2 = tmp;
}

void HeapPush(HP* php, HPDataType x)
{
    assert(php);
    if (php->capacity == php->size)
    {
        int newcapacity = php->capacity == 0 ? 4 : php->capacity * 2;
        HPDataType* tmp = (HPDataType*)realloc(php->a, sizeof(HPDataType) * newcapacity);
        if (tmp == NULL)
        {
            perror("realloc fail");
            return;
        }
        php->a = tmp;
        php->capacity = newcapacity;

    }
    php->a[php->size] = x;
    php->size++;

    AdjustUp(php->a, php->size - 1);
}


void AdjustUp(int* a, int child)     //小堆.
{
    int parent = (child - 1) / 2;
    
    while (child > 0)
    {
        if (a[parent] > a[child])
        {
            Swap(&a[parent], &a[child]);
            child = parent;
            parent = (child - 1) / 2;
        }
        else
        {
            break;
        }
    }

}


void AdjustDown(int* a, int n, int parent)
{
    int child = parent * 2 +1;
    while (child < n)
    {
        if (child + 1 < n && a[child + 1] < a[child])
        {
            child++;
        }
        if (a[parent] > a[child])
        {
            Swap(&a[parent], &a[child]);
            parent = child;
            child = parent * 2 +1;
        }
        else
        {
            break;
        }
    }
}


void HeapPop(HP* php)
{
    assert(php);
    assert(!HeapEmpty(php));
    Swap(&php->a[0], &php->a[php->size - 1]);
    php->size--;
    AdjustDown(php->a, php->size, 0);
}

bool HeapEmpty(HP* php)
{
    assert(php);
    return php->size == 0;
}

HPDataType HeapTop(HP* php)
{
    assert(php);
    assert(!HeapEmpty(php));
    return php->a[0];
}


int HeapSize(HP* php)
{
    assert(php);
    return php->size;
}

void HeapDestroy(HP* php)
{
    assert(php);
    free(php->a);
    php->a = NULL;
    php->capacity = php->size = 0;
}

test.c

#include "Heap.h"


//int main()
//{
//    HP hp;
//    HeapInit(&hp);
//    int a[] = { 65,100,70,32,50,60, };
//    for (int i = 0; i < sizeof(a) / sizeof(int); i++)
//    {
//        HeapPush(&hp, a[i]);          //建堆完毕。
//    }
//
//    while (!HeapEmpty(&hp))
//    {
//        int top = HeapTop(&hp);
//        printf("%d\n", top);
//        HeapPop(&hp);
//    }
//
//
//    return 0;
//}


void HeapSort(int* a, int n)
{
    HP hp;
    HeapInit(&hp);
    for (int i = 0; i < n; i++)
    {
        HeapPush(&hp, a[i]);
    }

    int i = 0;
    while ()
    {
        int top = HeapTop(&hp);
        a[i++] = top;
        HeapPop(&hp);

    }
}


堆排序的说明(含降序堆逻辑):

时间复杂度:O(N*logN)

冒泡的是N*N;

堆排序:

升序的实现逻辑为:构建小堆,取出堆顶放入a[0],再Pop出堆顶元素。(Pop里有向下调整函数)。

排降序:小堆,选出最小的,首位交换,最小的放在最后的位置,把最后一个数据,不看作堆里面的,向下调整选出次小的。重复交换操作...

实现逻辑

void HeapSort(int *a,int n)

{
for(int i=1;i<n;i++)

{

  AdjustUp(a,i)

}

int end=n-1;

while(end>0)

{

Swap(&a[0],&a[end]);

AdjustDown(a,end,0)

end--;

}

}

巨量数的堆排:

前K个数建小堆。

后面的N-K个数依次比较,如果比堆顶大,则替换掉进堆,堆向下排序。

最后小堆的值就是最大的k个。

向下调整!!!

nlogn
 

  • 23
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值