C语言实现大顶堆的示例代码

目录
  • 堆的实现
    • 1.堆结构
    • 2.堆的种类
    • 3.大顶堆代码实现

堆的实现

1.堆结构

逻辑结构上类似于 一棵 “树”

2.堆的种类

大顶堆结构: 一种特殊的树:其每个子节点均比母节点要小

小顶堆结构: 同理:其每个子节点均比母节点要大

结构图示:

3.大顶堆代码实现

这里实现堆 用循序表的方式

①初始化:

typedef int Heaptype;

typedef struct Heap
{
    Heaptype* head;
    int size;         //记录堆总容量
    int capacity;     //记录当前数据总个数
}Heap;

//堆的初始化
void Heap_Init(Heap* pphead)
{
    assert(pphead);
    pphead->head = NULL;
    pphead->size = 0;
    pphead->capacity = 0;
}

②插入数据:

实现细节:数据在插入的同时,要进行数据结构的调整,使树顶始终保持最大数

如果新插入节点比母节点大的话,要进行交换 ,因此将这个调整结构的环节独立出来

即:“向上调整”。

向上调整:因为插入数据时:新数据默认储存在顺序表尾,因此其逻辑上是在堆的底部,

所以,当新数据比母节点大时,它将与逻辑上处于其上方的母节点交换,称为

向上调整。

注:向上调整有时不止调整一次 ,还有可能调整多次,直到每个节点都在其相应位置 。

流程图解:

大顶堆插入流程

细节点:因为数据是以顺序表的方式储存,所以子节点的下标与母节点的下标符合

公式:parent = (child - 1)/2 ;(按照此公式带入计算就理解了)

//向上调整
void adjust_up(Heap* pphead)
{
    int child = pphead->capacity;
    int parent = (child - 1) / 2;
    for (; pphead->head[parent] < pphead->head[child];)//判断是否符合大顶堆
    {
        swap(&(pphead->head[parent]),&(pphead->head[child]));//进行交换
        child = parent;
        parent = (child - 1) / 2;
    }
}

//插入数据
void Heap_push(Heap* pphead, Heaptype data)
{
    assert(pphead);
    //判断是否满容量并扩容
    Heap_realloc(pphead);
    pphead->head[pphead->capacity] = data;
    //向上调整
    adjust_up(pphead);
    pphead->capacity++;
}

③删除数据:为了避免因为直接删除头部数据导致整个堆的结构打乱,

这里先将头部数据与尾数据交换,然后将尾部数据删除,接着使用“向下调整”,即:将换上来的顶部数据向下与其子节点比较调整,直至符合大顶堆结构为止。

注:1.大顶堆向下调整时,母节点要与两个子节点中较大的一个交换 ,因此要比较一下。

2.这里下标的计算公式为:左孩子:child = (parent * 2) + 1

右孩子:child = (parent * 2) + 2

3.计算孩子下标时要避免越界,避免将母节点与不属于堆中的数据比较。

//删除数据
void Heap_pop(Heap* pphead)
{
    assert(pphead);
    assert(pphead->capacity > 0);      //防止堆为空
    //将顶部数据与尾部数据交换
    swap(&(pphead->head[0]),&( pphead->head[pphead->capacity-1]));
    pphead->capacity--;
    //向下调整
    adjust_down(pphead,0);
}

//向下调整
void Adjust_down(int* a, int size, int parent)
{
    assert(a);
    for (int child = parent * 2 + 1; child <= size; child = parent * 2 + 1)
    {
        //默认用左孩纸与母节点比较,如果右孩纸比左孩纸大且不越界则交换
        if (a[child] > a[child + 1] && child + 1 <= size)
            child = child + 1;
        //比较孩纸和母节点
        if (a[child] < a[parent])
        {
            int temp = a[child];
            a[child] = a[parent];
            a[parent] = temp;
        }
        //向下继续比较
        parent = child;
    }
}

④扩容 || 判空 || 取顶数据 || 销毁堆

//判断是否扩容
void Heap_realloc(Heap* pphead)
{
    assert(pphead);
    if (pphead->size == pphead->capacity)
    {
        Heaptype Newsize = (pphead->size == 0) ? 4 : (pphead->size * 2);
        Heaptype* Newhead = (Heaptype*)realloc(pphead->head,sizeof(Heaptype) * Newsize);
        if (Newhead == NULL)
        {
            perror("realloc");
            exit(-1);
        }
        pphead->head = Newhead;
        pphead->size = Newsize;
    }
}

