关于优先队列的数据结构:
优先队列的底层实现是堆;
下面介绍一下堆数据结构:堆数据结构是由数组构建的,最大堆:所有非叶子节点值都大于等于其左右孩子结点的值;
最小堆:所有非叶子节点值都小于等于左右孩子结点的值;
如何构建一个堆;伪代码如下(为了方便起见,数组的第一个元素的索引是1开始的)
1.首先得到相应的左结点和右结点的下标索引
PARENT(i)
return i / 2
LEFT(i)
return 2 * i
RIGHT(i)
2 * i + 1
2.从第一个非叶子节点开始,构建堆;(注意是从第一个非叶子节点开始构建堆)
A.heap-size = A.length
for A.length / 2 downto 1
MAX-HEAPIFY(A, i)
3.一下是递归的max_heapify(array,n)的伪代码:(非叶子节点和左右两个节点进行比较,选择大的数的索引,然后将大的数与起先的非叶子节点进行交换),交换后如果index!=largest_index ,还需要在交换后的结点进行维护
l = LIFT(i)
r = RIGHT(i)
if l <= A.heapsize and A[l] > A[i]
largest = l
else largest = i
if r <= A.heapsize and A[r] > A[largest]
largest = r
if largest != i
exchage A[i] with A[largest]
MAX-HEAPIFY(A, largest)
4,然后是堆排序算法:
伪代码是:交换相应的堆顶元素和数组尾部的元素,然后弹出数组最后一个元素,然后继续维护堆,max_heapify(array,n-1);
优先队列就是堆排序的一种应用;在c++中优先队列数据结构的使用,以及leetcode刷题如下:
leetcode347:
返回数组中前k个频率最大的数;
1.首先将数组进行遍历,然后通过map数据结构(hash)存储,然后对map中值进行排序,然后选择前k个数,时间复杂度为O(nlogn)主要的时间复杂度都是在排序算法上面;
class Solution { public: vector<int> topKFrequent(vector<int>& nums, int k) { //算法一实现:使用map数据结构来实现 unordered_map<int,int> nums_map; for(int i=0;i<nums.size();i++){ nums_map[nums[i]]++;//同时也可以还是通过insert函数添加pair类型的数据; } unordered_map<int,int>::iterator iter=nums_map.begin(); vector<pair<int,int>> temp_nums; for(iter;iter!=nums_map.end();iter++){ temp_nums.push_back(make_pair(iter->first,iter->second)); } sort(temp_nums.begin(),temp_nums.end(),compare); vector<int> ans; //没有iter+i的用法,关联容器 for(int i=0;i<k;i++){ ans.push_back(temp_nums[i].first); } return ans; } static int compare(const pair<int,int>& pair1,const pair<int,int> &pair2){ if(pair1.second<pair2.second){ return false; } else{ return true; } } };时间复杂度为O(nlog(n));
2.使用优先队列来维护一个最小堆来实现相应;
class Solution { public: vector<int> topKFrequent(vector<int>& nums, int k) { unordered_map<int,int> nums_map; for(int i=0;i<nums.size();i++){ nums_map[nums[i]]++;//同时也可以还是通过insert函数添加pair类型的数据; } //如何创建一个优先对垒priority_queue<int,vector<int>,greater<int>> 基本数据结构是int时,如果基本数据结构是pair<int,int> priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>> min_queue;//构建了一个最小堆; unordered_map<int,int>::iterator iter=nums_map.begin(); for(iter;iter!=nums_map.end();iter++){//对排序默认按照是键值进行排序 if(min_queue.size()==k){//如果已经维护了一个k个数字的最小堆 pair<int,int> temp=max_queue.top();//得到最大堆顶元素; if(iter->second>temp.first){ min_queue.pop();//弹出最后的元素,k个值中的较小频率值 min_queue.push(pair<int,int>(iter->second,iter->first)); } } else{ min_queue.push(pair<int,int>(iter->second,iter->first)); } } vector<int> ans; while(!min_queue.empty()){ ans.push_back(min_queue.top().second); min_queue.pop(); } return ans; } };
python 中也有相应的高级数据结构
from collections import defaultdict import heapq class Solution: def topKFrequent(self, nums, k): """ :type nums: List[int] :type k: int :rtype: List[int] """ mydict=defaultdict(int) for num in nums: mydict[num]+=1 mylist=mydict.items() ans_list=heapq.nlargest(k,mylist,key=lambda x:x[1]) result=[] for item in ans_list: result.append(item[0]) return result