我有一个大约有200 000个项目的数据库,按用户名排序。现在,当我将一个项添加到数组的末尾并调用我的快速排序函数来对该数组进行排序时,几乎需要一秒的时间进行排序,这是不可接受的。肯定有一些可以做的优化。例如,如果我按顺序将每个字符串从n-1比较为0,然后相应地移动项目,则性能会更高。
其他想法是我可以执行从0到n-1的二进制搜索,而不是infact搜索,但类似于利用我已经排序的数组。但是我没有编写一个能够返回索引的正确函数,我的新元素应放在该函数中。
void quick_sort(int left, int right)
{
int i = left, j = right;
if (left >= right) return;
char pivotC[128];
DataEntry *tmp;
strcpy_a(pivotC, sizeof pivotC, User[(left + right) / 2]->username);
while (i <= j)
{
while (StringCompare(User[i]->username, pivotC))
i++;
while (StringCompare(pivotC, User[j]->username))
j--;
if (i <= j)
{
tmp = User[i];
User[i] = User[j];
User[j] = tmp;
i++;
j--;
}
}
if (left < j)
quick_sort(left, j);
if (i < right)
quick_sort(i, right);
}
非常感谢任何帮助。
答案 0 :(得分:5)
解决方案是重写代码以使用stl,我不明白为什么人们用C ++编写C代码。
您需要一个用户
的向量std::vector<User> users;
//then you can keep it ordered at each insertion
auto it = upper_bound(users.begin(), users.end(), user_to_insert,
[](auto& lhs, auto& rhs ) { /* implementation left to the reader */});
users.insert(it, user_to_insert);
您现在可以以更好,更干净的方式使用相同的功能
答案 1 :(得分:1)
简单,直接的方法导致二进制搜索太主流了。只需要几行:
int where_to_add(int array[], int element)
{
int i;
for (i = length; i >= 0 && array[i-1] > element; i--);
return i;
}
如果这是您正在寻找的答案,请告诉我
答案 2 :(得分:1)
如果你想学习如何编码二进制搜索,重新发明轮子是好的,否则重用是更好的。
std::lower_bound
对已排序的范围[first, last)
执行二进制搜索,如果已存在,则将迭代器返回到搜索的元素x
;否则迭代器将指向大于x
的第一个元素。自标准容器&#39;暴露insert
将在迭代器之前插入,这个迭代器可以原样使用。这是一个简单的例子。
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
int main()
{
std::list<int> data = { 1, 5, 7, 8, 12, 34, 52 };
auto loc = std::lower_bound(data.begin(), data.end(), 10);
// you may insert 10 here using loc
std::cout << *loc << '\n';
loc = std::lower_bound(data.begin(), data.end(), 12);
// you may skip inserting 12 since it is in the list (OR)
// insert it if you need to; it'd go before the current 12
std::cout << *loc << '\n';
}
12
12
答案 3 :(得分:1)
二进制搜索的兴趣有限,因为无论如何都需要插入,这将是一个耗时的操作(O(N))。所以你第一次想到线性搜索然后插入就足够了;你可以在一个向后循环中组合。 (这是StraightInsertionSort的一个步骤。)
处理动态排序列表的真正有效方法是维护平衡树或使用哈希表。
答案 4 :(得分:0)
你可以这样做二进制搜索。这里你可以假设如果val是字符串类型,则使用字符串比较函数进行比较,并且int AR []设置为字符串或者您可以将它们映射到整数。由于数组已排序,我认为二进制搜索将为您提供最佳性能。
int bsearch(int AR[], int N, int VAL)
{
int Mid,Lbound=0,Ubound=N-1;
while(Lbound<=Ubound)
{
Mid=(Lbound+Ubound)/2;
if(VAL>AR[Mid])
Lbound=Mid+1;
else if(VAL<AR[Mid])
Ubound=Mid-1;
else
return Mid;
}
return 0;
}
答案 5 :(得分:0)
从我所看到的,您使用C数组来存储您的条目,这意味着每当您尝试插入新条目时,由于您可能需要移动数组中有很多条目。
如果你打算保留一个C数组而不使用某些stl有序容器(虽然主要是考虑std :: map),你可以尝试将C数组拆分成两个数组。一个是第一个包含键的数组和第二个数组元素的索引。你仍然需要对第一个数组进行排序,但它的元素只有两个单词(一个用于键,一个用于索引)而不是包含键和一些值的大块)并且应该更快。插入项目时,在第二个数组的末尾分配并获取索引,将其作为一对与第一个数组内的键插入。如果您打算动态删除元素,那么您可以更聪明一些,但您的问题似乎并未涵盖它。
但即便如此,它可能仍然太慢,所以你应该考虑使用AVL,红黑树,Splay树等std :: map或二进制树等算法,你不需要在物理上移动元素。
答案 6 :(得分:0)
如果您仅使用少量新的不合适的尾随项目对排序列表进行排序,那么您应该利用插入排序实际有效工作的罕见情况。在排序列表上实现插入排序只有少量尾随值可以在O(n)时间内排序。您只是将少数不合适的值插入到位,而快速排序则选择一个支点并完成整个快速排序过程。此外,如果您没有将某种类型的有效枢轴选择过程纳入您的快速排序,并且与前三个项目的平均值相关,那么#34;在已排序的列表上进行处理,您将在O(n ^ 2)时间内进行排序。
答案 7 :(得分:-1)
int add(Container c, int r, int l, Unit t)
{
if(c[r]>t)
return r;
if(c[l]<t)
return l+1;
if(c[r]==c[l])
{
if(c[r]==t)
return -1;
return -1;
}
int m=(r+l)/2;
if(c[m]==t)
return -1;
if(c[m]>t)
return add(c,m,l,t);
if(c[m]<t)
return add(c,r,m,t);
}
它可能会为您提供您需要添加的索引...我希望它可以提供帮助。它假设您不需要在其已经存在时添加。