zoukankan      html  css  js  c++  java
  • 堆的学习笔记和堆的相关操作

     本博客的代码的思想和图片参考:好大学慕课浙江大学陈越老师、何钦铭老师的《数据结构》

    (Heap)

    1:引子

    1.1 需求

    在一个操作系统中,CPU如何处理进程。如果按照时间先后排序,那么

    对优先权较高的线程来说,就会出现问题。我们必须建立一种组织方式

    假设我们每次从"队列"里面取出的元素,是按照优先权大小,而不是如"队列"

    的时间顺序,如何进行组织?

    1.2比较我们之前使用过的几种数据结构

    1.2.1 数组

    插入:总是在最后,时间复杂度为O(1)

    删除:

    查找最大或者最小元素,时间复杂度为O(n)

    删除找到的最大最小元素,时间复杂度为O(n)

    1.2.2 链表

    插入:总是插入在链表的头部 时间复杂度O(1)

    删除:

    查找到最大或者最小元素,时间复杂度O(n)

    删除元素,时间复杂度O(1)

    1.2.3 有序数组

    插入:

    找到合适位置,时间复杂度O(n)或者O(log2 N)

    移动元素位置:O(n)

    删除:删去最后一个元素

    1.2.4 有序链表

    插入:找到合适的位置,时间复杂度O(n)

    删除:删除首元素或者尾元素,时间复杂度O(1)

    上面的数据结构至少都需要O(n)的时间复杂度,不是我们所需要的

    我们使用二叉搜索树看看怎么样。

    1.2.5 二叉搜索树

    插入:找到元素的位置 时间复制度O(log2 N)

    删除:最大最小元素在二叉搜索树的最左边或者最右边,时间复杂度O(log2 N)

    这么一看,感觉还是可以的,但是我们发现,我们每次删除的都是最大(最小)元素

    那么如果一直这么操作,这棵树会歪掉。我们得重新定义树的结构要求。

    2 引入堆的概念

    2.1 堆的特性

    结构性:使用数组来表示完全二叉树的特性

    有序性:任意节点的关键字是其子树所有节点的最大值(最小值)

    最大堆(MaxHeap),也称“大顶堆”:最大值

    最小堆(MinHeap),也称“小顶堆”:最小值

    2.2 堆的演示图

     

    堆的示意图:

     

    不是堆的示意图:

     

    2.3 堆的要求是

    从根节点到任意节点的路径上节点序列都有序

    2.4 堆的数据结构的定义

     1 typedef int elementType;
     2 
     3  
     4 
     5 typedef struct heapStruct *maxHeap;
     6 
     7 struct heapStruct{
     8 
     9     elementType *elementArray;/*定义存储元素的数组*/
    10 
    11     int size;/*堆当前元素的个数*/
    12 
    13     int capacity;/*堆的最大容量*/
    14 
    15  
    16 
    17 };

    2.5 堆的操作集合

    类型名称: 最大堆( MaxHeap
    数据对象集: 完全二叉树,每个结点的元素值不小于其子结点的元素值
    操作集:最大堆H Î MaxHeap,元素item Î ElementType,主要操作有:

    2.5.1 创建一个空的最大堆

    MaxHeap Create( int MaxSize );

    算法思想:

    a.分配一个内存空间给 heapStruct

    b.在分配 (MaxSize+1) * elementType 的数组空间给 elementArray

    c.设置 size=0

    d.设置capacity=MaxSize

    e.我们设置了MaxSize+1个元素,我们让元素的角标从1开始,那么在第0号角标,我们设置一个MaxValue作为哨兵。MaxValue要求大于所有的堆元素

    2.5.2判断最大堆H是否已满


    Boolean IsFull( MaxHeap H );

    算法思想:如果size==capacity,则堆满了

    2.5.3 将元素item插入最大堆H


    Insert( MaxHeap H, ElementType item );

    算法思想:

    不论什么元素,先把元素插入到数组的末尾,在和根元素进行比较,比根元素大就进行交换,否则不进行调整。调整以后,在比较,是否还是比根元素大,若还是大,在进行条,一直到比MaxValue小为止。下面使用图解来说明

     

    2.5.4 判断最大堆H是否为空

    Boolean IsEmpty( MaxHeap H )

    算法思想:如果size==0,表示堆为空

    2.5.5 删除堆中最大元素,并返回


    ElementType DeleteMax( MaxHeap H )

    算法思想:算法思想:先使用数组最末尾的元素替换第一个元素(根元素),然后判断当前根元素的左右孩子是否比根元素大,如果是,进行调整。一直这样进行递归,直到当前根元素比左右孩子都大,这样,就得到了堆。下面看演示图:

     

    2.5.6 建立一个堆

    需求:给你N个数据,如何在快速的建立一个堆

    方法1:我们可以按照堆插入算法,把这些元素,一个个的插入堆中。一个元素插入堆的时间复杂度为O(log2 N),N个元素插入堆中的时间复杂度为O(N * log2 N)

    方法2:我们依次把这些元素放入数组中(构建完全二叉树),然后从倒数第一个有孩子的节点的元素开始,按照删除元素的思路,对该节点和其孩子进行调整,使该节点和它对于的孩子变成一个堆。然后在往前推一个元素,在进行如此操作,就完成了快速建立一个堆。

    时间复杂度的计算:

    结点数 最多交换次数
    n/4 1
    n/8 2
    n/16 3
    ……
    n/2^k=1 log2n-1 (k-1)

    所有时间复杂度为N,比第一种方法要好得多。

    下面是具体的演示过程:

     

      1 #include<stdio.h>
      2 #include<stdlib.h>
      3 #define MAXDATA 65536
      4 
      5 typedef int elementType;
      6 
      7 typedef struct heapStruct *maxHeap;
      8 struct heapStruct{
      9     elementType *elementArray;/*定义存储元素的数组*/
     10     int size;/*堆当前元素的个数*/
     11     int capacity;/*堆的最大容量*/
     12 
     13 };
     14 
     15 /*
     16     create a heap appointed maxsize
     17     @param maxSize The max size of the max heap
     18     @return a initialized empty heap.
     19 */
     20 maxHeap createEmptyHeap(int maxSize){
     21     maxHeap heap = (maxHeap)malloc(sizeof(struct heapStruct));
     22     /*把数组元素空间分配出来*/
     23     heap->elementArray = (elementType *)malloc(sizeof((maxSize+1)*sizeof(elementType)));
     24     heap->size=0;
     25     heap->capacity = maxSize;
     26     /*define the max value as 哨兵, we will make update easy*/
     27     heap->elementArray[0]=MAXDATA;
     28     return heap;
     29 }
     30 
     31 /*
     32 Judge the heap whether is full.
     33 @param heap The heap need to judge
     34 @return 1 will be returned if the heap is full, otherwise will return 0
     35 */
     36 int isHeapFull(maxHeap heap){
     37     return (heap->size==heap->capacity);
     38 }
     39 
     40 /*
     41 Judge the heap whether is emppty.
     42 @param heap The heap need to judge
     43 @return 1 will be returned if the heap is empty, otherwise will return 0
     44 */
     45 int isHeapEmpty(maxHeap heap){
     46     return (heap->size==0);
     47 }
     48 
     49 /*insert element to heap,we will update it if necessary
     50 @param heap The heap exsit
     51 @param element The element need to insert
     52 */
     53 void insertHeap(maxHeap heap,elementType element){
     54     int i;
     55     if(isHeapFull(heap)){
     56         printf("the heap is full
    ");
     57         return;
     58     }
     59     i = ++heap->size;
     60     heap->elementArray[i]=element;
     61     for( ; heap->elementArray[i/2]<element;i=i/2){
     62         heap->elementArray[i]=heap->elementArray[i/2];
     63     }
     64     heap->elementArray[i]= element;
     65 }
     66 
     67 elementType deleteMax(maxHeap heap){
     68     int parent,child;
     69     elementType maxElement,temp;
     70     if(isHeapEmpty(heap)){
     71         printf("the heap has bean empty
    ");
     72         return;
     73     }
     74     /*取出最大元素*/
     75     maxElement = heap->elementArray[1];
     76     temp=heap->elementArray[heap->size--];
     77     for(parent=1;parent*2<heap->size;parent=child){
     78         child = parent*2;
     79         /*
     80         child!=heap->size:indicate the heap has a right child
     81         heap->elementArray[child]<heap->elementArray[child+1]:the value of right greater than the value of left
     82         the code of IF is to find the index of the bigger value of left child and right child
     83         */
     84         if((child!=heap->size)&& heap->elementArray[child]<heap->elementArray[child+1]){
     85             child++;/*get the right child index*/
     86         }
     87         if(temp>=heap->elementArray[child]){
     88             break;/*temp find a suitable station*/
     89         }else{
     90             /*move bigger element to parent station*/
     91             heap->elementArray[parent]=heap->elementArray[child];
     92         }
     93     }
     94 
     95     heap->elementArray[parent]=temp;
     96     return maxElement;
     97 }
     98 
     99 
    100 /*
    101 print the heap
    102 @param heap The heap nend to print to the controal
    103 */
    104 void toString(maxHeap heap){
    105     maxHeap p = heap;
    106     printf("toString:");
    107     int i=1;
    108     while(i<=p->size){
    109         printf("%d ",p->elementArray[i]);
    110         i++;
    111     }
    112     printf("
    ");
    113 }
    114 
    115 
    116 /*
    117     construct the max heap,the algorithem thought is same with delete method
    118     @param heap The binary tree who want to construct a max heap
    119     @param p The parent index of the tree
    120 */
    121 void percDown(maxHeap heap,int p){
    122     elementType temp=heap->elementArray[p];
    123     int parent,child;
    124     for(parent=p;parent*2<=heap->size;parent=child){
    125         child = parent *2;
    126         if((child!=heap->size) && heap->elementArray[child]<heap->elementArray[child+1]){
    127             child++;
    128         }
    129         if(temp>=heap->elementArray[child]){
    130             break;
    131         }else{
    132             heap->elementArray[parent]=heap->elementArray[child];
    133         }
    134     }
    135     heap->elementArray[parent]=temp;
    136 }
    137 
    138 /*
    139 make a binary tree to be a heap
    140 @param heap The binary tree need to transfer into heap
    141 */
    142 void buildMaxHeap(maxHeap heap){
    143     int i;
    144     /*
    145     maxHeap heap = createEmptyHeap(10);
    146     maxHeap heap = createEmptyHeap(10);
    147     printf("lala,%d
    ",length);
    148     for(i=1;i<=length;i++){
    149         heap->elementArray[++heap->size]=a[i-1];
    150     }
    151     */
    152     for(i=heap->size/2;i>0;i--){
    153         percDown(heap,i);
    154     }
    155 
    156 }
    157 
    158 /*
    159 void testBuildHeap(){
    160     int i;
    161     maxHeap heap2 = createEmptyHeap(10);
    162     for(i=1;i<=10;i++){
    163         heap2->elementArray[++heap2->size]=i;
    164     }
    165     toString(heap2);
    166     buildMaxHeap(heap2);
    167     toString(heap2);
    168 }
    169 */
    170 int main(){
    171 
    172     int i,arr[10];
    173     maxHeap heap = createEmptyHeap(30);
    174 
    175     for(i=1;i<=10;i++){
    176         heap->elementArray[++heap->size]=i;
    177     }
    178     printf("build a bianray tree,not heap	");
    179     toString(heap);
    180     buildMaxHeap(heap);
    181     printf("constructor a binary into a heap	");
    182     toString(heap);
    183     for(;i<=20;i++){
    184         insertHeap(heap,i);
    185     }
    186     printf("test insert method	");
    187     toString(heap);
    188     printf("delete max element%d
    ",deleteMax(heap));
    189     toString(heap);
    190     printf("delete max element%d
    ",deleteMax(heap));
    191     toString(heap);
    192     printf("delete max element%d
    ",deleteMax(heap));
    193     toString(heap);
    194     printf("delete max element%d
    ",deleteMax(heap));
    195     toString(heap);
    196     //testBuildHeap();
    197     printf("just test");
    198     return 0;
    199 }
    the operation of heap

    下面是结果演示:

  • 相关阅读:
    关于容器和里面元素的间距的排版技巧
    Grafana 通过api create&update dashboard
    .net(c#)生成xml并输出(api的设计)
    Ajax学习总结
    网站内容更新之伪原创七绝招
    并发和多线程(十九)ConcurrentHashMap源码解析(jdk1.8) Diamond
    分布式事务(一)分布式事务理论基础 Diamond
    分布式事务(二)事务基础ACID隔离级别MVCC Diamond
    并发和多线程(十八)CountDownLatch、Semaphore和CyclicBarrier源码解析 Diamond
    分布式事务(三)XA、2PC、3PC Diamond
  • 原文地址:https://www.cnblogs.com/yghjava/p/6733443.html
Copyright © 2011-2022 走看看