【数据结构-I】顺序结构存储二叉数堆
2019-05-29 21:50
134 查看
[code]时间啊,等等我!
堆的概念及结构
如果有一个关键码的集合K = {k0,k1, k2,…,kn-1},把它的所有元素按完全二叉树的顺序存储方式存储 在一个一维数组中,
并满足:Ki <= K2i+1 且 Ki<= K2i+2 (Ki >= K2i+1 且 Ki >= K2i+2) i = 0,1,2…,则称为 小堆(或大堆)。将根节点最大的堆叫做最大堆
或大根堆,根节点最小的堆叫做最小堆或小根堆。
堆的性质
- 堆中某个节点的值总是不大于或不小于其父节点的值;
- 堆总是一棵完全二叉树。
堆的实现
- 堆向上调整算法
- 堆向下调整算法
堆的代码实现
头文件Heap.h:
[code]#pragma once typedef int HPDataType; typedef int(*PCOM)(HPDataType, HPDataType); int Less(HPDataType left, HPDataType right); int Greater(HPDataType left, HPDataType right); typedef struct Heap { HPDataType* _array; int _capacity; int _size; PCOM Compare; }Heap; //用数组初始化堆 void InitHeap(Heap* hp, HPDataType* array, int size, PCOM compare); //初始化一个空堆 void InitEmptyHeap(Heap* hp, int capacity, PCOM compare); //在堆中插入值为data的元素 void InsertHeap(Heap* hp, HPDataType data); //删除堆顶元素 void EraseHeap(Heap* hp); //获取堆中有效元素的个数 int HeapSize(Heap* hp); //检测堆是否为空 int HeapEmpty(Heap* hp); //获取堆顶元素 HPDataType HeapTop(Heap* hp); //销毁堆 void DestroyHeap(Heap* hp); void TestHeap(); void HeapSort(int* array, int size);
源文件Heap.c:
[code]#include "Heap.h" #include <assert.h> #include <malloc.h> #include <stdio.h> void Swap(HPDataType* pLeft, HPDataType* pRight) { HPDataType temp = *pLeft; *pLeft = *pRight; *pRight = temp; } void AdjustDown(HPDataType* array, int size, int parent, PCOM Compare) { // 默认让child标记parent的左孩子,因为:完全二叉树某个节点如果只有一个孩子,该孩子一定是其双亲的左孩子 int child = parent * 2 + 1; while (child < size) { // 找双亲孩子中较小的孩子 if (child + 1 < size && Compare(array[child + 1], array[child])) { child += 1; } if (Compare(array[child], array[parent])) { Swap(&array[child], &array[parent]); parent = child; child = parent * 2 + 1; } else return; } } void AdjustUP(HPDataType* array, int size, int child, PCOM Compare) { int parent = (child - 1) / 2; while (child) { if (Compare(array[child], array[parent])) { Swap(&array[child], &array[parent]); child = parent; parent = (child - 1) / 2; } else return; } } void CheckCapacity(Heap* hp) { assert(hp); if (hp->_size == hp->_capacity) { int newCapacity = hp->_capacity * 2; // 申请新空间 HPDataType* pTemp = (HPDataType*)malloc(sizeof(HPDataType)*newCapacity); if (NULL == pTemp) { assert(0); return; } // 拷贝元素 for (int i = 0; i < hp->_size; ++i) pTemp[i] = hp->_array[i]; // 释放旧空间 free(hp->_array); hp->_array = pTemp; hp->_capacity = newCapacity; } } int Less(HPDataType left, HPDataType right) { return left < right; } int Greater(HPDataType left, HPDataType right) { return left > right; } void InitHeap(Heap* hp, HPDataType* array, int size, PCOM compare) { assert(hp); hp->_array = (HPDataType*)malloc(sizeof(HPDataType)*size); if (NULL == hp->_array) { assert(0); return; } hp->_capacity = size; for (int i = 0; i < size; ++i) hp->_array[i] = array[i]; hp->_size = size; hp->Compare = compare; // 将该完全二叉树调整让其满足堆的性质 // 找完全二叉数中倒数第一个非叶子节点 int root = ((size - 2) >> 1); for (; root >= 0; --root) AdjustDown(hp->_array, size, root, hp->Compare); } void InitEmptyHeap(Heap* hp, int capacity, PCOM compare) { assert(hp); hp->_array = (HPDataType*)malloc(sizeof(HPDataType)*capacity); if (NULL == hp->_array) { assert(0); return; } hp->_capacity = capacity; hp->_size = 0; hp->Compare = compare; } void InsertHeap(Heap* hp, HPDataType data) { CheckCapacity(hp); hp->_array[hp->_size] = data; hp->_size++; AdjustUP(hp->_array, hp->_size, hp->_size - 1, hp->Compare); } void EraseHeap(Heap* hp) { if (HeapEmpty(hp)) return; Swap(&hp->_array[0], &hp->_array[hp->_size - 1]); hp->_size -= 1; AdjustDown(hp->_array, hp->_size, 0, hp->Compare); } int HeapSize(Heap* hp) { assert(hp); return hp->_size; } int HeapEmpty(Heap* hp) { assert(hp); return 0 == hp->_size; } HPDataType HeapTop(Heap* hp) { assert(hp); return hp->_array[0]; } void DestroyHeap(Heap* hp) { assert(hp); if (hp->_array) { free(hp->_array); hp->_capacity = 0; hp->_size = 0; } } void TestHeap1() { Heap hp; int array[] = { 2, 3, 8, 0, 9, 1, 7, 4, 6, 5 }; InitHeap(&hp, array, sizeof(array) / sizeof(array[0]), Less); printf("Size=%d\n", HeapSize(&hp)); printf("堆顶:%d\n", HeapTop(&hp)); EraseHeap(&hp); printf("删除堆顶元素成功!\n"); printf("Size=%d\n", HeapSize(&hp)); printf("堆顶:%d\n", HeapTop(&hp)); InsertHeap(&hp, 0); printf("插入堆顶元素成功!\n"); printf("Size=%d\n", HeapSize(&hp)); printf("堆顶:%d\n", HeapTop(&hp));; } void TestHeap2() { Heap hp; InitEmptyHeap(&hp, 10, Greater); int array[] = { 2, 3, 8, 0, 9, 1, 7, 4, 6, 5 }; for (int i = 0; i < 10; ++i) InsertHeap(&hp, array[i]); printf("Size=%d\n", HeapSize(&hp)); printf("堆顶:%d\n", HeapTop(&hp)); DestroyHeap(&hp); } void HeapAdjust(int* array, int size, int parent) { int child = parent * 2 + 1; while (child < size) { // 找左右孩子中较大的孩子 if (child + 1 < size && array[child + 1] > array[child]) child += 1; if (array[child] > array[parent]) { Swap(&array[child], &array[parent]); parent = child; child = parent * 2 + 1; } else { return; } } } void HeapSort(int* array, int size) { // 1. 建堆---大堆,小堆? // 找倒数第一个非叶子节点 int root = ((size - 2) >> 1); for (; root >= 0; --root) HeapAdjust(array, size, root); // 2. 排序: 删除方式 int end = size - 1; while (end) { Swap(&array[0], &array[end]); HeapAdjust(array, end, 0); end--; } } void TestHeap() { TestHeap1(); TestHeap2(); int array[] = { 2, 3, 8, 0, 9, 1, 7, 4, 6, 5 }; HeapSort(array, sizeof(array) / sizeof(array[0])); }
测试代码test.c:
[code]#include "Heap.h" int main(){ TestHeap(); system("pause"); return 0; }
~bye~
相关文章推荐
- 数据结构--数组和广义表--以行逻辑链接的顺序表为存储结构的矩阵的基本运算(求矩阵乘积)
- C语言数据结构-3.栈的顺序及链式存储结构
- 基于完全二叉树木形成的二叉树顺序存储-数据结构(13)
- NOJ-建立二叉树的二叉链表存储结构-西工大数据结构
- 【数据结构---24】顺序结构存储二叉树堆
- [数据结构]四种数据存储结构---顺序存储 链接存储 索引存储 散列存储
- 10-0-顺序表存储结构-内部排序-第10章-《数据结构》课本源码-严蔚敏吴伟民版
- 数据结构第六章-二叉树顺序存储变链式存储
- 数据结构_线性表_顺序/链式存储优缺点比较
- 队列的顺序存储和链式表示方法-数据结构学习笔记2.3
- 【数据结构】算法3.1-3.2 栈的顺序存储表示
- 进击的数据结构一之线性表的顺序结构
- 数据结构:线性表的顺序存储--Java实现
- 数据结构-栈的顺序存储
- 数据结构之线性表——栈的顺序存储
- 数据结构之线性表——链表的顺序存储(数组描述)
- SD--关于定价过程中的存储顺序的参考结构和参考字段的使用代码跟踪
- 4-2-串的堆存储结构-串-第4章-《数据结构》课本源码-严蔚敏吴伟民版
- 数据结构 树的链式存储(二叉表示法)
- 【数据结构】顺序线性表的构造和存储数据