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、自定义优先级:

[cpp]  view plain copy
  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)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值