【问题标题】:Merge sort logic failure in allocating memory.分配内存时合并排序逻辑失败。
【发布时间】:2016-06-02 21:17:11
【问题描述】:

我正在研究合并排序的实现,它将按歌曲的长度对歌曲列表进行排序。我已经写了以下内容并且无法找出我的逻辑中的缺陷。这些函数不是返回排序列表,而是返回原始列表中间的一项列表。

vector<song> merge( vector<song> firstList, vector<song> secondList){
 vector<song> outPut;
 int i = 0; int n = 0;
 while( outPut.size() < (firstList.size() + secondList.size()-1 )){
    if( firstList[i].length < secondList[n].length){
        outPut.push_back( firstList[i]);
        i++;
    }else{
        outPut.push_back( secondList[n]);
        n++;
    }
 }
return outPut;
}
vector<song> mergeSortLength( vector<song> playlist){
 int scope = playlist.size()/2;
 vector<song> firstHalf( &playlist[0], &playlist[scope]);
 vector<song> secondHalf( &playlist[scope], &playlist[playlist.size()]);
 if ( firstHalf.size() != 1){
    firstHalf = mergeSortLength(firstHalf);
 }
 if ( secondHalf.size() != 1){
    secondHalf = mergeSortLength( secondHalf);
 }
 return merge( firstHalf, secondHalf);
}

如果我改变 while 循环条件

( outPut.size() < (firstList.size() + secondList.size() -1)){ 

( outPut.size() < (firstList.size() + secondList.size())){

列表排序成功到一半,直到编译器吐出:

playList(27898,0x7fff78b7b000) malloc: * mach_vm_map(size=7526769998340063232) 失败(错误代码=3) * 错误:无法分配区域 *** 在 malloc_error_break 中设置断点进行调试 libc++abi.dylib:以 std::bad_alloc 类型的未捕获异常终止:std::bad_alloc 中止陷阱:6

我非常感谢任何人的帮助。我的眼睛因为盯着这个而变得模糊。

【问题讨论】:

  • 比较你的代码和the merge sort implemented here
  • 这里是small test。我建议你拿你在链接上看到的代码,拿你的代码,仔细调试你的代码失败的地方,以及好的例子没有失败的地方。看起来你在模仿std::inplace_merge,但你弄错了。 Here is another link 举个例子。
  • 感谢您的提示。我会比较一下,如果有帮助,我会告诉你。
  • 有什么理由不只实现 song::operator

标签: c++ sorting logic mergesort


【解决方案1】:

在merge()中,代码不会检查是否已经到达向量的末尾,特别是如果i >= firstList.size()或n >= secondList.size(),在这种情况下另一个向量的其余部分将被复制。 while 语句的末尾不应有 -1。

VS 抱怨使用 &playlist[playlist.size()] 创建临时向量,因为下标超出范围。一个可选的方法是使用 begin() + index,它是一个迭代器:

    vector<song> firstHalf( playlist.begin()+0, playlist.begin()+scope);
    vector<song> secondHalf( playlist.begin()+scope, 
                 playlist.begin()+playlist.size());

已经过了一天,所以发布一个固定版本以防万一有人感兴趣。所有这些向量的创建和推回都会增加很多开销,最好进行一次分配,然后只使用迭代器或索引来处理子向量。

vector<song> merge( vector<song> firstList, vector<song> secondList){
    vector<song> outPut;
    size_t i = 0; size_t n = 0;
    while( outPut.size() < (firstList.size() + secondList.size()) ){
        if( firstList[i].length < secondList[n].length){
            outPut.push_back( firstList[i]);
            if(++i >= firstList.size()){
                do
                    outPut.push_back( secondList[n]);
                while(++n < secondList.size());
                break;
            }
        }else{
            outPut.push_back( secondList[n]);
            if(++n >= secondList.size()){
                do
                    outPut.push_back( firstList[i]);
                while(++i < firstList.size());
                break;
            }
        }
    }
    return outPut;
}

vector<song> mergeSortLength( vector<song> playlist){
    size_t scope = playlist.size()/2;
    vector<song> firstHalf( playlist.begin()+0, playlist.begin()+scope);
    vector<song> secondHalf( playlist.begin()+scope, playlist.begin()+playlist.size());
    if ( firstHalf.size() != 1){
        firstHalf = mergeSortLength(firstHalf);
    }
    if ( secondHalf.size() != 1){
        secondHalf = mergeSortLength( secondHalf);
    }
    return merge( firstHalf, secondHalf);
}

【讨论】:

  • 你说的完全正确!谢谢你。这向我解释了很多,我非常感谢你的透彻。
【解决方案2】:

我没有看到很多关注,但也许你想要

vector<song> secondHalf( &playlist[scope+1], &playlist[playlist.size()-1]);

我认为没有 -1 的 &playlist[playlist.size()] 是你问题的根源, 但我没试过。

【讨论】:

  • -1 避免了 malloc 错误,因为它阻止我访问超过向量末尾的内存。缺点是 firstList 和/或 secondList 的大小为 1。这会导致函数返回一个元素的列表。公平地说,该列表已排序。请参阅 rcgldr 的评论,谁真正完成了繁重的工作。
猜你喜欢
  • 2015-12-18
  • 2021-12-23
  • 1970-01-01
  • 1970-01-01
  • 2013-06-16
  • 2019-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多