数据结构之堆的增删查改,应用,及其时间复杂度的计算

本文详细介绍了数据结构中的堆,包括堆的概念、性质、结构、初始化、插入、创建、判空、取堆顶值、销毁、删除等操作。重点讨论了向上和向下调整算法的时间复杂度,以及堆在堆排序和解决TOP-K问题中的应用。堆排序的时间复杂度分析表明,降序建大堆比升序建小堆更优。对于TOP-K问题,小堆优于大堆,特别是在内存限制的情况下。
摘要由CSDN通过智能技术生成

数据结构之堆

堆的概念:

如果有一个关键码的集合K = {k0 ,k1 ,k2 ,k3,…, kn-1},把它的所有元素按完全二叉树的顺序存储方式存储 在一个一维数组中,并满足:Ki <= K2*i+1且 Ki<=K2*i+2 (Ki >=K2*i+1 且 Ki>= K2*i+2) i = 0,1, 2…,则称为小堆(或大堆)。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆

1.堆的性质

  • 堆中的某个节点的值总是不大于或者不小于父节点的值(大堆或者小堆)
  • 堆总是一颗完全二叉树
堆的难点请添加图片描述

堆的逻辑结构和堆的物理存储结构是完全不一样的!操作的是数组,但是表示出来的却是二叉树!

2.堆的结构

typedef int  HPdataType;
typedef struct Heap
{
   
    HPdataType* data;//堆的存储结构本质就是一个数组
    int size;//用来表示数组内的元素的多少
    int capacity;//用来表示数组的内存大小!
}//堆的结构与顺序表相同,但是因为操作方式的不同导致了堆与顺序表完全不同的性质!

堆的创建后面进行阐述,因为堆的创建有两种方式一种是将一个非堆的数组通过调整变成堆,另一种是通过数组插入的方式获得一个堆,两种的本质其实都是相同的!

3.堆的初始化

void HeapIint(Heap* php)//堆刚创建的堆进行初始化!
{
   
    php->data = NULL;
    php->size = php->capacity = 0;
}

4.堆的插入

//堆插入的重点在于在插入后仍要保持堆的基本结构!保持大堆或者小堆!
//思路是先插入到最后面,然后进行向上调整算法
typedef int  HPdataType;
void AdjustUp(HPdataType* a,int child);

typedef struct Heap
{
   
    HPdataType* data;
    int size;
    int capacity;
}
void HeapPush(Heap* php,HPdataType x)
{
   
    assert(php);
    if(php->size == php->capacity)//先检查容量是否足够!不够则进行扩容
    {
   
        int newcapacity = php->capacity == 0 ? 4 : php->capacity * 2;
        HPdataType temp* = (HpdataType*)realloc(php->data,
        sizeof(HPdataType)*newcapacity);
        
        if(temp == NULL)//检查是否扩容成功!
        {
   
            perror("realloc fail!");
            return;
        }
        php->data = temp;
        php->capacity = newcapacity;
    }
    php->data[php->size++] = x;
    AdjustUp(php->a,php->size-1);
    //插入尾部,现在开始进行向上调整!将其调整为堆!
    //传过去最后一个插入的数据的位置和数组
    
}

void swap(HPdataType* x,HPdataType* y)
{
   
    HPdataType temp = *x;
    *x = *y;
    *y = temp;
}

void AdjustUp(HPdataType* a,int child)
{
   
    int parent = (child-1) / 2;//找到父节点
    
    while(child > 0)//child不用等于0因为,到0这个位置上面也就没有父节点了
    {
   
        if(a[child] > a[parent])//这里以大堆为例!
        {
      swap(&a[child],&a[parent]);
            child = parent;
            parent = (child -1)/2;
        }
        else
        {
   
            break;//遇到比child大的那么久跳出循环
        }
    }
    //这里如果使用parent>0,那么因为子节点还在下一个位置,则无法调整根节点
    //如果是parent>=0 因为parent =(0-1)/2 仍然为0,则就会出现死循环!
    
}
//向上调整算法的核心是对比父节点和子节点,如果是大堆,那么子节点大于父节点那么就进行互换位置
//如果是小堆那么则相反过来

请添加图片描述

向上调整算法的时间复杂度

为了方便计算我们以h层的满二叉树为例:
总结点数 N = 2h-1;
则 h = log2(N+1) ≈ logN;
所以向上调整算法的时间复杂度为logN。

5.堆的创建

从上面的堆的插入可以看出如果我们将第一个逻辑结构为完全二叉树的数组,一个个进行堆的插入到另一个数组中,这样子就可以创建出一个堆出来!

void HeapCreat(Heap* php,HPdataType* a,int size)
{
   
    for(int i = 0;i < size;i++)
    {
   
        HeapPush
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值