//判断堆是否为空
bool Heap_Empty(Heap* pphead)
{
    if (pphead->capacity)
        return false;
    return true;
}
//取对顶数据
Heaptype Heap_top(Heap* pphead)
{
    return pphead->head[0];
}
//销毁堆
void Heap_Destory(Heap* pphead)
{
    assert(pphead);
    free(pphead->head);
    pphead->head = NULL;
    pphead->size = 0;
    pphead->capacity = 0;
}

以上就是C语言实现大顶堆的示例代码的详细内容,更多关于C语言大顶堆的资料请关注我们其它相关文章!

(0)

相关推荐

  • Java 堆排序实例(大顶堆、小顶堆)

    堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法.堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点. 堆排序的平均时间复杂度为Ο(nlogn) . 算法步骤: 1. 创建一个堆H[0..n-1] 2. 把堆首(最大值)和堆尾互换 3. 把堆的尺寸缩小1,并调用shift_down(0),目的是把新的数组顶端数据调整到相应位置 4. 重复步骤2,直到堆的尺寸为1 堆: 堆实际上是一棵完全二叉树,其任何一非叶节点满足性质:

  • 解读堆排序算法及用C++实现基于最大堆的堆排序示例

    1.堆排序定义 n个关键字序列Kl,K2,-,Kn称为堆,当且仅当该序列满足如下性质(简称为堆性质): (1) ki≤K2i且ki≤K2i+1 或(2)Ki≥K2i且ki≥K2i+1(1≤i≤   ) 若将此序列所存储的向量R[1..n]看做是一棵完全二叉树的存储结构,则堆实质上是满足如下性质的完全二叉树:树中任一非叶结点的关键字均不大于(或不小于)其左右孩子(若存在)结点的关键字. [例]关键字序列(10,15,56,25,30,70)和(70,56,30,25,15,10)分别满足堆性质(1

  • Java实现二叉堆、大顶堆和小顶堆

    目录 什么是二叉堆 什么是大顶堆.小顶堆 建堆 程序实现 建立大顶堆 逻辑过程 程序实现 建立小顶堆 逻辑过程 程序实现 从堆顶取数据并重构大小顶堆 什么是二叉堆 二叉堆就是完全二叉树,或者是靠近完全二叉树结构的二叉树.在二叉树建树时采取前序建树就是建立的完全二叉树.也就是二叉堆.所以二叉堆的建堆过程理论上讲和前序建树一样. 什么是大顶堆.小顶堆 二叉堆本质上是一棵近完全的二叉树,那么大顶堆和小顶堆必然也是满足这个结构要求的.在此之上,大顶堆要求对于一个节点来说,它的左右节点都比它小:小顶堆要求

  • 详解Java如何实现小顶堆和大顶堆

    大顶堆 每个结点的值都大于或等于其左右孩子结点的值 小顶堆 每个结点的值都小于或等于其左右孩子结点的值 对比图 实现代码 public class HeapNode{ private int size;//堆大小 private int[] heap;//保存堆数组 //初始化堆 public HeapNode(int n) { heap = new int[n]; size = 0; } //小顶堆建堆 public void minInsert(int key){ int i = this.

  • C语言实现基于最大堆和最小堆的堆排序算法示例

    堆定义 堆实际上是一棵完全二叉树,其任何一非叶节点满足性质: Key[i]<=key[2i+1]&&Key[i]<=key[2i+2](小顶堆)或者:Key[i]>=Key[2i+1]&&key>=key[2i+2](大顶堆) 即任何一非叶节点的关键字不大于或者不小于其左右孩子节点的关键字. 堆排序的思想 利用大顶堆(小顶堆)堆顶记录的是最大关键字(最小关键字)这一特性,使得每次从无序中选择最大记录(最小记录)变得简单. 最大堆:所有节点的子节点比其

  • C语言实现大顶堆的示例代码

    目录 堆的实现 1.堆结构 2.堆的种类 3.大顶堆代码实现 堆的实现 1.堆结构 逻辑结构上类似于 一棵 “树” 2.堆的种类 大顶堆结构: 一种特殊的树:其每个子节点均比母节点要小 小顶堆结构: 同理:其每个子节点均比母节点要大 结构图示: 3.大顶堆代码实现 这里实现堆 用循序表的方式 ①初始化: typedef int Heaptype; typedef struct Heap { Heaptype* head; int size; //记录堆总容量 int capacity; //记录

  • C++实现二叉树及堆的示例代码

    1 树 树是一种非线性数据结构,它是由n个有限结点组成的具有层次关系的集合.把它叫树是因为它是根朝上,叶子朝下的 来上图瞧瞧 1.1 树的相关名词 2 二叉树 2.1 二叉树的概念 一颗二叉树是结点的一个有限集合,该集合或者为空,或者是由一个根结点加上两棵分别称为左子树和右子树. 如图所示: 二叉树有以下特点: 1.每个二叉树最多有两颗子树,所以二叉树不存在度为2的结点. 2.二叉树的子树有左右之分,其子树的顺序不能颠倒. 2.2 二叉树的性质 1.若规定根结点的层数为第一层,则一颗非空二叉树的

  • Java语言实现二叉堆的打印代码分享

    二叉堆是一种特殊的堆,二叉堆是完全二元树(二叉树)或者是近似完全二元树(二叉树).二叉堆有两种:最大堆和最小堆.最大堆:父结点的键值总是大于或等于任何一个子节点的键值:最小堆:父结点的键值总是小于或等于任何一个子节点的键值. 打印二叉堆:利用层级关系 我这里是先将堆排序,然后在sort里执行了打印堆的方法printAsTree() public class MaxHeap<T extends Comparable<? super T>> { private T[] data; pr

  • C语言编程入门必背的示例代码整理大全

    目录 一.C语言必背代码前言 二.一部分C语言必背代码 一.C语言必背代码前言 对于c语言来说,要记得东西其实不多,基本就是几个常用语句加一些关键字而已.你所看到的那些几千甚至上万行的代码,都是用这些语句和关键词来重复编写的.只是他们逻辑功能不一样,那如何快速的上手C语言代码,建议多看多写,下面是小编整理的C语言必背代码. 二.一部分C语言必背代码 1.输出9*9成法口诀,共9行9列,i控制行,j控制列. #include "stdio.h" main() {int i,j,resul

  • C语言实现经典排序算法的示例代码

    目录 一.冒泡排序 1.原理 2.实现 3.算法分析 二.选择排序 1.原理 2.实现 3.算法分析 三.插入排序 1.原理 2.实现 3.算法分析 四.希尔排序 1.原理 2.实现 3.算法分析 总结 一.冒泡排序 1.原理 从数组的头开始不断比较相邻两个数的大小,不断将较大的数右移,一个循环后,最大数移至最后一位,无序数组规模减一.不断重复前面动作,知道数组完全有序. 2.实现 void swap(int* a, int* b) { int temp = *a; *a = *b; *b =

  • Go语言实现常用排序算法的示例代码

    目录 冒泡排序 快速排序 选择排序 插入排序 排序算法是在生活中随处可见,也是算法基础,因为其实现代码较短,应用较常见.所以在面试中经常会问到排序算法及其相关的问题,可以说是每个程序员都必须得掌握的了.为了方便大家学习,花了一天的时间用Go语言实现一下常用的算法且整理了一下,如有需要可以参考. 冒泡排序 思路:从前往后对相邻的两个元素依次进行比较,让较大的数往下沉,较小的网上冒,即每当两个相邻的元素比较后发现他们的排序要求相反时,就将它们互换. 时间复杂度:O(N^2) 空间复杂度:O(1) f

  • C语言手写集合List的示例代码

    目录 前沿 定义结构 创建List 扩容 创建数据节点 给集合添加值 删除集合内指定的值 删除集合内指定下标的值 打印集合 迭代器 查询指定元素的下标(第一个) 末尾查询指定元素下标(第一个) 判断数组是否有序 二分查询 修改集合指定元素的值 快速排序 集合去重 集合复制 集合合并 集合差集 集合补集 集合并集 集合交集 销毁集合 前沿 数组长度是固定的,那么在很多时候我们并不知道到底有多少数据需要存储,这时候我么就需要一个可变长度的数组来进行存储,在C语言中需要我们自己进行定义,我们称为集合

随机推荐