【问题标题】:Merge Sort: Segmentation error Core Dumped合并排序:分割错误核心转储
【发布时间】:2020-09-24 18:51:45
【问题描述】:

我阅读了归并排序算法的理论,并在此基础上使用 STL Vector 类在 C++ 中编写了归并排序的实现。

我知道互联网上有关合并排序的数万亿文章中的任何一篇的复制粘贴都可以解决这个问题,但我想自己尝试一下。

当我运行代码时,我得到分段错误核心转储错误,这是由递归函数未终止引起的。 谁能帮我找出代码中的错误。

#include<iostream>
#include<vector>
void merge(std::vector<int>& arr,int last,int begin,int mid);
void mergeSort(std::vector<int>& arr,int begin, int last){ 
    std::cout<<"In merge sort";
    int mid; 
    if(begin<last){
      mid = (begin+last)/2;
      mergeSort(arr,begin,mid);
      mergeSort(arr,mid,last);
      merge(arr,last,begin,mid);
    } 
    return;
}
void merge(std::vector<int>& arr ,int last,int begin,int mid){
    if(last==begin){
        std::cout<<"Returned form finger";
        return; 
    }
    int b=begin,c=mid;
    std::vector<int> temp;
    while(b<mid&&c<last){
        if(arr[b]<arr[c]){
            temp.push_back(arr[b]);
            b++;
        }
        else{
            temp.push_back(arr[c]);
            c++;
        }
    }
    while(b<mid){temp.push_back(arr[b]);}
    while(c<last){temp.push_back(arr[c]);}
    arr.swap(temp);
    return;
}


int main(){
    std::vector<int> arr({2,4,1,5,3,6,2,4,3});   
    for(auto it=arr.begin();it!=arr.end();++it){
        std::cout<<*it<<' '; 
    }
    std::cout<<'\n';
   mergeSort(arr,0,8);
    for(auto it=arr.begin();it!=arr.end();++it){
        std::cout<<*it<<' '; 
    }
    return 0;
    }

我使用 gcc 9.3.0 版本使用终端命令编译代码

$ gcc filename.cpp -lstdc++

分析代码后,我认为问题出在合并函数中,但我无法指出问题出在哪里。如果有人可以帮助我,如果可能的话,我会提供一些优化我的代码的方法。

【问题讨论】:

  • 对不起,但我不得不说“......但我想自己尝试这个。”这就是为什么您要求其他人在您的代码中找到问题。好的:P。您是否已经使用过调试器?
  • 为什么编译时使用gcc而不是g++
  • 你的区间划分错误。如果begin 为0,end 为1,则mid 为0 并递归mergeSort(0,1)
  • 旁注:我们将范围指定为半开区间的一个原因是它使区间划分更容易。
  • 是的,很好,我的评论并不是冒犯,而是建议通过使用调试器将“我自己”更进一步。编写代码只是编程的一小部分,调试至少需要同样多的时间,并且是一项重要的技能

标签: c++ algorithm sorting stdvector


【解决方案1】:

所以你的递归是错误的。在main 中,您有一个包含九个元素的向量。

std::vector<int> arr({2,4,1,5,3,6,2,4,3});

然后你像这样打电话给mergeSort

mergeSort(arr,0,8);

所以mergeSort 的第三个参数是您要排序的向量的最后一个有效索引(使用arr.size() - 1 会更好)。换句话说,mergeSort 是对 inclusive 范围 (0, 8) 进行排序。

现在在merge_sort 你有这个

void mergeSort(std::vector<int>& arr,int begin, int last) { 
    ...
    mergeSort(arr,begin,mid);
    mergeSort(arr,mid,last);
    ...
}

召回归并排序是对包含范围(开始,最后)进行排序。所以你的递归将对两个包含范围(开始,中间)和(中间,最后)进行排序。换句话说,mid 被包含了两次。

既然(非常令人钦佩地)你想自己编程,我会让你找出解决办法。

【讨论】:

    【解决方案2】:

    除了其他答案之外,您的 merge 函数存在严重问题。用于将剩余元素复制到 temp 的代码如下所示:

    while (b < mid) { temp.push_back(arr[b]); }
    while (c < last) { temp.push_back(arr[c]); }
    

    请注意,您永远不会增加 bc 索引。这是一个无限循环,最终将耗尽内存调用push_back。简单的修复是这样的:

    while (b < mid) { temp.push_back(arr[b++]); }
    while (c < last) { temp.push_back(arr[c++]); }
    

    【讨论】:

      猜你喜欢
      • 2017-08-13
      • 1970-01-01
      • 1970-01-01
      • 2015-06-25
      • 2021-06-03
      相关资源
      最近更新 更多