当前位置: 首页 > news >正文

数据结构之二叉树——堆 详解(含代码实现)

1.堆

如果有一个关键码的集合 K = { , , , ,},把它的所有元素按完全二叉树的顺序存储方式存储
在一个一维数组中,则称为小堆( 或大堆 ) 。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。

堆的性质:

堆中某个节点的值总是不大于或不小于其父节点的值;
堆总是一棵完全二叉树。

创建堆

向上调整建堆

向下调整建堆

堆的插入

先插入一个10到数组的尾上,再进行向上调整算法,直到满足堆

向上调整算法

数组一个个循环插入时边插入边成堆,当插入新的元素时向上调整成新的堆

使用向上调整算法,每次孩子与父亲相比较,当孩子大于或小于父亲时进行交换,改变孩子的下标,再次进行判断然后交换,知道孩子的下标为0

堆的删除

向下调整算法

给出一个数组,逻辑上看做一颗完全二叉树。通过从根节点开始的向下调整算法可以把它调整成一个小堆。向下调整算法有一个前提:左右子树必须是一个堆,才能调整。

当已经成大堆或者小堆后想删元素,最好的办法是把堆的第一个元素与最后一个进行交换,当交换完成,堆中最大或最小的元素就到了最后一个结点,减小下标进行删除,此时堆顶的左右子树为大堆或者小堆,用向下调整算法,将父亲与孩子循环比较大小进行交换,形成新的堆,再次把堆顶元素与最后一个元素交换,使用向下调整成新的堆,反复进行即可删除堆

堆的排序   升序  降序

向上调整建堆,堆顶元素与最后一个元素交换,再次向上或向下调整,得到升序或降序

向上调整建堆

向下调整建堆

向上向下调整对比

向下调整时间复杂度分析

向上调整时间复杂度分析

总结

堆排序时间复杂度

堆的代码实现

