堆(二叉堆)

作者: 修夏之夏i | 来源:发表于2018-08-29 16:40 被阅读13次
    堆:关键码的集合。

    小堆(大堆):任一结点的关键码均小于等于(大于等于)它的的左右孩子的关键码,位于堆顶结点的关键码最小(最大),从根结点到每个节点的路径上数组元素组成的序列都是递增(递减)的。


    最小堆 & 最大堆.png

    堆存储在下标为0的数组中。
    已知 child :::::: 得parent=(child-1)/2
    已知 parent :::::: 得 left=2parent+1
    :::::: ::::: ::::::: :::::::::right=2
    parent+2

    向下调整的应用
    • 堆的创建
    • 堆的删除(只能删除堆顶元素,最后一个元素替代堆顶元素,向下调整以满足堆的性质)
    向上调整的应用
    • 堆的插入 (只能在堆最后插入,插入之后,当堆中的元素不再满足堆的性质时,就需要对堆进行向上调整)

    Heap.h

    #define _CRT_SECURE_N0_WARNINGS 1
    
    #include <stdio.h>
    #include <assert.h>
    
    typedef struct Heap{
        int array[100];
        int size;
    }Heap;
    
    static void Swap(int *a, int *b)
    {
        int t = *a;
        *a = *b;
        *b = t;
    }
    
    //初始化
    void HeapInit(Heap *pH, int source[], int size)
    {
        for (int i = 0; i < size; i++)
        {
            pH->array[i] = source[i];
        }
        //更改堆的实际大小
        pH->size = size;
    }
    
    //向下调整 大堆
    //root 指的是下标
    void HeapAdjustDown(Heap* pH, int root)
    {
        int parent = root;
        
        while (1)
        {
            // 先判断有没有孩子(叶子结点)
            // 数组角度去想   -> 孩子的下标是否越界
            // 只要判断左孩子的下标(因为是完全二叉树)
            int left = parent * 2 + 1;
            int right = parent * 2 + 2;
    
            if (pH->size < left) //越界 左孩子不存在
                return;
    
            int MaxChild = left;
            if ((pH->size >= right) && (pH->array[right]>pH->array[MaxChild]))
                MaxChild = right;
    
            if (pH->array[MaxChild] < pH->array[parent])
                return;
    
            //交换 
            int temp = pH->array[MaxChild];
            pH->array[MaxChild] = pH->array[parent];
            pH->array[parent] = temp;
    
            parent = MaxChild;
        }
    }
    
    //向上调整 大堆
    
    void HeapAdjustUp(Heap* pH, int child)
    {
        int parent;
        while (child > 0)
        {
            parent = (child - 1) / 2;
            if (pH->array[parent] >= pH->array[child])
                return;
    
            Swap(pH->array + parent, pH->array + child);
    
            child = parent;
        }
    }
    
    void HeapMakeHeap(Heap* pH)
    {
        //最后一个非叶子结点 last=size-1;
        //parent=(last-1)/2 = size/2-1;
        //所有非叶子结点的下标为[0 ,size/2-1]
        //从物理结构上来看 从后往前建堆 [最后一个非叶子结点size/2-1,0]
        for (int i = (pH->size - 2) / 2; i >= 0; i--) {
            HeapAdjustDown(pH, i);
        }
    }
    
    void HeapPop(Heap* pH)
    {
        pH->array[0] = pH->array[pH->size - 1];
        pH->size = pH->size - 1;
    
        HeapAdjustDown(pH, 0);
    }
    
    int HeapTop(Heap* pH)
    {
        return pH->array[0];
    }
    
    void HeapPush(Heap* pH,int data)
    {
        assert(pH->size < 100);
        pH->array[pH->size++] = data;
    
        HeapAdjustUp(pH, pH->size-1);
    }
    
    
    
    void Test()
    {
        int array[] = { 53, 17, 78, 9, 45, 65, 87, 23, 31 };
        int size = sizeof(array) / sizeof(int);
    
        Heap    heap;
        HeapInit(&heap, array, size);
        HeapMakeHeap(&heap);
    
        HeapPop(&heap);
    
        HeapPush(&heap, 100);
        printf("%d\n", HeapTop(&heap));
    
        printf("建堆完成\n");
    }
    

    Main.c

    #define _CRT_SECURE_N0_WARNINGS 1
    
    #include "Heap.h"
    
    int main()
    {
        //Test(); 
        return 0;
    }
    

    相关文章

      网友评论

        本文标题:堆(二叉堆)

        本文链接:https://www.haomeiwen.com/subject/njxkwftx.html