提问者:小点点

合并排序:分段错误核心转储


我阅读了归并排序算法的基本原理,在此基础上,利用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使用terminal命令编译代码

$ gcc filename.cpp -lstdc++

在分析代码后,我认为问题出在合并函数上,但我无法指出问题出在哪里。 如果有人能帮助我,如果可能的话,建议一些方法来优化我的代码,这将是很有帮助的。


共2个答案

匿名用户

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

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

然后像这样调用mergesort

mergeSort(arr,0,8);

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

现在,在merge_sort中,您可以看到以下内容

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

召回归并排序是对包含范围(begin,last)进行排序。 因此您的递归将对两个包含范围(begin,mid)和(mid,last)进行排序。 换句话说,mid被包含了两次。

既然(非常令人钦佩地)你想自己编写这个程序,我就让你自己去解决这个问题。

匿名用户

除了其他答案之外,您的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++]); }