zoukankan      html  css  js  c++  java
  • 用堆实现优先队列

    话不多说,先上代码

    #include <stdio.h>
    #include <stdlib.h>
    
    //定义一个堆得结构体,
    struct MyHeap
    {
        int* pnData;    //指向数据的指针
        int nSize;     //当前堆中的元素个数
    };
    
    //调整数据,维持堆得性质,这个和上次heapify的作用一样
    //只是这个时从子道父节点这样的判断而已。
    int IncreaseKey(MyHeap* pHeap, int nPos)
    {
        //循环和他父节点判断,只要 nPos > 1他就有父节点 
        while (nPos > 1)
        {
            int nMax = pHeap->pnData[nPos];
            int nParent = nPos / 2;
    
            //如果他比父节点大,交换数据,并使判断进入父节点
            //(因为只有父节点可能会影响堆得性质。他的数据改变了。)
            if (nMax > pHeap->pnData[nParent])
            {
                pHeap->pnData[nPos] = pHeap->pnData[nParent];
                pHeap->pnData[nParent] = nMax;
                nPos = nParent;
            }
            else        //否则堆没有被破坏,退出循环
            {
                break;
            }
        }
    
        return 1;
    }
    
    //插入数据,这里pnHeap为要插入的队,nLen为当前堆得大小。
    //nData为要插入的数据,这里注意报保证堆得空间足够。
    int Insert(MyHeap* pHeap, int nData)
    {
        ++pHeap->nSize;            //添加数据到末尾
        pHeap->pnData[pHeap->nSize] = nData;
        IncreaseKey(pHeap, pHeap->nSize);
        return 1;
    }
    
    //弹出堆中对大元素,并使堆得个数减一
    int PopMaxHeap(MyHeap* pHeap)
    {
        int nMax = pHeap->pnData[1];  //得到最大元素
    
                                      //不要忘记维持堆得性质,因为最大元素已经弹出了,主要思路就是
                                      //同他最大孩子填充这里。
    
        int nPos = 1;            //起始位1,因为他弹出,所以是这里开始破坏堆得性质的
        int nChild = nPos * 2;    //他的左孩子的位置,
    
                                  //循环填充,用最大孩子填充父节点
        while (nChild <= pHeap->nSize)
        {
            int nTemp = pHeap->pnData[nChild];
            if (nChild + 1 <= pHeap->nSize &&
                nTemp < pHeap->pnData[nChild + 1])
            {
                ++nChild;
                nTemp = pHeap->pnData[nChild];
            }
            pHeap->pnData[nPos] = nTemp;
            nPos = nChild;
            nChild *= 2;
        }
        //最好一个用最末尾的填充。
        pHeap->pnData[nPos] = pHeap->pnData[pHeap->nSize];
        --pHeap->nSize;            //堆个数量减一
        return nMax;            //返回最大值。
    }
    
    //程序入口main
    int main()
    {
        MyHeap myHeap;            //定义一个堆
        myHeap.pnData = (int*)::malloc(sizeof(int) * 11); //申请数据空间
        myHeap.nSize = 0;            //初始大小为0
    
        for (int i = 1; i <= 10; ++i)        //给优先队列堆里添加数据
        {
            Insert(&myHeap, i);
        }
    
        for (int i = 1; i <= 10; ++i)        //测试优先队列是否建立成功
        {
            printf("%d ", myHeap.pnData[i]);
        }
        printf("
    ");
    
        while (myHeap.nSize > 0)  //逐一弹出队列的最大值。并验证
        {
            printf("%d ", PopMaxHeap(&myHeap));
        }
        printf("
    ");
    
        ::free(myHeap.pnData);        //最后不要忘记释放申请的空间
        system("pause");
        return 0;
    }

    其实用堆实现队列就是用完全二叉树的应用过程,如果对完全二叉树以及堆排序有比较扎实的基础知识,再加上网上的查找的资料,实现优先队列还是不难的。

  • 相关阅读:
    LINQ分组排序后获取每组第一条记录
    String 中的Trim
    C# Switch优雅写法
    C# 输入指定日期获取当前年的第一天 、当前年的最后天、某月的第一天 、某月的最后一天
    快捷方式 ABP——切换MySQL数据库
    新建立git分支,之后将分支合并到master上
    C# Contains()、 == 和Equals() 比较
    使用TimeSpan 日期与时间拼接
    ActiveReports报表行号
    iOS基础(八)——最新更新方法,每天只提示一次
  • 原文地址:https://www.cnblogs.com/bryce1010/p/9387475.html
Copyright © 2011-2022 走看看