//头文件
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>typedef int HPDataType;
typedef struct Heap
{HPDataType* a;int size;int capacity;
}Heap;
//初始化
void HeapInit(Heap* hp);
// 堆的销毁
void HeapDestory(Heap* hp);
// 堆的插入
void HeapPush(Heap* hp, HPDataType x);
// 堆的删除
void HeapPop(Heap* hp);
// 取堆顶的数据
HPDataType HeapTop(Heap* hp);
// 堆的数据个数
int HeapSize(Heap* hp);
// 堆的判空
bool HeapEmpty(Heap* hp);
//向上调整
void Adjustup(HPDataType* a, int child);
//向下调整
void Adjustdown(HPDataType* a, int parent);
void swap(Heap* hp, int child, int parent);
//函数实现
#define _CRT_SECURE_NO_WARNINGS  1
#pragma warning(disable:6031)
#include"heap.h"
//初始化
void HeapInit(Heap* hp)
{assert(hp);hp->a = NULL;hp->size = hp->capacity = 0;
}
void swap( int *p1, int *p2)
{int tmp = *p1;*p1 = *p2;*p2 = tmp;
}
bool HeapEmpty(Heap* hp)
{assert(hp);return hp->size == 0;
}// 堆的销毁
void HeapDestory(Heap* hp)
{free(hp->a);hp->a = NULL;free(hp);hp = NULL;
}
//向上调整
void Adjustup(HPDataType* a, int child)
{assert(a);int parent = (child - 1) / 2;while (child > 0){if (a[child] < a[parent]){swap(&a[child], &a[parent]);child = parent;parent = (child - 1) / 2;}else {break;}}
}
// 堆的插入
void HeapPush(Heap* hp, HPDataType x)
{assert(hp);if (hp->capacity == hp->size)//1未开劈空间 2.已满没有空间{int newcapacity = hp->capacity == 0 ? 4 : hp->capacity * 2;Heap* tmp = (Heap*)realloc(hp->a, sizeof(HPDataType)* newcapacity);if (tmp == NULL){perror("realloc fail");return NULL;}hp->a = tmp;hp->capacity = newcapacity;}//空间够  hp->a[hp->size] = x;hp->size++;//放进之后 向上调整形成新的堆Adjustup(hp->a, hp->size - 1);
}
//向xia调整
void Adjustdown(HPDataType* a,int n, int parent)
{assert(a);int child = parent * 2 + 1;while (child < n){     //右孩子小于huo大于左孩子if (child + 1 < n && a[child + 1] < a[child]){child++;}if (a[parent] > a[child]){swap(&a[child], &a[parent]);parent = child;child= parent * 2 + 1;}else {break;}}
}
// 堆的删除
void HeapPop(Heap* hp)
{assert(hp);assert(!HeapEmpty(hp));//把第一个元素与最后一个交换,向下调整swap( &hp->a[0],&hp->a[hp->size-1]);hp->size--;Adjustdown(hp->a, hp->size, 0);}
//取堆顶数据
HPDataType HeapTop(Heap* hp)
{assert(hp);assert(!HeapEmpty(hp));return hp->a[0];
}
// 堆的数据个数
int HeapSize(Heap* hp)
{assert(hp);return hp->size;
}
#define _CRT_SECURE_NO_WARNINGS  1
#pragma warning(disable:6031)
#include"heap.h"
void test()
{Heap hp;HeapInit(&hp);int a[] = { 60,50,6,8,14,7,3 };for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++){HeapPush(&hp, a[i]);}HeapDestroy(&hp);
}
void HeapSort(int* a, int n)
{// 升序 -- 建大堆// 降序 -- 建小堆Heap hp;HeapInit(&hp);//建堆--向上调整建堆/*for (int i = 1; i < n; i++){AdjustUp(a, i);}*/// 建堆--向下调整建堆 --O(N)for (int i = (n - 1 - 1) / 2; i >= 0; --i){AdjustDown(a, n, i);}int end = n - 1;while (end > 0){Swap(&a[0], &a[end]);// 再调整,选出次小的数AdjustDown(a, end, 0);--end;}
}
int main()
{test();return 0;
}

http://www.lryc.cn/news/477989.html

相关文章:

  • 推荐一款面向增材制造的高效设计平台:nTopology
  • SQL,力扣题目1767,寻找没有被执行的任务对【递归】
  • JavaScript数据类型- Symbol 详解
  • WordPress网站添加嵌入B站视频,自适应屏幕大小,取消自动播放
  • 11.6 校内模拟赛总结
  • Redis常用的五大数据类型(列表List,集合set)
  • Ubuntu 20.04 部署向量数据库 Milvus + Attu
  • 实现数传数据转网口(以太网)和遥控器SBUS信号转串口的功能
  • APP 后台广告位配置的关键要素与策略
  • 分布式数据库概述
  • 用通义灵码帮助实现校验bpmn.js当前画布上只能有一个开始节点的功能
  • OKHTTP断点续传
  • 软件测试学习笔记丨Flask操作数据库-ORM
  • ABAP 开发的那些小技巧
  • 电科金仓(人大金仓)更新授权文件(致命错误: XX000: License file expired.)
  • 玩转「HF/魔搭/魔乐」平台
  • 鸿蒙系统的优势 开发 环境搭建 开发小示例
  • python批量合并excel文件
  • AWS S3 JavaScript SDK(v3)常用操作
  • 数据结构——图的基本操作
  • 掌握全球速递:在表格中高效利用国际快递公式查询快递
  • 【MySQL系列】字符集设置
  • Vue2进阶之Vue3高级用法
  • 基于微信的追星小程序+ssm(lw+演示+源码+运行)
  • 【51单片机】串口通信原理 + 使用
  • 优选算法第五讲:位运算模块
  • 【07】Maven项目多环境打包配置
  • 嵌入式Linux入门具备:C语言基础与基本驱动学习(2):Linux GIibc IO基础
  • 【微服务】Docker 容器化
  • [前端] 为网站侧边栏添加搜索引擎模块