将元素插入到已排序的向量中

时间:2012-10-05 05:31:20

标签: c++ sorting vector

我编写了一个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;
}

5 个答案:

答案 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类的变量,不过也谢谢你。