• 堆(二叉堆) 源码笔记


    binheap.h

    typedef int ElementType;
    
    /* START: fig6_4.txt */
    #ifndef _BinHeap_H
    #define _BinHeap_H
    
    struct HeapStruct;
    typedef struct HeapStruct *PriorityQueue;
    
    PriorityQueue Initialize( int MaxElements );
    void Destroy( PriorityQueue H );
    void MakeEmpty( PriorityQueue H );
    void Insert( ElementType X, PriorityQueue H );
    ElementType DeleteMin( PriorityQueue H );
    ElementType FindMin( PriorityQueue H );
    int IsEmpty( PriorityQueue H );
    int IsFull( PriorityQueue H );
    
    #endif
    
    /* END */
    

    binheap.c

    /* 这里实现的是最小堆 */
    
    #include "binheap.h"
    #include "fatal.h"
    #include <stdlib.h>
    
    #define MinPQSize (10) // 堆最小的尺寸
    #define MinData (-32767)
    
    // 堆的结构
    struct HeapStruct
    {
        int Capacity; // 代表最大值
        int Size; // 当前的堆大小
        ElementType *Elements; // 数组
    };
    
    /* START: fig6_0.txt */
    /**
     * 初始化堆
     * @param MaxElements 最大的容量
     * @return 指向最大堆的指针
     */
    PriorityQueue
    Initialize( int MaxElements )
    {
                PriorityQueue H;
    
    /* 1*/      if( MaxElements < MinPQSize )
    /* 2*/          Error( "Priority queue size is too small" );
    
    /* 3*/      H = malloc( sizeof( struct HeapStruct ) );
    /* 4*/      if( H ==NULL )
    /* 5*/          FatalError( "Out of space!!!" );
    
        /* Allocate the array plus one extra for sentinel */
    /* 6*/      H->Elements = malloc( ( MaxElements + 1 )
                                      * sizeof( ElementType ) ); // 给数组分配空间
    /* 7*/      if( H->Elements == NULL )
    /* 8*/          FatalError( "Out of space!!!" );
    
    /* 9*/      H->Capacity = MaxElements; // H 的容量
    /*10*/      H->Size = 0; // 当前的堆大小
    /*11*/      H->Elements[ 0 ] = MinData;
    
    /*12*/      return H;
    }
    /* END */
    
    void
    MakeEmpty( PriorityQueue H )
    {
        H->Size = 0;
    }
    
    /* START: fig6_8.txt */
    /* H->Element[ 0 ] is a sentinel */
    /**
     * 插入操作
     * @param X 待插入的元素
     * @param H 要插入的目标堆
     */
    void
    Insert( ElementType X, PriorityQueue H )
    {
        int i;
    
        if( IsFull( H ) )
        {
            Error( "Priority queue is full" );
            return;
        }
    
        // 上滤(percolate up),如果父节点比 X 大,就将其给滤下来
        for( i = ++H->Size; H->Elements[ i / 2 ] > X; i /= 2 )
            H->Elements[ i ] = H->Elements[ i / 2 ];
        H->Elements[ i ] = X; // 最后剩下的位置就是 X 应该插入的位置
    }
    /* END */
    
    
    /* START: fig6_12.txt */
    /**
     * 删除最小元
     * @param H
     * @return 返回最小元
     */
    ElementType
    DeleteMin( PriorityQueue H )
    {
                int i, Child;
                ElementType MinElement, LastElement;
    
    /* 1*/      if( IsEmpty( H ) )
                {
    /* 2*/          Error( "Priority queue is empty" );
    /* 3*/          return H->Elements[ 0 ];
                }
    /* 4*/      MinElement = H->Elements[ 1 ]; // 根节点即最小元
    /* 5*/      LastElement = H->Elements[ H->Size-- ]; // 取出最后一个元素,用于插入到删除最小元之后的根节点处,然后下滤
    
    /* 6*/      for( i = 1; i * 2 <= H->Size; i = Child )
                {
                    /* Find smaller child */
    /* 7*/          Child = i * 2;
    /* 8*/          if( Child != H->Size && H->Elements[ Child + 1 ]
    /* 9*/                                < H->Elements[ Child ] )
    /*10*/              Child++;
    
                    /* Percolate one level 下滤操作 */
    /*11*/          if( LastElement > H->Elements[ Child ] )
    /*12*/              H->Elements[ i ] = H->Elements[ Child ];
                    else
    /*13*/              break;
                }
    /*14*/      H->Elements[ i ] = LastElement;
    /*15*/      return MinElement;
    }
    /* END */
    
    /**
     * 查找最小元,即取出根节点存储的元素
     * @param H
     * @return
     */
    ElementType
    FindMin( PriorityQueue H )
    {
        if( !IsEmpty( H ) )
            return H->Elements[ 1 ];
        Error( "Priority Queue is Empty" );
        return H->Elements[ 0 ];
    }
    
    /**
     * 判断堆是否为空
     * @param H
     * @return
     */
    int
    IsEmpty( PriorityQueue H )
    {
        return H->Size == 0;
    }
    
    /**
     * 判断堆是否已满
     * @param H
     * @return
     */
    int
    IsFull( PriorityQueue H )
    {
        return H->Size == H->Capacity;
    }
    
    /**
     * 销毁堆
     * @param H
     */
    void
    Destroy( PriorityQueue H )
    {
        free( H->Elements );
        free( H );
    }
    
    #if 0
    /* START: fig6_14.txt */
            for( i = N / 2; i > 0; i-- )
                PercolateDown( i );
    /* END */
    #endif
    

    main.c(测试函数)

    #include "binheap.h"
    #include <stdio.h>
    
    #define MaxSize (1000)
    
    int main()
    {
        PriorityQueue H;
        int i, j;
    
        H = Initialize(MaxSize);
    
        // 循环插入 MaxSize 个数字
        for (i = 0, j = MaxSize / 2; i < MaxSize; i++, j = (j + 71) % MaxSize)
            Insert(j, H);
    
        j = 0;
    
    #if 0
        while (!IsEmpty(H))
        {
            int ele = DeleteMin(H);
            printf("%d ", ele);
        }
        printf("
    ");
    #endif
    
    
        while (!IsEmpty(H))
            if (DeleteMin(H) != j++)
                printf("Error in DeleteMin, %d
    ", j);
    
        printf("Done...
    ");
        return 0;
    }
    

    fatal.h

    #include <stdio.h>
    #include <stdlib.h>
    
    #define Error( Str )        FatalError( Str )
    #define FatalError( Str )   fprintf( stderr, "%s
    ", Str ), exit( 1 )
    
  • 相关阅读:
    代办事项
    问题总结2015/05/05
    Android Studio 更新
    Android 防内存泄露handler
    android canvas 绘图笔记
    Android Studio compile error : enum constant INSTANT_RUN_REPLACEMENT does not exist in class
    android Studio 配置LUA 开发环境
    Android 性能优化之(1)-MAT使用教程
    shareSdk打包报错解决办法
    Android 事件分发机制
  • 原文地址:https://www.cnblogs.com/fanlumaster/p/13933758.html
Copyright © 2020-2023  润新知