初阶数据结构 堆(一)

简介: 初阶数据结构 堆(一)

一. 堆的概念和性质


我们在上一篇博客介绍存储二叉树的两种方式


分别是顺序结构和链式结构


顺序结构和链式结构


1. 堆的概念


这里注意!!! 这里说的堆和操作系统里面的堆没有半点关系!!!


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


上面这个就是官方的解释了


但是要是我们用通俗的话来说


就是这样子的


大堆 就是所有的父节点都大于等于子节点的堆


小堆 就是所有的子节点都小于等于父节点的堆


如图


557a467840254b149e34dc2006aa624c.png


2. 堆的性质


堆总是一棵完全的二叉树


堆中某个节点的值总是不大于或者不小于其父节点的值


3. 小题目练练手


1.下列关键字序列为堆的是:()


A 100,60,70,50,32,65

B 60,70,65,50,32,100

C 65,100,70,32,50,60

D 70,65,100,32,50,60

E 32,50,100,70,65,60

F 50,100,70,65,60,32


我们首先来看A

cceeb932ffec47a780e7ef9be059fa48.png


很明显 满足大堆的定义


所以该题选A


我们再来看看B是不是错的

31d0ae8096d64cceaa8209c60a98d427.png


很明显是错的


所以更加确定了答案是A


二. 代码实现以及堆的部分接口函数


1. 结构体代码


结构体代码表示如下


typedef int HeapType;
typedef struct Heap
{
  HeapType* arr;
  int size;
  int capacity;
}HP;


2. 初始化以及销毁


这两段代码很简单 这里就连起来写了


void HeapInit(HP* hp)
{
  assert(hp);
  hp->arr = NULL;
  hp->capacity = 0;
  hp->size = 0;
}
void HeapDestroy(HP* hp)
{
  assert(hp);
  free(hp->arr);
  hp->capacity = 0;
  hp->size = 0;
}


两段代码表示如上


3. 增加数据 (大堆为例)


void HeapPush(HP* hp, HeapType x);
• 1


我们这里增加数据要先考虑一点


储存数据的空间够不够


如果不够的话我们就要扩容空间了


这一段代码已经讲过很多次了


我就不讲解了


判断代码如下


  assert(hp);
  if (hp->size==hp->capacity)
  {
    int newcapacity = hp->capacity * 2 + 4;
    HeapType* tmp = realloc(hp->arr, sizeof(HeapType) * newcapacity);
    if (tmp==NULL)
    {
      printf("HeapPush error");
      exit(-1);
    }
    else
    {
      hp->capacity = newcapacity;
      hp->arr = tmp;
    }
  }

1ff8af7fb57e4ce7919a8e8fe7896bb7.png


当我们这里插入一个75的时候 这里明显是错误的啊 怎么办呢?


这个时候我们就需要将它跟它的父亲比较 是否大于它的父亲


如果不大于就填入


如果小于就交换它和它的父亲


知道孩子等于0为止


下面开始写代码


我们用一个函数来写 防止要复用


void JudgeHeap(HP* hp,int size,int set)
{
  assert(hp);
  int child = set;
  int father = (child - 1) / 2;
  while (child!=0)
  {
    if (hp->arr[child]>hp->arr[father])
    {
      HeapType* tmp = 0;
      tmp = hp->arr[child];
      hp->arr[child] = hp->arr[father];
      hp->arr[father] = tmp;
      child = father;
      father = (child - 1) / 2;
    }
    else
    {
      break;
    }
  }
}
void HeapPush(HP* hp, HeapType x)
{
  assert(hp);
  if (hp->size==hp->capacity)
  {
    int newcapacity = hp->capacity * 2 + 4;
    HeapType* tmp = realloc(hp->arr, sizeof(HeapType) * newcapacity);
    if (tmp==NULL)
    {
      printf("HeapPush error");
      exit(-1);
    }
    else
    {
      hp->capacity = newcapacity;
      hp->arr = tmp;
    }
  }
  hp->arr[hp->size] = x;
  hp->size++;
  JudgeHeap(hp,hp->size,hp->size-1);
}


整体代码表示如上

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