数据结构堆详解

来源:互联网 发布:什么英语听力软件好 编辑:程序博客网 时间: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]);    }}


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 健康证无法下载怎么办 健康证下载不了怎么办 北京办理健康证怎么办 北京的健康证怎么办 健康证丢了怎么办 健康证吃宵夜怎么办 合肥办健康证怎么办 个人办理健康证怎么办 身份证丢失怎么办健康证 个人怎么办武汉健康证 山海关古御壹号怎么办房本? 车玻璃被炮烧了怎么办 奔驰钥匙没电怎么办 婚内买的车离婚怎么办 离心风机噪音大怎么办 匹凸匹被st五牛怎么办 考不进去中学怎么办 教师体检来例假怎么办 老板拖欠农民工工资怎么办 公司破产拖欠员工工资怎么办 白玉蜗牛下蛋了怎么办 黄牛卖不出的票怎么办 鸡受风寒不产蛋怎么办 蛋鸡感冒不下蛋怎么办 牛肉煮老了怎么办 牛肉炖碎了怎么办 比值审敛法等于1怎么办 华为手机停止运行怎么办 易事通卡怎么办延期 三星手机照相机故障怎么办 凌晨一点到机场怎么办 凌晨3点醒来怎么办 凌晨四五点咳嗽怎么办 凌晨4点大便怎么办 熊猫小课付了费怎么办 华为手机系统升级后卡机怎么办 孕妇汗脚脚臭怎么办 巴基斯坦留学生丢失护照怎么办 vivox20耳机进水了怎么办 轴圆齿之间间隙大怎么办 浩辰cad2017保存不了怎么办