Prerequisite:
先决条件:
Hashing data structure
散列数据结构
How to write user-defined comparator for priority queue STL in C++?
如何在C ++中为优先级队列STL编写用户定义的比较器?
How to sort a map based on values instead of value?
如何根据值而不是值对地图排序?
Problem statement:
问题陈述:
Sort an array based on frequencies. The element having maximum frequency will come first. If two elements have the same frequency then the element coming first will appear first in the sorted array two.
根据频率对数组排序。 具有最大频率的元素将排在最前面。 如果两个元素具有相同的频率,则最先出现的元素将首先出现在排序数组2中。
Example:
例:
Input array:
[1, 2, 3, 2, 3, 2, 1]After sorting frequency wise:
[2, 2, 2, 1, 1, 3, 3]2 has the maximum frequency
thus, it came first and since 1 and 3 have the same frequency,
so, 1 came first preserving the order in the input array.
Solution:
解:
The idea is to create a hash table first which will store the frequency of unique elements. That can be created like below:
这个想法是首先创建一个哈希表,它将存储唯一元素的频率。 可以如下创建:
Hash function, h(x)=x but instead of storing key we will store the count
哈希函数h(x)= x,但是我们将存储计数而不是存储密钥
Initially, hash table is empty.
最初,哈希表为空。
For each key in input array,
Hash[key]++
End for
If we create the hash table from the above input array, it will be,
如果我们根据上面的输入数组创建哈希表,它将是
Key Frequency
1 2
2 3
3 2
So now we need to sort the map based on the value instead of the key, but for the same frequencies, we need to preserve the key order(it’s order not key itself).
因此,现在我们需要根据值而不是键对映射进行排序,但是对于相同的频率,我们需要保留键顺序(该顺序不是键本身)。
To preserve the key order we require another hash table that would store the first position of the key. We will store that like below:
为了保留键顺序,我们需要另一个哈希表,该哈希表将存储键的第一个位置。 我们将像下面这样存储:
Say this hash table is named first_occurrence
假设此哈希表名为first_occurrence
For each key in input array,
If first_occurence[key]==0: //not assigned
first_occurence[key]=key index+1
End for
So after processing the input the hash table first_occurrence would be:
因此,在处理输入后,哈希表first_occurrence将是:
Key First occurrence
1 1(0+1)
2 2(1+1
3 3(2+1)
So now rest of the task is to sort the hash table based on the map and based on first_occurrence hash table.
因此,现在剩下的任务是根据地图和基于first_occurrence哈希表对哈希表进行排序。
We will use the priority queue to sort this map based on our defined comparator where we will implement logic to sort by frequency value and first_occurrence hash table.
我们将使用优先级队列根据定义的比较器对此映射表进行排序,在该比较器中,我们将实现按频率值和first_occurrence哈希表排序的逻辑。
How to pass this in the comparator is our main challenge or area of our discussion?
如何在比较器中传递这一点是我们的主要挑战还是我们讨论的领域?
You can observe a thing that we have designed a class for this problem and kept the first_occurrence hash table as a data member, not any local member to a function. Thing is not the thing I do in general. So, there must be something, that made me design a class and bring the OOP concept within it. This is because I need to feed the first_occurrence hash table into the comparator and the comparator is a lambda function. Like below,
您会发现,我们已经为此问题设计了一个类,并将first_occurrence哈希表保留为数据成员,而不是函数的任何本地成员。 总的来说,这不是我要做的事情。 因此,必须有某种东西使我设计了一个类并将OOP概念引入其中。 这是因为我需要将first_occurrence哈希表提供给比较器,并且比较器是lambda函数。 像下面一样
auto comp=[](pair<int,int> a, pair<int,int> b){
//function body
}
But this time if you notice the implementation, we have
auto comp=[this](pair<int,int> a, pair<int,int> b){
//function body
}
This helps you to pass the data members to the lambda function or it's known as capturing of the lambda function.
这可以帮助您将数据成员传递给lambda函数,或者称为捕获lambda函数 。
That's why we designed the class and made first_occurrence as data members to feed into the lambda function. Now we can perform our logic similarly as we do in comparators.
这就是为什么我们设计类并让first_occurrence作为数据成员馈入lambda函数的原因。 现在,我们可以像在比较器中一样执行逻辑。
The lambda comparator would be like below which will give us a sorted map based on our requirement via the priority_queue.
Lambda比较器如下所示,它将根据优先级通过priority_queue为我们提供排序的映射。
auto comp=[this](pair<int,int> a, pair<int,int> b){
if(a.second<b.second)
return true;
else if(a.second>b.second)
return false;
else{
if(first_occurence[a.first]<first_occurence[b.first])
return false;
else
return true;
}
};
So after pushing all pairs(a map element is pair, <key, element>) we will have our priority queue as,
因此,在推送所有对之后(一个地图元素是pair,<key,element>),我们将拥有优先级队列,
Key Frequency
2 3
1 2
3 2
Now, pop each element from the priority queue and append the key as many times as the frequency,
现在,从优先级队列中弹出每个元素,并按频率添加键多次,
So at iteration 1
We will pop <2,3>
So vector will be 2 2 2
So at iteration 2
We will pop <1,2>
So vector will be 2 2 2 1 1
So at iteration 3
We will pop <3,2>
So vector will be 2 2 2 1 1 3 3
Queue Is empty
So our sorted array based on frequency is
2 2 2 1 1 3 3
C++ implementation:
C ++实现:
#include <bits/stdc++.h>
using namespace std;
class Includehelp {
public:
unordered_map<int, int> first_occurence;
void print(vector<int> arr)
{
for (auto i : arr) {
cout << i << " ";
}
cout << endl;
}
vector<int> sort_by_frequency(vector<int> arr)
{
//create the hashmap
unordered_map<int, int> mymap;
for (int i = 0; i < arr.size(); i++) {
mymap[arr[i]]++;
if (first_occurence[arr[i]] == 0)
first_occurence[arr[i]] = i + 1;
}
//now to sort based on frequency lets use priority queue
//comparator of priority queue using lambda function
auto comp = [this](pair<int, int> a, pair<int, int> b) {
if (a.second < b.second)
return true;
else if (a.second > b.second)
return false;
else {
if (first_occurence[a.first] < first_occurence[b.first])
return false;
else
return true;
}
};
priority_queue<pair<int, int>, vector<pair<int, int> >, decltype(comp)> pq(comp);
for (auto& ij : mymap) {
pq.push(ij);
}
//sorted outcome
vector<int> result;
while (!pq.empty()) {
pair<int, int> p = pq.top();
pq.pop();
int no = p.first;
int freq = p.second;
for (int i = 0; i < freq; i++)
result.push_back(no);
}
return result;
}
};
int main()
{
int n;
cout << "Enter number of elements\n";
cin >> n;
vector<int> arr(n, 0);
cout << "Enter the elements\n";
for (int i = 0; i < n; i++) {
cin >> arr[i];
}
Includehelp* obj = new Includehelp();
arr = obj->sort_by_frequency(arr);
cout << "Printing after sorting by frequency\n";
obj->print(arr);
return 0;
}
Output:
输出:
Enter number of elements
8
Enter the elements
1 2 3 1 2 3 4 5
Printing after sorting by frequency
1 1 2 2 3 3 4 5
翻译自: https://www.includehelp.com/data-structure-tutorial/sort-elements-by-frequency.aspx