最小堆的插入、删除和创建的C语言实现
来源:互联网 发布:足球数据直播 编辑:程序博客网 时间:2024/06/05 11:21
堆是一种特殊的“队列”,它取出元素的顺序是依照元素的优先级大小,而不是元素进入队列的先后顺序。堆具有两个特性,1.结构性:它是能用数组表示的完全二叉树。2.堆序性:任一结点的关键字是其子树所有结点的最大值(最大堆)或最小值(最小堆),即任意子树也应该是个堆。
根据最小堆的结构特性,本文使用含有哨兵元素的数组实现了最小堆的创建、插入和删除。
数据类型定义和函数声明
#include<stdio.h>#include<stdlib.h>#define MinData -100//哨兵元素的值typedef struct HeapStruct{int *p;int size;int capacity;} *MinHeap;MinHeap Init_MinHeap(int MaxSize);int IsFull(MinHeap H);int IsEmpty(MinHeap H);void Insert(MinHeap H, int data);int Delete(MinHeap H);void BuildMinHeap(MinHeap H, int N);void PrintValue(MinHeap H);
程序中用到的功能函数
int IsFull(MinHeap H){return (H->size == H->capacity) ? 1 : 0;}int IsEmpty(MinHeap H){return (H->size == 0) ? 1 : 0;}void PrintValue(MinHeap H){int i;printf("最小堆中的元素依次为:");for (i = 1; i <= H->size; i++)printf("%d ", H->p[i]);printf("\n");}
最小堆的初始化
该函数给最小堆分配了内存空间并完成初始化操作,此时最小堆中元素为空。
MinHeap Init_MinHeap(int MaxSize){MinHeap H = (MinHeap)malloc(sizeof(HeapStruct));H->p = (int*)malloc((MaxSize + 1) * sizeof(int));H->p[0] = MinData;H->size = 0;H->capacity = MaxSize;return H;}
在最小堆中插入元素
插入元素的关键是把要插入的元素放在最小堆的合适位置中。所谓合适即不破坏最小堆的结构性和堆序性。
为了将一个元素data插入到堆中,在遵守堆的结构性特点(完全二叉树)基础上,在下一个空闲位置创建一个空穴。如果元素data可以放在该空穴中而并不破坏堆的序,则完成插入。否则,把空穴的父节点上的元素移入该空穴中,这样,空穴就朝着根的方向上移动一层。继续该过程知道元素data能放入空穴中。因为空穴在逐渐往树的上方移动,所以把这种策略成为“上滤”。
void Insert(MinHeap H, int data){int i;if (IsFull(H)){printf("最小堆已满,无法插入元素");return;}for (i = ++H->size; data < H->p[i / 2]; i /= 2)H->p[i] = H->p[i / 2];H->p[i] = data;}
删除最小堆中的最小元素
删除元素的关键是把堆中最后一个元素移动到最小堆中的合适位置。所谓合适即不破坏最小堆的结构性和堆序性。
删除元素以类似于插入的方式处理。找到最小元很容易(第一个元素),困难的部分是删除后的调整。当删除一个最小元时,在根节点处产生一个空穴。由于现在堆里少了一个元素,因为堆中最后一个元素lastvalue必须移动到该堆的某个地方。通常我们将空穴的两个儿子中较小者移入空穴,这样就把空穴向下退了一层。重复该步骤知道lastvalue可以放在空穴中。通常把这种策略成为“下滤”。
int Delete(MinHeap H){int minvalue , lastvalue, child, parent;if (IsEmpty(H)){printf("最小堆已满,无法删除元素");return -999;}minvalue = H->p[1];lastvalue = H->p[H->size--];for (parent = 1; 2 * parent <= H->size; parent = child){child = 2 * parent;/*默认左结点的元素值更小*/if (child != H->size && H->p[child + 1] < H->p[child])/*若右节点的元素值更小,则调整child*/child++;if (lastvalue < H->p[child])break;elseH->p[parent] = H->p[child];}H->p[parent] = lastvalue;return minvalue;}
创建最小堆
在创建最小堆时,可以 : 通过插入操作Insert函数,将N 个元素一个个相继插入到一个初始为空的堆中去 ,但其时间代价最大为O(NlogN)。
也可以在线性复杂度下建立最小堆,基本步骤为:1. 将N个元素按输入顺序存入,先满足完全二叉树的结构特性。2.调整各节点位置,以满足最大堆的堆序性。这样创建最小堆时的时间代价为O(N)。在调整节点位置时,只需对从第N/2个节点到第一个节点依次应用“下滤”策略即可,其实也就是进行了N/2次的近似删除操作。
void BuildMinHeap(MinHeap H, int N){int i, num, parent, child, root, lastvalue;if (N > H->capacity){printf("要创建的元素个数超过堆的最大容量,创建失败");return;}for (i = 1; i <= N; i++){printf("请输入要插入的元素值:");scanf_s("%d", &num);H->p[i] = num;}H->size = N;root = N / 2;/*从第N/2个结点到第1个结点依次进行下滤 近似N/2次删除操作*/while (root){lastvalue = H->p[root];for (parent = root; 2 * parent <= H->size; parent = child){child = 2 * parent;/*默认左结点的元素值更小*/if (child != H->size && H->p[child + 1] < H->p[child])/*右结点元素值更小*/child++;if (lastvalue < H->p[child])break;elseH->p[parent] = H->p[child];}H->p[parent] = lastvalue;--root;}}
主程序
测试序列:150 80 40 30 10 70 110 100 20 90 60 50 120 140 130
正确结果为:10 20 40 30 60 50 110 100 150 90 80 70 120 140 130
void main(){int num;MinHeap H;H = Init_MinHeap(100);BuildMinHeap(H, 15);PrintValue(H);printf("请输入你要插入的数据:");scanf_s("%d", &num);Insert(H, num);PrintValue(H);printf("请输入你要插入的数据:");scanf_s("%d", &num);Insert(H, num);PrintValue(H);num = Delete(H);printf("删除的元素为:%d\n", num);PrintValue(H);}
- 最小堆的插入、删除和创建的C语言实现
- 最小堆的调整、插入和删除
- 最大堆的创建、插入和删除
- 堆的创建 插入和删除
- C语言实现单链表的创建、插入、删除
- C语言实现二叉搜索树的创建、插入、删除和查找
- 堆插入和删除的简单实现
- 实现最大堆的插入和删除!
- 堆的插入删除实现和优化
- 堆的创建、插入、删除
- 堆的创建,插入,删除
- 堆的创建,插入,删除
- c语言单链表的创建、插入、删除
- 面试题95:最小堆的调整、插入和删除
- C语言实现链表节点的插入和删除
- C语言实现链表节点的插入和删除
- 单链表插入和删除结点c语言的实现
- C语言实现线性表的插入和删除操作
- [模板]
- C++时间戳time_t和时间结构体tm
- 大整数乘积:算法思想
- Swift Source Code
- 至今为止最易懂的BM算法精讲
- 最小堆的插入、删除和创建的C语言实现
- [模板]
- Hibernate 5.2.12 二级缓存配置及案例
- LeetCode String to Integer (atoi)
- 入门训练 序列求和
- 调用方法
- SVN分支使用使用说明
- 消息队列 RabbitMQ 与 Spring 整合使用
- Spring Boot CommandLineRunner和ApplicationRunner