MergeSort为双打矢量

时间:2014-10-20 06:37:12

标签: c++ data-structures vector

我正在尝试为包含double值的向量实现MergeSort算法。我有以下代码。但是,在我的输入中,两个值被视为零并且不合适。有人能告诉我哪里出错了吗?

P.S:我是数据结构的新手,所以我不知道在这里正确使用iterator

代码

#include <iostream>
#include <vector>
void sort(std::vector<double> vec);
std::vector<double> merge(std::vector<double> left, std::vector<double> right, int len);
std::vector<double> mergeSort(std::vector<double> vec, int len);
void sort(std::vector<double> vec) {
    std::vector<double> tmp = mergeSort(vec, vec.size());
    for (unsigned int i = 0; i < vec.size(); i++){
        vec[i] = tmp[i];
        std::cout << vec[i] << " ";
    }
}

std::vector<double> merge(std::vector<double> left, std::vector<double> right, int len){
    std::vector<double> ret(len + len);
    int left_position = 0;
    int right_position = 0;
    int ret_position = 0;
    while (left_position < len && right_position < len){
        double left_value = left[left_position];
        double right_value = right[right_position];
        if (left_value < right_value){
            ret.insert((ret.begin() + ret_position), left_value);
            //ret[ret_position] = left_value;
            ret_position++;
            left_position++;
        }
        else {
            ret.insert((ret.begin() + ret_position), right_value);
            ret_position++;
            right_position++;
        }
    }
    while (left_position < len){
        ret.insert((ret.begin() + ret_position), left[left_position]);
        ret_position++;
        left_position++;
    }
    while (right_position < len){
        ret.insert((ret.begin() + ret_position), right[right_position]);
        ret_position++;
        right_position++;
    }
    return ret;
}

std::vector<double> mergeSort(std::vector<double> vec, int len){
    if (len == 1){
        return vec;
    }
    int middle = len / 2;
    std::vector<double> left(middle);
    std::vector<double> right(middle);
    for (int i = 0; i < middle; i++){
        left.insert((left.begin() + i), vec[i]);
    }
    for (int j = 0; j < middle; j++){
        right.insert((right.begin() + j), vec[j + middle]);
    }
    left = mergeSort(left, middle);
    right = mergeSort(right, middle);
    std::vector<double> ret = merge(left, right, middle);
    return ret;
}

int main(){
    std::vector<double> vec;
    vec.push_back(7.04);
    vec.push_back(8.04);
    vec.push_back(6.04);
    vec.push_back(9.04);
    vec.push_back(1.04);
    vec.push_back(3.04);
    vec.push_back(5.04);
    vec.push_back(2.04);
    vec.push_back(10.04);
    vec.push_back(4.04);
    vec.push_back(12.04);
    vec.push_back(11.04);
    sort(vec);
    return 0;
}

输出为:1.04 2.04 4.04 5.04 0 7.04 8.04 0 9.04 0 12.04 0这很奇怪。 (请注意,输入中的每个第三元素都被视为0)

直播:http://ideone.com/fHZzZf

2 个答案:

答案 0 :(得分:1)

我已更正您的代码。

  1. 第一个问题是,正如 UmNyobe 所说的那样,在计算时会失去元素

    int middle = len / 2;  
    
  2. 使用构造函数时

    std::vector<int>(size_type n);
    

    构造一个包含n个元素0.0
    的vecror  关于vector的构造函数的更多信息请阅读here

  3. 使用时

    vec.insert(iterator pos, const value_type& val);
    

    你在位置pos之前插入一个新元素,并且增加向量的大小为1 在合并排序中,我建议您创建一个包含一些元素的向量,然后将它们分配给适当的值 例如,您可以在下面的代码中看到:

    std::vector<double> ret(left.size() + right.size(), -1); // construct vector with left.size() + right.size() elements assigned to -1
    int left_position = 0;
    int right_position = 0;
    int ret_position = 0;
    while (left_position < left.size() && right_position < right.size()) {
        double left_value = left[left_position];
        double right_value = right[right_position];
        if (left_value < right_value) {
            ret[ret_position++] =  left_value;
            left_position++;
        } else {
            ret[ret_position++] = right_value;
            right_position++;
        }
    }
    
  4. 更正后的代码:

    #include <iostream>
    #include <vector>
    std::vector<double> merge(std::vector<double> left, std::vector<double> right);
    std::vector<double> mergeSort(std::vector<double> vec);
    
    void sort(std::vector<double>& vec) { // using reference here std::vector<double>& - to be able to change vector inside function
        vec = mergeSort(vec);
        for (unsigned int i = 0; i < vec.size(); i++){
            std::cout << vec[i] << " ";
        }
    }
    
    std::vector<double> merge(std::vector<double> left, std::vector<double> right) {
        std::vector<double> ret(left.size() + right.size(), -1); // construct vector with left.size() + right.size() elements assigned to -1
        int left_position = 0;
        int right_position = 0;
        int ret_position = 0;
        while (left_position < left.size() && right_position < right.size()) {
            double left_value = left[left_position];
            double right_value = right[right_position];
            if (left_value < right_value) {
                ret[ret_position++] =  left_value;
                left_position++;
            } else {
                ret[ret_position++] = right_value;
                right_position++;
            }
        }
        while (left_position < left.size()) {
            ret[ret_position++] = left[left_position++];
        }
        while (right_position < right.size()) {
            ret[ret_position++] = right[right_position++];
        }
        return ret;
    }
    
    std::vector<double> mergeSort(std::vector<double> vec){
        if (vec.size() < 2){
            return vec;
        }
        int middle = vec.size() / 2;
        std::vector<double> left(vec.begin(), vec.begin() + middle);
        std::vector<double> right(vec.begin() + middle, vec.end());
    
        left = mergeSort(left);
        right = mergeSort(right);
        std::vector<double> ret = merge(left, right);
        return ret;
    }
    
    int main(){
        std::vector<double> vec;
        vec.push_back(7.04);
        vec.push_back(8.04);
        vec.push_back(6.04);
        vec.push_back(9.04);
        vec.push_back(1.04);
        vec.push_back(3.04);
        vec.push_back(5.04);
        vec.push_back(2.04);
        vec.push_back(10.04);
        vec.push_back(4.04);
        vec.push_back(12.04);
        vec.push_back(11.04);
        sort(vec);
        return 0;
    }
    

    现在输出

      

    1.04 2.04 3.04 4.04 5.04 6.04 7.04 8.04 9.04 10.04 11.04 12.04

    您应该仔细阅读 vector 类的方法 这是一个关于c ++的好网站:http://www.cplusplus.com/reference/vector/vector/

答案 1 :(得分:0)

将原始集分成leftright子集时,您忘记了元素。

int middle = len / 2;
for (int i = 0; i < middle; i++){
    ...
}
for (int j = 0; j < middle; j++){
   ...
}

如果len很奇怪,您将获得2*middle = len -1。您可以更改为

for (int j = 0; j < len - middle; j++){
   ...
}

修改 您的整个程序基于左侧和右侧长度相等的事实。这意味着只有当输入向量的长度是2的幂时它才是正确的。 你需要重新考虑你的函数,假设左右大小不同

处理向量时,你真的需要传递一个长度参数吗?例如

 std::vector<double> ret(len + len);
合并功能中的

可以是

std::vector<double> ret(left.size() + right.size());