• Priority Queue(优先队列)


      今天早上起来完成了一个完整的基于二叉堆实现的优先队列,其中包含最小优先和最大优先队列。

      上篇说了优先队列的特性,通过建堆和堆排序操作,我们就已经看到了这种数据结构中的数据具有某种优先级别,要么非根节点大于他的子节点,要么就相反,在最大优先队列中最大优先级别就是指节点值最大的数据为根节点,每次出队时肯定是最大的先出去,反之则是最小优先队列,但要注意插入时的数据不一定是最大或最小的,优先队列会通过一点小技巧找到所有节点之间的关系并对应起来,重新使得你随意插入的数据满足优先队列的特性,因而这种数据结构的使用很普遍。比如:操作系统中的任务调度等。

      用线性表实现这种数据结构并不难,下面是代码:

    /**
     *  PrioityQueue(优先队列)
     */
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <conio.h>
     
    typedef int ElemType;
     
    typedef struct
    {
        ElemType * arr;
        int size;
    }Heap;
     
    /* 全局函数 */
    Heap * Initialize_Heap();
    void Build_Min_Heap();
    void Build_Max_Heap();
    void Heap_Sort();
    int Heap_Minimum();
    int Heap_Maximum();
    int Heap_Extract_Min();
    int Heap_Extract_Max();
    void Heap_Insert_Max();
    void Heap_Insert_Min();
    void Destroy_Heap();
     
    /* 静态函数 */
    static int HeapParent();
    static int HeapLeft();
    static int HeapRight();
    static void Min_Heapify();
    static void Max_Heapify();
    static void Heap_Increase_Min_Key();
    static void Heap_Increase_Max_Key();
     
    /*
     *  初始化堆
     *     参数说明:无参数
     *
     *  返回堆
     */
    Heap * Initialize_Heap(void)
    {
        Heap * heap;
     
        heap = (Heap *)malloc(sizeof(Heap));
        heap -> arr = (ElemType *)malloc(sizeof(ElemType));
        heap -> size = -1;
     
        return heap;
    }
     
    /*
     *  节点i的双亲
     */
    static int HeapParent(int i)
    {
        return i/2;
    }
     
    /*
     *  节点i的左孩子
     */
    static int HeapLeft(int i)
    {
        return 2*i + 1;
    }
     
    /*
     *  节点i的右孩子
     */
    static int HeapRight(int i)
    {
        return 2*(i + 1);
    }
     
    /*
     *  维护最小堆的性质
     */
    static void Min_Heapify(Heap * heap, int i)
    {
        int l = HeapLeft(i);
        int r = HeapRight(i);
        int smallest;
        int temp;
     
        if(l < heap -> size && heap -> arr[l] < heap -> arr[i])
            smallest = l;
        else
            smallest = i;
        if(r < heap -> size && heap -> arr[r] < heap -> arr[i])
            smallest = r;
        if(smallest != i)
        {
            temp = heap -> arr[i];
            heap -> arr[i] = heap -> arr[smallest];
            heap -> arr[smallest] = temp;
            Min_Heapify(heap, smallest);
        }
    }
     
    /*
     *  维护最大堆的性质
     */
    static void Max_Heapify(Heap * heap, int i)
    {
        int _L = HeapLeft(i);
        int _R = HeapRight(i);
        int largest;
        int temp;
     
        if(_L < heap -> size && heap -> arr[_L] > heap -> arr[i])
            largest = _L;
        else
            largest = i;
        if(_R < heap -> size && heap -> arr[_R] > heap -> arr[largest])
            largest = _R;
        if(largest != i)
        {
            temp = heap -> arr[i];
            heap -> arr[i] = heap -> arr[largest];
            heap -> arr[largest] = temp;
            Max_Heapify(heap, largest);
        }
    }
     
    /*
     *  建最小堆
     */
    void Build_Min_Heap(Heap * heap)
    {
        int i;
     
        for(i = heap -> size/2; i >= 0; i--)
            Min_Heapify(heap, i);
    }
     
    /*
     *  建最大堆
     */
    void Build_Max_Heap(Heap * heap)
    {
        int i;
     
        for(i = heap -> size/2; i >= 0; i--)
            Max_Heapify(heap, i);
    }
     
    /*
     *  最大优先队列 - 排序
     */
    void Heap_Sort(Heap * heap)
    {
        int i;
        int temp;
     
        Build_Max_Heap(heap);
        for(i = heap -> size; i >= 0; i--)
        {
            temp = heap -> arr[0];
            heap -> arr[0] = heap -> arr[i];
            heap -> arr[i] = temp;
            -- heap -> size;
            Max_Heapify(heap, 0);
        }
    }
     
    /*
     *  最小优先队列 - 最小值
     */
    int Heap_Minimum(Heap * heap)
    {
        return heap -> arr[0];
    }
     
    /*
     *  最大优先队列 - 最大值
     */
    int Heap_Maximum(Heap * heap)
    {
        return heap -> arr[0];
    }
     
    /*
     *  最小优先队列 - 去除最小值节点
     */
    int Heap_Extract_Min(Heap * heap)
    {
        int min;
     
        if(heap -> size < 0)
        {
            fprintf(stderr, "Heap underflow!
    ");
            return 0;
        }
        min = heap -> arr[0];
        heap -> arr[0] = heap -> arr[heap -> size];
        heap -> arr[heap -> size] = min;
        -- heap -> size;
        Min_Heapify(heap, 0);
     
        return min;
    }
     
    /*
     *  最大优先队列 - 去除最大值节点
     */
    int Heap_Extract_Max(Heap * heap)
    {
        int max;
     
        if(heap -> size < 0)
        {
            fprintf(stderr, "Heap underflow!
    ");
            return 0;           //提前退出
        }
        max = heap -> arr[0];
        heap -> arr[0] = heap -> arr[heap -> size];
        -- heap -> size;
        Max_Heapify(heap, 0);
     
        return max;
    }
     
    /*
     *  将key的值赋给节点i。此处将key值插入最小堆中
     *
     *  参数说明:
     *      1.接收一个已存在的堆
     *      2.节点位置
     *      3.与堆节后数据相同类型的键值
     */
    static void Heap_Increase_Min_Key(Heap * heap, int i, ElemType key)
    {
        int temp;
     
        if(key > heap -> arr[i])
        {
            printf("请输入小于当前节点值的数据
    ");
            return ;
        }
        heap -> arr[i] = key;
        while(i > 0 && heap -> arr[HeapParent(i)] > heap -> arr[i])
        {
            temp = heap -> arr[i];
            heap -> arr[i] = heap -> arr[HeapParent(i)];
            heap -> arr[HeapParent(i)] = temp;
            i = HeapParent(i);
        }
    }
     
    /*
     *  将key的值赋给节点i。此处将key值插入最大堆中
     *
     *  参数说明:
     *      1.接收一个已存在的堆
     *      2.节点位置
     *      3.与堆节后数据相同类型的键值
     */
    static void Heap_Increase_Max_Key(Heap * heap, int i, ElemType key)
    {
        int temp;
     
        if(key < heap -> arr[i])
        {
            printf("请输入大于当前节点值的数据
    ");
            return ;
        }
        heap -> arr[i] = key;
        while(i > 0 && heap -> arr[HeapParent(i)] < heap -> arr[i])
        {
            temp = heap -> arr[i];
            heap -> arr[i] = heap -> arr[HeapParent(i)];
            heap -> arr[HeapParent(i)] = temp;
            i = HeapParent(i);
        }
    }
     
    /*
     *  将key值插入最小堆
     */
    void Heap_Insert_Min(Heap * heap, ElemType key)
    {
        ++ heap -> size;
        heap -> arr[heap -> size] = 65533;
        Heap_Increase_Min_Key(heap, heap -> size, key);
    }
     
    /*
     *  将key值插入最大堆
     */
    void Heap_Insert_Max(Heap * heap, ElemType key)
    {
        ++ heap -> size;
        heap -> arr[heap -> size] = -65533;
        Heap_Increase_Max_Key(heap, heap -> size, key);
    }
     
    /*
     *  如果堆存在则销毁堆
     *
     *  无参数/返回值
     */
    void Destroy_Heap(Heap * heap)
    {
        if(heap && heap -> arr)
        {
            free(heap -> arr);
            free(heap);
            heap = NULL;
        }
    }
    
    // 主函数
    int main(void)
    {
        ElemType val;
        Heap * heap;
        char c;
        int i, cont = 0;
     
        heap = Initialize_Heap();
     
        puts("1) Insert Heap    2) Extract Max");
        puts("3) Display  4) Exit");
     
        while((c = getch()) != '4')
        {
            switch(c)
            {
                case '1' :  cont ++;
                            printf("Enter key:");
                            scanf("%d", &val);
                            Heap_Insert_Max(heap, val);
                    break;
                case '2' :  cont --;
                            printf("Max key = %d
    ", Heap_Extract_Max(heap));
                    break;
                case '3' :  Build_Max_Heap(heap);
                            printf("显示数据:
    ");
                            for(i = 0; i < cont; i++)
                                printf("%d ", heap -> arr[i]);
                            printf("NULL
    ");
                    break;
            }
        }
        // Destroy_Heap();
     
        return 0;
    }

      参考资料:1.《算法导论》- 堆排序 (84~93)。

           2.百度百科 - 优先队列

           3.百度百科 - 堆

  • 相关阅读:
    git 仓库过大,clone不下来的解决办法
    vue项目使用elementUI pagination 实现前端分页
    Element中 Table表格数据居中显示设置
    css实现鼠标悬浮图片放大
    vue中配置开发环境、测试环境、生产环境
    vue中@keyup.enter没有作用
    LambdaToSql(轻量级ORM) 入门篇 开源项目
    04.如何升级扩展以支持Visual Studio 2019
    03. 将pdb调试文件包含到.vsix包中
    02.vs插件 获取项目和解决方案路径
  • 原文地址:https://www.cnblogs.com/darkchii/p/7595189.html
Copyright © 2020-2023  润新知