我编写了一个C ++程序,目的是快速将元素插入到排序向量中。它有时有效,但不是所有的时间,我无法弄清楚为什么。当我用纸和笔来跟踪算法时,它可以解决问题。请帮帮忙?
#include <time.h>
#include <cstdlib>
#include <vector>
#include <iostream>
using namespace std;
vector<int> sortedVec;
int main() {
// Random seed
srand(time(NULL));
// Put in n random elements
for (int i = 0; i < 10; i++) sortedVec.push_back(rand()%10);
// Sort the vector
bool swapped = true;
int endDecrement = 0;
while (swapped) {
swapped = false;
endDecrement++;
for (int i = 0; i < sortedVec.size()-endDecrement; i++) {
if (sortedVec.at(i) > sortedVec.at(i+1)) {
int swap = sortedVec.at(i);
sortedVec.at(i) = sortedVec.at(i+1);
sortedVec.at(i+1) = swap;
swapped = true;
}
}
}
cout<<"Sorted random list:"<<endl;
for (int i = 0; i < sortedVec.size(); i++) cout<<sortedVec.at(i)<<endl;
int toInsert = rand()%10;
cout<<"Random element to insert = "<<toInsert<<endl;
// Insert a random int to the sorted vector
int minIndex = 0;
int maxIndex = sortedVec.size()-1;
while (true) {
int mid = (maxIndex-minIndex)>>1;
if (toInsert == sortedVec.at(mid) || maxIndex-minIndex < 2) {
sortedVec.insert(sortedVec.begin()+mid, toInsert);
break;
}
else if (toInsert < sortedVec.at(mid)) maxIndex = mid;
else if (toInsert > sortedVec.at(mid)) minIndex = mid;
}
cout<<"Random list with inserted element:"<<endl;
for (int i = 0; i < sortedVec.size(); i++) cout<<sortedVec.at(i)<<endl;
return 0;
}
答案 0 :(得分:2)
正如评论所指出的那样,你提出的建议是解决基本问题的一种相当复杂的方法。
在随机生成器初始化中使用一个常量来替换time(NULL)
可以使您的问题变得更具吸引力,该常量可以使观察到的行为进行调试。
如果没有这个,我会对罪魁祸首:
int maxIndex = sortedVec.size()-1;
我认为应该是
int maxIndex = sortedVec.size();
或者你永远不会考虑顶级元素。
答案 1 :(得分:1)
标准库中有一些用于排序的工具:
#include <algorithm>
#include <vector>
template <typename T, typename A, typename C>
class SortedVector {
public:
SortedVector() {}
// Initialization
template <typename It>
SortedVector(It begin, It end): _data(begin, end) {
std::sort(_data.begin(), _data.end(), _comparator);
// if we wanted unicity
_data.erase(std::unique(_data.begin(), _data.end(), _comparator), _data.end());
}
// Addition of element (without checking for unicity)
void add(T const& element) {
_data.push_back(element);
std::inplace_merge(_data.begin(), prev(_data.end()), _data.end(), _comparator);
// or simply: std::sort(_data.begin(), _data.end(), _comparator);
// it is surprisingly efficient actually because most sort implementations
// account for partially sorted range. It is not, however, stable.
}
// Addition of element with unicity check
bool add(T const& element) {
typename std::vector<T, A>::iterator it =
std::lower_bound(_data.begin(), _data.end(), element, _comparator);
if (it != _data.end() and not _comparator(element, *it)) {
return false;
}
size_t const n = it - _data.begin();
_data.push_back(element);
std::copy(_data.begin() + n, _data.end() - 1, _data.begin() + n + 1);
// C++11: std::move
_data[n] = element;
}
private:
std::vector<T, A> _data;
C _comparator;
};
答案 2 :(得分:1)
根据评论,我们假设我们的结构类似于:
struct data {
int fval;
// other stuff we don't care about right now
};
而且,我们假设我们有一个这样的矢量:
std::vector<data> items;
如果我们想按顺序将新项目插入到向量中,我们不真的想要进行二进制搜索,然后是std::insert
。这需要O(log N)搜索,然后插入O(N)。相反,我们可以将两者结合起来,所以我们只需要一个O(N)操作来找到正确的位置并进行插入。这是一个简单的版本:
void insert(std::vector<int> &vec, int new_val) {
if (vec.empty()) {
vec.push_back(new_val);
return;
}
vec.resize(vec.size()+1);
std::vector<int>::reverse_iterator pos = vec.rbegin();
for ( ; *(pos+1) > new_val && (pos+1) != vec.rend(); ++pos)
*pos = *(pos+1);
*pos = new_val;
}
在您的情况下,您希望插入data
结构,并比较(pos+1)->fval > new_val.fval
,但基本思路基本相同。实际上,这个应该可能是作为通用算法实现的,但我现在没有时间。
答案 3 :(得分:0)
我写了一个C ++程序,目的是快速将元素插入到排序的向量中
你不应该这样做。 std :: vector不适合快速插入自定义位置。 编辑:BTW你正在做替换,而不是插入。因为矢量的使用是可以的。
此外,您的代码也没有使用标准功能。 std :: sort,如果你真的想手动交换元素,你也有std :: swap。
这也是不必要的:
int mid = (maxIndex-minIndex)>>1;
编译器可以轻松优化/ 2到&gt;&gt; 1;
修改强>
您的代码已损坏,希望能告诉您原因: http://ideone.com/pV5oW
答案 4 :(得分:0)
我改变了它,我很确定它现在适用于所有情况:
if (toInsert < sortedVec.at(0)) sortedVec.insert(sortedVec.begin(), toInsert);
else if (toInsert > sortedVec.at(sortedVec.size()-1)) sortedVec.push_back(toInsert);
else {
int minIndex = 0;
int maxIndex = sortedVec.size();
while (true) {
int mid = (maxIndex+minIndex)>>1;
if (toInsert == sortedVec.at(mid) || maxIndex-minIndex < 2) {
sortedVec.insert(sortedVec.begin()+mid+1, toInsert);
break;
}
else if (toInsert < sortedVec.at(mid)) maxIndex = mid;
else if (toInsert > sortedVec.at(mid)) minIndex = mid;
}
}
@LeGEC和@chac,感谢您查看我发布的算法,它帮助了很多。 @Jerry Coffin,我确实让std :: upper_bound为此工作但不是我的Node类的变量,不过也谢谢你。