Visual 3-way归并排序stackoverflow错误

visual 3-way mergesort stackoverflow error in c++

本文关键字:错误 stackoverflow 归并排序 3-way Visual      更新时间:2023-10-16

嗨,伙计们,谁能告诉我我的3-way合并排序代码有什么问题?我写的代码只能排序4个数字,如果你给它超过4个数字(通过改变大小),它最终与堆栈溢出错误,这是代码:

#include "stdafx.h"
#include <iostream>
#include <vector>
using namespace std;
const int size=4;
vector <int> s(size);
void merge(int,int,int);
void mergesort(int,int);
int main(){
    for(int i=0;i<size;i++){
        cout<<"enter number "<<i+1<<":";
        cin>>s.at(i);
    }
    system("CLS");
    cout<<"here are the unsorted numbers:n";//prints the input values so U can see'em
    for(int j=0;j<size;j++)
        cout<<s.at(j)<<".";
    mergesort(0,size-1);//calls mergesort
    cout<<"nhere are the sorted numbers:n";
    for(int j=0;j<size;j++)
        cout<<s.at(j)<<".";
    cin.get();
    cin.get();
    return 0;
}
void merge(int low,int one_third,int high){
    int i=low;
    int j=one_third+1;
    int k=0;
    int length=(high-low)+1;
    vector <int> u(length,0);
    if(k<length){
        while((i<=one_third)&&(j<=high)){
            if(s.at(i)<=s.at(j)){
                u.at(k)=s.at(i);
                i++;
                k++;
            }//end for
            else{
                u.at(k)=s.at(j);
                j++;
                k++;
            }//end elseif
        }//end while
        if(j>high)
            while(i<=one_third)
            {
                u.at(k)=s.at(i);
                i++;
                k++;
            }
        if(i>one_third)
            while(j<=high)
            {
                u.at(k)=s.at(j);
                j++;
                k++;
            }
        for(int n=low;n<k;n++)
            s.at(n)=u.at(n);
    }
}//end if
void mergesort(int low,int high){
    if(low<high){
        int one_third=(high-low)/3;//division,it's 3-way mergesort so obviously it's divided by 3
        int two_third=2*one_third;
        mergesort(low,one_third);
        mergesort(one_third+1,two_third);
        mergesort(two_third+1,high);
        merge(low,one_third,two_third);
        merge(low,two_third,high);
    }//end if
}
在这一点上,我想我已经完成了思考,任何答案/想法将不胜感激。

下面是对代码的部分检查。我相信有一个问题调试3路合并排序与4个值。您应该使用更多的值,例如6或7。


我猜测缩进是因为您在代码中使用制表符并直接粘贴。在下一篇文章中,你会想要展开标签。

预编译头文件
你的项目很大吗?当您更改头文件或修改源代码时,它是否显著减少了构建时间?

我发现stdafx通常更麻烦,解决它所导致的缺陷所花费的时间抵消了预编译头文件所带来的任何潜在节省。

函数原型应该使用命名参数
您能告诉我mergemergeSort申报中不同参数的用途吗?
模棱两可会滋生缺陷。足够地说。

Main函数声明错误
main函数总是返回一个int给操作系统,总是。操作系统可以忽略它。

这个机制是为了让脚本文件可以执行你的程序并测试错误。

可读性防止缺陷
投资于运营商周围的空间。牺牲空间所节省的时间可以忽略不计。易于阅读的代码节省了大量的调试时间,特别是当其他人审查或检查您的代码时。

使用中间变量
中间变量有助于澄清程序。当您告诉编译器进行优化时,它们不会消耗内存。在调试期间,它们可以帮助在计算期间显示值。

读入vector的典型用法是:

  int value;
  cin >> value;
  s.push_back(value);

at方法可能有溢出问题(或者至少你没有检查越界问题)。push_back方法将导致向量根据需要展开。

有意义的变量名减少了缺陷
变量s没有任何意义。像original_valuesnumber_container这样的东西更具描述性。同样,变量名长度与提高性能无关。可读的名称有助于减少注入的缺陷。

未检查cin状态
如果我在你的第二个提示中输入"Lion",那么数组的第二个槽中是什么?
不要相信用户,他们并不完美。

不要清空屏幕
它可能包含有用的数据,例如输入的实际数字。所以当你在调试的时候,想知道用户实际输入了什么,它将永远丢失。

cin的原因。获得两次?
在没有提示的情况下要求用户输入。和两次。你的程序和用户之间的恶果。

如果您想忽略字符直到接收到特定的字符,请参阅cin.ignore。例如:

  cout << "Paused. Press Enter to continue.n";
  cin.ignore(100000, 'n');  

魔法数字
在函数mergesort中,使用数字2和3。为什么?它们的目的是什么?

<

多余的评论/strong>
大多数程序员都知道数学表达式中的'/'字符是除法。这评论是多余的。

还有,为什么要除以3?这是一个令人讨厌的数字。您是否意识到您正在执行整数除法,您的产品将被截断?例如:1/3 == 2/3 == 0

使用调试器

最后,通过使用调试器可以更容易、更快地验证程序的许多功能。调试器允许您执行语句并查看变量值。您可以设置断点以在不同的位置停止执行。这是一项值得的教育投资,现在就开始吧。

一个"经典的" 3路归并排序一次归并3次,在源数组和目标数组(或向量或列表)之间交替进行。代码需要执行最多3次比较,以便从3次运行中确定3个值中的"最小",然后将相应运行中的最小值移动到目标数组。代码还必须处理在到达运行结束时,只剩下2个运行要合并的情况,然后处理在到达第二次运行结束时,在这种情况下,第三次运行的其余部分被移动到目标数组。

对于基于ram的排序,我不确定这是否比正常的2路合并更快。对于外部排序,有多个设备或非常大的读写,那么k方式合并k到12或16将更快。