数据结构堆详解
来源:互联网 发布:什么英语听力软件好 编辑:程序博客网 时间:2024/06/05 03:15
数据结构中的堆一般值指的是二叉堆,通常大家说堆如果不是指的内存堆,那就是说的二叉堆,一下内容用堆直接代指二叉堆
堆具有两个性质:结构性和堆序性
结构性:堆是一颗完全二叉树,因为堆由完全二叉树组成所以堆很有规律,它可以用一个数组来表示而不需要使用指针。
对与数组中任一位置i上的元素,其左儿子在位置2*i上 右儿子在2*i + 1上。
堆序性:(这里以最小堆为例,既顶部为元素为最小值)是操作被快速执行的性质是堆序性 由于我们想要快速的找出最小元,因此最小元应该在根上。如果我们考虑任意子数也应该是一个堆,那么任意节点就应该小于它的所有后裔。这个逻辑这个就是堆序性。
一个最简化的堆最少要实现 插入和删除最小元素 insert 和 deleteMin。
堆的具体实现如下:
//// sort.c// test_sort////#include <stdio.h>#include <stdlib.h>#include <stdbool.h>#include <math.h>typedef int ElementType;#define kMinSentinelElement (-1024)typedef struct _priorityQueue{ int capacity; int size; ElementType *elements;}HeapStruct, *PriorityQueue;PriorityQueue initialize(int maxElementsCount);bool insert(PriorityQueue h, ElementType d);bool deleteMin(PriorityQueue h);void traverse(PriorityQueue h);ElementType findMin(PriorityQueue h);ElementType findTail( PriorityQueue h);void heapSort(int arr[], int length);PriorityQueue initialize(int maxElementsCount){ PriorityQueue priorityq = calloc(1, sizeof(HeapStruct)); //add one extra for sentinel sentinel ElementType *elements = calloc((maxElementsCount + 1), sizeof(ElementType)); priorityq->elements = elements; priorityq->capacity = maxElementsCount; priorityq->size = 0; priorityq->elements[0] = kMinSentinelElement; return priorityq;}bool insert(PriorityQueue h, ElementType d){ if (h->size + 1 > h->capacity) { printf("capacity is big\n"); return false; } int size = h->size; if (size == 0) { h->elements[1] = d; h->size++; return true; } if (size > 0){ //得到当前要插入的数据的位置 //和其父节点进行比较 判断是否需要交换 //一直判断到父节点的数据满足条件 //当前要插入的数据在数组中的位置 int insertPosition = size + 1; int fatherNodePosition = floor(insertPosition/2); if (h->elements[fatherNodePosition] < d) { h->elements[insertPosition] = d; h->size++; }else{ while (h->elements[fatherNodePosition] > d) { //将父节点的数据赋给当前插入的节点 h->elements[insertPosition] = h->elements[fatherNodePosition]; insertPosition = fatherNodePosition; fatherNodePosition = floor(fatherNodePosition/2); } //将当前要插入的数据放入其父节点 h->elements[insertPosition] = d; h->size++; } } return true; }bool deleteMinFunction1(PriorityQueue h){ //put the last element to top //compare top to (left and right //when top is small (left and right) stop //when top is big (left or right) put (left or right samll) to top //put tail to (left or right samll) go on //此方法在判断左右子节点时方法较为繁琐 ElementType tail = h->elements[h->size]; h->size--; for (int i = 1; i <= h->size; ) { int leftp = i*2; int rightp = i*2 + 1; if (leftp > h->size) { //the last position h->elements[i] = tail; return true; } if (rightp > h->size && leftp <= h->size) { //just one left immediate change if (tail > h->elements[leftp]) { h->elements[i] = h->elements[leftp]; h->elements[leftp] = tail; }else{ h->elements[i] = tail; } return true; } if (tail < h->elements[leftp] && tail < h->elements[rightp]) { h->elements[i] = tail; return true; }else { int position = h->elements[leftp] < h->elements[rightp] ? leftp : rightp; h->elements[i] = h->elements[position]; i = position; } } return false;}//对二叉堆按照(结构性和堆序性要求)进行调整void rebulid(PriorityQueue h, int topPosition){ //put the last element to top //compare top to (left and right //when top is small left and right stop //when top is big (left or right) put (left or right samll) to top //put tail to (left or right samll) go on ElementType top = h->elements[topPosition]; int lp = topPosition * 2; int rp = topPosition * 2 + 1; if (lp > h->size) { return; } if (rp > h->size || lp == h->size) { //only left ElementType l = h->elements[lp]; if (l < top) { //change h->elements[lp] = top; h->elements[topPosition] = l; } return; } ElementType l = h->elements[lp]; ElementType r = h->elements[rp]; if (top < l && top < r) { return; } int rlpsmall = l < r ? lp : rp; h->elements[topPosition] = h->elements[rlpsmall]; h->elements[rlpsmall] = top; rebulid(h, rlpsmall);}bool deleteMinByFunction2(PriorityQueue h){ //此方法采用递归一直向下过滤 ElementType tail = h->elements[h->size]; h->elements[1] = tail; h->size--; rebulid(h, 1); return true;}/* 此方法实现较为简洁 */bool deleteMin(PriorityQueue h){ /* 当删除一个最小元时,在根节点处产生了一个空穴,由于现在堆少了一个元素,因此堆 中最后一个元素X必须移动到该堆的某个位置,如果X可以被放到空穴中,那么deleteMin操作完成,不过这一般是不太可能的。因此我们将空穴的两个儿子中较小者 移到空穴,这样就把空穴向下推了一层,重复该步骤直到X可以被放入空穴中。 */ ElementType tail = h->elements[h->size]; h->size--; for (int i = 1; i <= h->size; ) { //find left and right min position int minPosition = 0; if ((2 * i + 1) <= h->size) { minPosition = h->elements[2 * i] < h->elements[2 * i + 1] ? (2 * i) : (2 * i + 1); }else if (2 * i <= h->size){ minPosition = 2 * i; }else{ //the last position no (left and right) h->elements[i] = tail; return true;//compare end } if (tail < h->elements[minPosition]) { h->elements[i] = tail; return true;//compare end }else{ h->elements[i] = h->elements[minPosition]; i = minPosition; } } return false;}//下滤void percolateDown( PriorityQueue h, int position){ if (position > h->size) { return; } ElementType top = h->elements[position]; int i = position; //find left and right min position int minPosition = 0; if ((2 * i + 1) <= h->size) { minPosition = h->elements[2 * i] < h->elements[2 * i + 1] ? (2 * i) : (2 * i + 1); }else if (2 * i <= h->size){ minPosition = 2 * i; }else{ //the last position no (left and right) return; } if (top > h->elements[minPosition]) { h->elements[i] = h->elements[minPosition]; h->elements[minPosition] = top; percolateDown(h, minPosition); }}ElementType findTail( PriorityQueue h){ int size = h->size; if (size <= h->capacity) { printf("the findTail is %d\n", h->elements[size]); return h->elements[size]; } return kMinSentinelElement;}ElementType findMin(PriorityQueue h){ if (h->size > 0) { return h->elements[1]; } return kMinSentinelElement;}//遍历void traverse(PriorityQueue h){ int size = h->size; for (int i = 0; (2*i) <= size; i++) { if (i != 0) { printf("the element is %d\n", h->elements[2*i]); } if (2*i+1 <= size) { printf("the element is %d\n", h->elements[2*i + 1]); } } printf("\n"); for (int i = 0; 2*i <= size; i++) { if (i != 0) { printf("the left element is %d\n", h->elements[2*i]); } } printf("\n"); for (int i = 0; (2*i+1) <= size; i++) { if (i != 0) { printf("the right element is %d\n", h->elements[2*i+1]); } } printf("\n");}void testInfoMessage(){ PriorityQueue priorityq = initialize(15); insert(priorityq, 1); traverse(priorityq); insert(priorityq, 2); insert(priorityq, 3); insert(priorityq, 4); insert(priorityq, 5); // insert(priorityq, 2);// insert(priorityq, 4);// insert(priorityq, 3);// insert(priorityq, 5); // insert(priorityq, 4);// insert(priorityq, 8);// insert(priorityq, 12);// insert(priorityq, 11); // insert(priorityq, 4);// insert(priorityq, 8);// insert(priorityq, 12);// insert(priorityq, 3);// insert(priorityq, 7);// insert(priorityq, 6);// insert(priorityq, 5);// insert(priorityq, 1);// insert(priorityq, 9); traverse(priorityq); deleteMinFunction1(priorityq); traverse(priorityq); findTail(priorityq); deleteMinFunction1(priorityq); traverse(priorityq); deleteMinFunction1(priorityq); traverse(priorityq); int arrNew[] = {49, 38, 65, 97, 26, 13, 27, 49, 55, 4};// int arrNew[] = {49, 38, 65, 97, 26, 13, 27, 55, 4}; heapSort(arrNew, sizeof(arrNew)/sizeof(int));}//堆排序void heapSort(int arr[], int length){ //根据数组创建堆 #if 0 - 逐个插入 PriorityQueue priorityq = initialize(length); for (int i = 0; i < length; i++) { insert(priorityq, arr[i]); } traverse(priorityq);#endif #if 1 - 逐渐向下过滤 PriorityQueue priorityq = initialize(length); for (int i = 0; i < length; i++) { priorityq->elements[i+1] = arr[i]; } priorityq->size = length; traverse(priorityq); for (int i = length / 2; i > 0; i--) { percolateDown(priorityq, i); } traverse(priorityq);#endif for (int i = 0; i < length; i++) { ElementType element = findMin(priorityq); arr[i] = element; //deleteMin(priorityq); deleteMinFunction1(priorityq);// deleteMinByFunction2(priorityq); } for (int i = 0; i < length; i++) { printf("the arr[%d] is %d\n", i, arr[i]); }}
阅读全文
0 0
- 数据结构堆详解
- 《数据结构与算法分析》二叉堆详解
- 数据结构:堆
- 数据结构-堆
- 堆数据结构
- 堆数据结构
- 数据结构:堆
- 数据结构-堆
- 数据结构-堆
- 数据结构 堆
- 数据结构--堆
- 数据结构:堆
- 数据结构:堆
- 数据结构--堆
- 堆数据结构
- 数据结构- 堆
- 数据结构:堆
- 【数据结构】堆
- MySQL中ddl_log.log初步认识
- 可能是第十好的Android 开源 日历 Calendar 仿小米
- spring boot 1.5+ 添加 redis
- MarkDown编辑器中缩进
- Android Studio 查看不到SDK源码解决办法
- 数据结构堆详解
- PHP实现组合C运算,从一个数组中取出m个数,有几种组合?有哪些组合?
- oracle user_source表
- Spark资源调度分配解密
- Django开发博客-(1)Django简介
- VMware Pro v12.5.6 官方版及激活密钥
- 从PowerDesigner概念设计模型(CDM)中的3种实体关系说起
- 杭电oj 1002 java 解决
- linux-csi-tools部署记录[镜像]