基本数据结构之堆
2015-07-13 21:18
513 查看
堆的定义
堆是一个完全二叉树或者近似的完全二叉树
每个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆)。
堆的存储
一般都用数组来表示堆,i结点的父结点下标就为(i – 1) / 2。它的左右子结点下标分别为2 * i + 1和2 * i + 2
堆的特点
插入元素和弹出堆顶元素的时间复杂度lg(n)
判断序列是不是堆
根据性质判断
比如输入序列15,30,22,93,52,71,89,15是根节点,可以看出满足性质,这是一个小根堆
堆是一个完全二叉树或者近似的完全二叉树
堆的性质
父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值。每个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆)。
堆的存储
一般都用数组来表示堆,i结点的父结点下标就为(i – 1) / 2。它的左右子结点下标分别为2 * i + 1和2 * i + 2
堆的特点
插入元素和弹出堆顶元素的时间复杂度lg(n)
判断序列是不是堆
根据性质判断
比如输入序列15,30,22,93,52,71,89,15是根节点,可以看出满足性质,这是一个小根堆
15 30 22 93 52 71 89
堆的C语言实现
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h> //c++ 中的priority_queue就是一个堆 typedef int heap_elem; //堆的数据类型 /** * @author 韦轩 * @time 2015/07/13 * @brief 堆的基本结构 * */ typedef struct heap { int size; //实际元素个数 int capacity;//堆的容量 heap_elem* elements;//堆的存储数组 int(*cmp)(const heap_elem*, const heap_elem*); //元素的比较函数 }heap; /** * @author 韦轩 * @time 2015/07/13 * @brief 创建一个堆 * @param capacity 容量 * @param cmp,小于返回-1,等于返回0,大于返回1,反过来是大根堆 * @return 成功返回堆对象的指针,否则为nullptr * */ heap* heap_create(const int capacity, int(*cmp)(const heap_elem*, const heap_elem*)) { heap* myheap = (heap*)malloc(sizeof(heap)); myheap->size = 0; myheap->capacity = capacity; myheap->cmp = cmp; myheap->elements = (heap_elem*)malloc(capacity*sizeof(heap_elem)); return myheap; } /** * @author 韦轩 * @time 2015/07/13 * @brief 销毁堆 * @param * @return 无 * */ void heap_destory(heap* myheap) { free(myheap->elements); free(myheap); } /** * @author 韦轩 * @time 2015/07/13 * @brief 判断堆是否为空 * @param * @return 返回true 是空,否则false * */ bool heap_empty(const heap* myheap) { return myheap->size == 0; } /** * @author 韦轩 * @time 2015/07/13 * @brief 堆的元素的个数 * @param * @return 返回元素的个数 * */ int heap_size(const heap* myheap) { return myheap->size; } /** * @author 韦轩 * @time 2015/07/13 * @brief 获取堆顶元素 * @param * @return 返回堆顶元素 * */ heap_elem heap_top(const heap* myheap) { return myheap->elements[0]; } /** * @author 韦轩 * @time 2015/07/13 * @brief 小根堆的自上而下的筛选算法 * @param start 开始的结点 * @return * */ void heap_sift_down(const heap* myheap, const int start) { int i = start; int j; const heap_elem temp = myheap->elements[start]; for (j = 2 * i + 1; j < myheap->size; j = 2 * j + 1) { if (j < myheap->size - 1 && myheap->cmp(&(myheap->elements[j]), &(myheap->elements[j + 1]))>0) { j++;//j指向两子女中的较小者 } if (myheap->cmp(&temp, &(myheap->elements[j]))<=0) { break; } else { myheap->elements[i] = myheap->elements[j]; i = j; } } myheap->elements[i] = temp; } /** * @author 韦轩 * @time 2015/07/13 * @brief 小根堆自下而上的筛选算法 * @param start 起始位置 * @return * */ void heap_sift_up(const heap* myheap, const int start) { int j = start; int i = (j - 1) / 2; const heap_elem temp = myheap->elements[start]; while (j > 0) { if (myheap->cmp(&(myheap->elements[i]), &temp) <= 0) { break; } else { myheap->elements[j] = myheap->elements[i]; j = i; i = (i - 1) / 2; } } myheap->elements[j] = temp; } /** * @author 韦轩 * @time 2015/07/13 * @brief 添加元素 * @param * @return * */ void heap_push(heap* myheap, const heap_elem x) { //堆已满,重新分配内存 if (myheap->size == myheap->capacity) { heap_elem* temp =(heap_elem*)realloc(myheap->elements, myheap->capacity * 2 * sizeof(heap_elem)); myheap->elements = temp; myheap->capacity *= 2; } myheap->elements[myheap->size] = x; myheap->size++; heap_sift_up(myheap, myheap->size - 1); } /** * @author 韦轩 * @time 2015/07/13 * @brief 弹出栈顶元素 * @param * @return * */ void heap_pop(heap* myheap) { myheap->elements[0] = myheap->elements[myheap->size - 1]; myheap->size--; heap_sift_down(myheap, 0); } /** * @author 韦轩 * @time 2015/07/13 * @brief 基本数据类型的比较 * @param * @return * */ int cmp(const int* data1, const int* data2) { const int ret = *data1 - *data2; if (ret < 0) return -1; else if (ret > 0) return 1; else return 0; } /** * @author 韦轩 * @time 2015/07/13 * @brief 打印堆,默认是int * */ void heap_print(const heap* myheap) { if (myheap == NULL) return; for (int i = 0; i < myheap->size; i++) { printf_s("%d\t", myheap->elements[i]); } } int main() { heap* myheap = heap_create(6, cmp); heap_push(myheap, 10); heap_push(myheap, 3); heap_push(myheap, 2); heap_push(myheap, 5); heap_push(myheap, 1); puts("初始...\n"); heap_print(myheap); puts("插入100,20...\n"); heap_push(myheap, 100); heap_push(myheap,20); heap_print(myheap); puts("删除堆顶元素...\n"); heap_pop(myheap); heap_print(myheap); heap_destory(myheap); return 0; }
相关文章推荐
- 基本数据结构之二叉树
- PAT 数据结构 08-排序3. Talent and Virtue (25)
- PAT 数据结构 07-排序2. Insert or Merge (25)
- 【数据结构】深度优先搜索BFS和广度优先搜索DFS
- 数据结构与算法设计--顺时针打印矩阵
- PAT 数据结构 07-排序1. 排序(25) 8种排序的比较
- java数据结构和算法------二叉树基本操作
- [数据结构]RMQ算法
- session 原理 数据结构
- 数据结构:树结构笔试题目
- 数据结构之栈
- 数据结构与算法——插入类排序(直接插入排序,希尔排序)
- PAT 数据结构 01-复杂度2. Maximum Subsequence Sum (25)
- PAT 数据结构 01-复杂度1. 最大子列和问题(20)
- PAT 数据结构 02-线性结构1. Reversing Linked List (25)
- PAT 数据结构 02-线性结构2. 一元多项式求导 (25)
- PAT 数据结构 02-线性结构3. 求前缀表达式的值(25)
- PAT 数据结构 02-线性结构4. Pop Sequence (25)
- PAT 数据结构 03-树3. Tree Traversals Again (25)
- PAT 数据结构 03-树2. List Leaves (25)