数据结构之堆详解

简介: 数据结构之堆详解

1.什么是堆

知道以上的存储方法,对于完全二叉树,有一个叫做堆的结构,堆本质就是一个完全二叉树,

堆分两种:1.大堆    2.小堆

除了是完全二叉树,大堆需满足任何一个双亲都大于等于孩子,对于小堆,任何一个双亲都小于等于孩子。

d6a453d84d494c2dbaaf71de58fd1d19.png

堆的定义

我们实现堆就用数组来实现的:这里以实现小堆为例

结构体定义与函数接口

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int HPDATAtype;
typedef struct Heap
{
  HPDATAtype *a;
  int size;
  int capacity;
}HP;
void Heapinit(HP* f);
void Heapdestroy(HP* f);
void Heappop(HP* f);
void Heappush(HP* f , HPDATAtype x);

堆的初始化

void Heapinit(HP* f)
{
  //初始有4个空间
  assert(f);
  f->a = NULL;
  f->size = 0;
  f->capacity = 0;
}

堆的销毁

void Heapdestroy(HP* f)
{
  assert(f->a);
  free(f->a);
  f->a = NULL;
}

入堆

void Heappush(HP* f, HPDATAtype x)
{
  assert(f);
  if (f->capacity == f->size)
  {
  int  newcapacity = f->capacity = 0 ? 4 : f->capacity*2;
      HPDATAtype* newnode = (HPDATAtype*)malloc(newcapacity);
  if (newnode == NULL)
  {
    perror("扩容失败\n");
    return;
  }
  f->a = newnode;
  f->capacity = f->capacity*2;
  }
  f->a[f->size] = x;
  f->size++;
  //向上调整算法
  Adjustup(f->a, f->size - 1);
  //向下调整算法
  //Adjustdown(f->a, f->size - 1);
}

在这里在入堆之后,也就是元素赋值到数组之后,根据你对数组的调整,也就是所说的向上调整算法,和向下调整算法,决定是小堆,还是大堆。

向上调整算法

我们这里通过对树所对应的数组元素的关系寻找父亲。 小堆:

void Adjustup(HPDATAtype*a, int child)
{
  //根据孩子zhaofuqin
  int parent = (child - 1) / 2;
  while (child>0)
  {
    if ( a[child]<a[parent])
    {
      HPDATAtype p = a[child];
      a [child] = a[parent];
      a[parent]=p;
      child = parent;
      parent = (child - 1) / 2;
    }
    else 
    {
      break;
    }
  }
}

大堆

这里只需要更改判断条件就变成大堆的调整

void Adjustdown(HPDATAtype* a, int child)
{
  //根据孩子找父亲
  int parent = (child - 1) / 2;
  while (child > 0)
  {
    if (a[child] > a[parent])
    {
      int tmp = a[child];
      a[child] = a[parent];
      a[parent] = tmp; 
        child = parent;
    parent = (child - 1) / 2;
    }
    else
    {
      break;
    }
  }
}

出堆

出堆就是最后一个元素换到第一个元素,在size--,之后在进行调整。

void Heappop(HP* f){
  assert(f);
  //堆顶元素出堆,最后元素出堆
  assert(f->size);
  int tmp = f->a[0];
  f->a[0] = f->a[f->size - 1];
  f->a[f->size - 1] = tmp;
  f->size--;
  //向下调整
  Adjustdown(f->a, f->size, 0);
};

向下调整算法

出堆为了不改变原有的父节点与兄弟节点的关系,采用的是将堆底的最后一个与第一个互换,在减减,此时我们仍需要调整堆,采用向下调整算法---即从第一个节点处开始,找作为父节点的儿子节点中较小的那一个,两者比较,循环调整。

因此传参需要堆的大小以及第一个父亲结点坐标也就是0.

void Adjustdown(HPDATAtype* a, int size,int parent)
{
  int child =parent * 2 +1;
  while (child<size)
  {
    if ((child+1<size)&&a[child + 1] < a[child])//若右孩子存在且小于左孩子
    {
      ++child;
    }
    if (a[child] < a[parent])
    {
      //交换
      int tmp = a[child];
      a[child] = a[parent];
      a[parent] = tmp;
      parent = child;
      child = parent * 2 + 1;
    }else
    {
      break;
    }
  }
}

返回堆顶元素

HPDATAtype HeapTop(HP* f)
{
  assert(f);
  assert(!HeapEmpty(f));
  return f->a[0];//返回堆顶数据
}

判空

bool HeapEmpty(HP* f)
{
  if (f->size == 0)
  {
    return true;
  }
  else
  {
    return false;
  }
}

堆的应用

.堆可以用作优先级队列,实现高效的插入和删除操作

.堆可以用来解决海量数据的topk问题,即从大量数据中找出最大或最小的k个数

.堆可以用来进行堆排序,即每次把堆顶元素和堆尾元素交换,然后重新调整堆,直到堆为空

.堆还可以用来实现一些其他的算法,比如哈夫曼编码,Dijkstra算法等

需要注意的是对于向上排序算法还是向下排序算法,他们都是一对一对的使用,从而取决于你是大堆还是小堆,主要体现调整算法中的判断条件。

相关文章
|
1月前
|
存储 算法 Java
散列表的数据结构以及对象在JVM堆中的存储过程
本文介绍了散列表的基本概念及其在JVM中的应用,详细讲解了散列表的结构、对象存储过程、Hashtable的扩容机制及与HashMap的区别。通过实例和图解,帮助读者理解散列表的工作原理和优化策略。
37 1
散列表的数据结构以及对象在JVM堆中的存储过程
|
1月前
|
存储 搜索推荐 算法
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
67 16
|
2月前
|
存储 JavaScript 前端开发
为什么基础数据类型存放在栈中,而引用数据类型存放在堆中?
为什么基础数据类型存放在栈中,而引用数据类型存放在堆中?
83 1
|
3月前
|
存储 Java
【数据结构】优先级队列(堆)从实现到应用详解
本文介绍了优先级队列的概念及其底层数据结构——堆。优先级队列根据元素的优先级而非插入顺序进行出队操作。JDK1.8中的`PriorityQueue`使用堆实现,堆分为大根堆和小根堆。大根堆中每个节点的值都不小于其子节点的值,小根堆则相反。文章详细讲解了如何通过数组模拟实现堆,并提供了创建、插入、删除以及获取堆顶元素的具体步骤。此外,还介绍了堆排序及解决Top K问题的应用,并展示了Java中`PriorityQueue`的基本用法和注意事项。
61 5
【数据结构】优先级队列(堆)从实现到应用详解
|
2月前
|
存储 算法 调度
数据结构--二叉树的顺序实现(堆实现)
数据结构--二叉树的顺序实现(堆实现)
|
2月前
|
存储 算法 分布式数据库
【初阶数据结构】理解堆的特性与应用:深入探索完全二叉树的独特魅力
【初阶数据结构】理解堆的特性与应用:深入探索完全二叉树的独特魅力
|
2月前
|
存储 算法
探索数据结构:分支的世界之二叉树与堆
探索数据结构:分支的世界之二叉树与堆
|
2月前
|
存储 算法 Java
【用Java学习数据结构系列】用堆实现优先级队列
【用Java学习数据结构系列】用堆实现优先级队列
35 0
|
2月前
|
存储 算法
【数据结构】二叉树——顺序结构——堆及其实现
【数据结构】二叉树——顺序结构——堆及其实现
|
2月前
【数据结构】大根堆和小根堆
【数据结构】大根堆和小根堆
38 0