typedef std::map<uint16_t, uint32_t> TSrcMap;
TPSrcMap sp;
TSrcMap::iterator its;
/*Code to populate the array_start.*/
/*Code to populate the array_end.*/
typedef struct port_count
{
uint32_t port_number;
uint32_t port_count;
}port_count_t;
port_count_t pcount[5];
memset(pcount,0,sizeof(pcount));
size_t structs_len = sizeof(pcount)/sizeof(port_count_t);
for(its = stcp.begin(); its != stcp.end();its++)
{
if(pcount[smallest_index].port_count < (*its).second)
{
pcount[smallest_index].port_count = (*its).second;
pcount[smallest_index].port_number = (*its).first;
#ifdef USEQSORT
qsort(pcount, structs_len, sizeof(port_count_t), struct_cmp_by_port_count);
#else
std::sort(pcount,(pcount+structs_len),cmp_by_port_count);
#endif
}
}
#ifdef USEQSORT
/* qsort struct comparision function compare port frequency*/
int struct_cmp_by_port_count(const void *a, const void *b)
{
port_count_t *ia = (port_count_t *)a;
port_count_t *ib = (port_count_t *)b;
return (ia->port_count - ib->port_count);
}
#else
/* qsort struct comparision function compare port frequency*/
int cmp_by_port_count(const port_count_t& a, const port_count_t& b)
{
return (a.port_count < b.port_count);
}
#endif
我有一个大的std :: map结构,它将port_count映射到port_number。我必须根据port_count找到最大的5个元素。(其中key是port_number)。我有一个上面给出的单个解析循环,它调用一个在大小为5的数组上排序算法(qsort或std :: sort)。这是实现这一目标的最有效方法吗?就排序函数的调用次数而言。有一个更好的方法来做到这一点,就计算效率?我也尝试了qsort和std :: sort,它们似乎都执行大致相同。这是因为我正在排序的数组的大小太小而不会产生重大影响。我试图理解这个算法就其复杂性而言。任何想法都会受到赞赏。
答案 0 :(得分:2)
从最初为空的结果deque开始,并在算法持续时间内保持排序:
最后,产生的双端队列包含(最多)5个最大元素。这基本上是O(n)算法。
您可以使用带有降序元素的向量而不是deque,而是从末尾删除,甚至是链接列表(尽管指针追逐永远不会对性能有益)。
或者,您可以简单地创建其他地图,即原始地图的“反向”(即,值现在是键,反之亦然),并始终向两者添加元素。这样,替代地图将在其末尾附近总是包含5个最大的元素。
答案 1 :(得分:2)
你为什么要整理?你正在变得比它需要的更复杂。
创建一个包含5个元素的树 - 这是您最大的5个元素。 (使用std :: set) 只需循环遍历内容,每次找到大于树中最小数字的数字时,将其添加到树中并删除任何溢出(前5位中的数字,不再存在)
这是我在两分钟内在记事本中绘制的内容,没有编译保证:
#include <set>
#include <iostream>
using namespace std;
int main(int argc, char **argv)
{
int unordered[] = {7, 12, 11, 19, 88, 42, 3, 1, 22};
set<int> biggest5;
int smallest = -1;
for(int i = 0; i < sizeof(unordered)/sizeof(int); ++i)
{
if (unordered[i] >= smallest)
{
biggest5.insert(unordered[i]);
if(biggest5.size() > 5)
biggest5.erase(biggest5.begin());
smallest = *biggest5.begin();
}
}
//All done
cout << "Set: ";
for (set<int>::reverse_iterator i = biggest5.rbegin(); i != biggest5.rend(); ++i)
{
cout << *i << " ";
}
cout << endl;
return 0;
}
这应该打印
Set: 88 42 22 19 12
您还可以在遍历之后修剪biggest5
集以获得最大性能,但需要花费更多内存。
答案 2 :(得分:2)
您应该查看我最喜欢的一个经常被忽视的STL算法:nth_element
(ref)。对于快速排序,它平均对 O(N)中的数据进行部分排序,与O(N log(N))相比,这样枢轴(第n个元素)大于一侧的所有元素,少于另一方的所有元素。对于大输入,加速与快速排序相比可能非常显着。
编辑:如果您想要对某个范围进行排序,例如5个最大的元素,您可以使用partial_sort
(ref):
std::partial_sort(large_container.begin(), large_container.begin() + 5, large_container.end(), comparison_function);
将在 O(n + 5 * log(5))中对large_container进行部分排序,这样前五个元素是big_container中降序最大的元素(或者是按升序排列的最小元素)关于比较功能)。这可能会取代上面代码的重要部分。
答案 3 :(得分:1)
std :: sort最有可能使用QuickSort,或者至少是一个名为IntroSort的QuickSort变体,当递归过深时,它会“退化”到HeapSort。所以两者都会在O(nlogn)时间运行。因此,选择哪一个(如果您自己的快速排序正确实施)无关紧要。
答案 4 :(得分:1)
我认为5元素数组可能小到可以手动处理,通过将最小元素与地图中的每个项目进行比较并相应地调整数组,因此不需要调用排序函数。如果需要维护更大的数组,堆可能是更好的选择。
答案 5 :(得分:1)
我想到的另一个解决方案是使用priority_queue,考虑到你正在寻找的是具有更高优先级的元素,这是有道理的。
#include <queue>
int main(){
priority_queue<int> q;
int a[] = {7, 12, 11, 19, 88, 42, 3, 1, 22};
for(int i=0;i<sizeof(a)/sizeof(int);i++){
q.push(a[i]);
}
for(int i=0;i<5;i++){
cout<<q.top()<<endl;
q.pop();
}
return 0;
}
请注意,priority_queue内部实现为堆,pop_heap以对数时间运行