• 2014腾讯实习笔试题——优先队列


    2014腾讯实习笔试题第二题是关于优先队列的。不是非常熟悉,查阅了一下资料。总结一下:

    优先队列是基于堆(二叉堆)实现的。每当增加(push)一个新元素时。会依据优先级。将优先级最大(或最小)的元素依照堆排序(大顶堆,小顶堆)的方式放到堆顶。

    如此的话。返回的堆顶元素(top)即优先级最高(或最小)的元素。

    当然。在pop()操作之后,仍然要进行堆排序,调整元素位置。參考资料例如以下:

    1 优先队列

    1.1 简单介绍

                  队列的特点是先进先出。通常都把队列比喻成排队买东西。大家都非常守秩序。先排队的人就先买东西。

    可是优先队列有所不同,它不遵循先进先出的规则,而是依据队列中元素的优先权,优先权最大的先被取出。通常把优先队列比喻成现实生活中的打印。

    一个打印店里有非常多打印机,每台机器的性能不一样,有的打印机打印非常快,有的打印机打印速度非常慢。

    当这些打印机陆陆续续打印完自己的任务时进入排队等候状态。假设我这个时候要打印一份文件,我选的不是第一个排队的打印机。而是性能最好。打印最快的打印机。

                重点:优先级队列,是要看优先级的,谁的优先级更高,谁就先得到权限。不分排队的顺序!

                基本操作:

                       empty() 假设队列为空返回真

                       pop() 删除对顶元素

                       push() 增加一个元素

                       size() 返回优先队列中拥有的元素个数

                       top() 返回优先队列对顶元素

                       在默认的优先队列中,优先级高的先出队。在默认的int型中先出队的为较大的数。

    1.2 用堆实现优先队列

     以下是最小堆实现的优先队列:

    #include <iostream>
    #include <vector>
    using namespace std;
    
    class Heap
    {
    public:
    	Heap(int iSize);
    	~Heap();
    
    	int Enqueue(int iVal);
    	int Dequeue(int &iVal);
    	int GetMin(int &iVal);
    	void printQueue();
    protected:
    	int *m_pData;
    	int m_iSize;
    	int m_iAmount;
    };
    Heap::Heap(int iSize = 100)//注意这里是从0開始,所以假设根是i。那么左孩子是2*i+1,右孩子是2*i+2
    {
    	m_pData = new int[iSize];
    	m_iSize = iSize;
    	m_iAmount = 0;
    }
    Heap::~Heap()
    {
    	delete []m_pData;
    }
    
    int Heap::Enqueue(int iVal)//进入堆
    {
    	if (m_iAmount == m_iSize)
    	{
    		return 0;
    	}
    	m_pData[m_iAmount ++] = iVal;
    	int iIndex = m_iAmount - 1;
    	while (m_pData[iIndex] < m_pData[(iIndex - 1) /2])//上浮,直到满足最小堆
    	{
    		swap(m_pData[iIndex],m_pData[(iIndex - 1) /2]);
    		iIndex = (iIndex - 1) /2;
    	}
    	return 1;
    }
    
    int Heap::Dequeue(int &iVal)//出堆
    {
    	if (m_iAmount == 0)
    	{
    		return 0;
    	}
    	iVal = m_pData[0];//出堆的数据
    	m_pData[0] = m_pData[m_iAmount - 1];//最后一个数据放到第一个根上面
    	-- m_iAmount;//总数减1
    	int rc = m_pData[0];
    	int s = 0;
    	for (int j = 2*s +1; j < m_iAmount; j *= 2)//最后一个数放到第一个位置以后。開始下沉,来维持堆的性质
    	{
    		if (j < m_iAmount - 1 && m_pData[j] > m_pData[j+1])
    		{
    			++ j;
    		}
    		if (rc < m_pData[j])//rc应该插入在s位置上
    		{
    			break;
    		}
    		m_pData[s] = m_pData[j];
    		s = j;
    	}
    	m_pData[s] = rc;
    	return 1;
    }
    
    int Heap::GetMin(int &iVal)
    {
    	if (m_iAmount == 0)
    	{
    		return 0;
    	}
    	iVal = m_pData[0];
    	return 1;
    }
    
    void Heap::printQueue()
    {
    	for (int i = 0; i < m_iAmount; ++ i)
    	{
    		cout << m_pData[i] << " ";
    	}
    	cout << endl;
    }
    int main()
    {
    	Heap heap;
    	heap.Enqueue(4);
    	heap.Enqueue(1);
    	heap.Enqueue(3);
    	heap.Enqueue(2);
    	heap.Enqueue(6);
    	heap.Enqueue(5);
    	heap.printQueue();
    
    	int iVal;
    	heap.Dequeue(iVal);
    	heap.Dequeue(iVal);
    
    	heap.printQueue();
    	return 0;
    }

    1.3 STL实现优先队列

    用法:

    头文件:

    #include <queue>

    声明方式:

    1、普通方法:

    priority_queue<int>q;
    //通过操作,依照元素从大到小的顺序出队

    2、自己定义优先级:

    1. struct cmp  
    2. {  
    3.     bool operator()(int x, int y)  
    4.     {  
    5.         return x > y;  
    6.     }  
    7. };  
    //当中,第二个參数为容器类型。第三个參数为比較函数。
    结构体声明方式:
    struct node
    {
          int x, y;
           friend bool operator < (node a, node b)
          {
                 return a.x > b.x; //结构体中。x小的优先级高
          }
    };
    priority_queue<node>q;//定义方法
    //在该结构中。y为值, x为优先级。


    //通过自己定义operator<操作符来比較元素中的优先级。


    //在重载”<”时。最好不要重载”>”,可能会发生编译错误

     

    2应用

    首先优先队列是由堆来实现的,所以以后用到优先队列的地方,能够直接用C++中的STL来直接实现。可是不妨自己实现几次。否则我们仅仅会成为傻瓜,什么东西就知道怎么用,不知道是怎样实现的。

    优先队列适用的范围非常广,比方:

    1、构造哈夫曼编码

                  构造哈夫曼编码是找到节点集合中频率最小的两个点,然后合并节点在插入到集合中,再循环。。

    2、一些任务调度算法

                比方操作系统的线程的调度算法,有的是依照优先级来调度的。每次都运行优先级较高的线程

    3、合并n个有序文件为一个有序文件

                首先把n个有序文件的第一个元素取出来。放到优先队列里面,然后取最小值,然后再插入元素导优先队列。取最小值。。。

    4、因为优先队列内部是有堆实现的。所以适用于堆的都适用于优先队列

              比方排序,找中位数,找最大的k个数


    (參考来源:http://blog.csdn.net/zhang20072844/article/details/10286997)

  • 相关阅读:
    日常问题--解决 ‘Could not fetch URL https://pypi.python.org’的问题
    scrapy(一)--Pycharm创建scrapy项目
    flask常用的第三方插件
    Django model补充(修改自带的user表以及获取单选值get_FOO_display)
    Django form组件应用
    Django auth权限和login_required用法
    flask--Django 基本使用
    Django分页器
    html备忘录
    jQuery备忘录
  • 原文地址:https://www.cnblogs.com/ldxsuanfa/p/9927700.html
Copyright © 2020-2023  润新知