简体   繁体   English

在递归插入排序中获取分段错误

[英]Getting segmentation fault in recursive insertion sort

I was trying to write recursive code of insertion sort, but I am getting segmentation fault.我试图编写插入排序的递归代码,但出现分段错误。 Please help me with this.请帮我解决一下这个。

#include <bits/stdc++.h>

using namespace std;

void insert(vector<int> &v,int temp){
    if(v.size()==0||v[v.size()-1]<=temp){
        v.push_back(temp);
        return;
    }
    int val = v[v.size()-1];
    v.pop_back();
    insert(v, temp);
    v.push_back(val);
    return;
}

void sort(vector<int> &v){
    if(v.size()==1) return;
    int temp = v[v.size()-1];
    v.pop_back();
    sort(v);
    insert(v,temp);
}

int main() {
    int n;
    vector<int> v;
    cin>>n;
    for(int i=0;i<n;i++)
    cin>>v[i];
    sort(v);
    for(int i=0;i<n;i++)
    cout<<v[i];
    return 0;
}

The problem is that the vector v is empty (meaning it has size 0 ) and you're trying to access its elements which leads to undefined behavior .问题是向量v的(意味着它的大小0 )并且您试图访问它的元素导致未定义的行为

vector<int> v; //this creates an empty vector named v
cin>>n;
for(int i=0;i<n;i++)
cin>>v[i]; //this leads to undefined behavior

In the above snippet, the vector v is an empty vector meaning it has no elements.在上面的代码片段中,向量v是一个空向量,意味着它没有元素。 So the expression cin >> v[i] , leads to undefined behavior because you're accessing elements at i th index of the vector but there are no elements inside the vector to access.所以表达式cin >> v[i]会导致未定义的行为,因为您正在访问向量的第i个索引处的元素,但向量中没有要访问的元素。

Undefined behavior means anything 1 can happen including but not limited to the program giving your expected output. But never rely (or make conclusions based) on the output of a program that has undefined behavior.未定义的行为意味着任何事情1都可能发生,包括但不限于给出您预期的 output 的程序。但永远不要依赖(或根据)具有未定义行为的程序的 output。

So the output that you're seeing(maybe seeing) is a result of undefined behavior.因此,您看到(可能看到)的 output 是未定义行为的结果。 And as i said don't rely on the output of a program that has UB.正如我所说,不要依赖具有 UB 的程序的 output The program may just crash(which is what happens in your case).该程序可能会崩溃(这就是您的情况)。

So the first step to make the program correct would be to remove UB.因此,使程序正确的第一步是删除 UB。 Then and only then you can start reasoning about the output of the program.只有这样你才能开始对程序的 output 进行推理。

Solution解决方案

To solve this you can specify the size of the vector when creating it as shown below:解决这个问题,您可以在创建矢量时指定矢量的大小,如下所示:

int n;
cin>>n;
vector<int> v(n);//create vector of size n

1 For a more technically accurate definition of undefined behavior see this where it is mentioned that: there are no restrictions on the behavior of the program . 1有关未定义行为的更技术准确的定义,请参阅此处提到的内容: There are no restrictions on the behavior of the program

This creates an empty vector<int> :这将创建一个空的vector<int>

vector<int> v;

Accessing any elements in it will make your program have undefined behavior .访问其中的任何元素将使您的程序具有未定义的行为 You can instead create the vector<int> with the number of elements you want by supplying n to the constructor, or by calling resize(n) after creating an empty vector<int> .您可以通过向构造函数提供n或在创建空 vector<int> 后调用resize(n)来创建具有所需元素数的vector<int> vector<int> Another option is to create it empty, and then to push_back() oremplace_back elements into it in which case it'll grow dynamically.另一种选择是将其创建为空,然后将push_back()emplace_back元素放入其中,在这种情况下它将动态增长。

Example creating it with the correct number of elements:使用正确数量的元素创建它的示例:

int main() {
    int n;

    // verify that extraction of `n` succeeded and that `n > 0`:
    if(!(std::cin >> n && n > 0)) {
        std::cerr << "error\n";
        return 1;
    }

    // create the vector with the correct number of elements
    std::vector<int> v(static_cast<size_t>(n));

    // use a range-based for loop to get a reference to each element:
    for(int& val : v)
        std::cin >> val;    // extract into the referenced `int`

    sort(v);

    // here you can use a range-based for loop to get a copy of each element
    // (which is cheap in this case, since they are `int`s):
    for(int val : v)
       std::cout << val << ' ';
    std::cout << '\n';
}

Demo演示

Notes:笔记:

  • #include <bits/stdc++.h> - Never include this non-standard header. Include the standard headers, like iostream and vector #include <bits/stdc++.h> - 永远不要包含这个非标准的 header。包含标准的头文件,比如iostreamvector

  • using namespace std; - Don't do this. - 不要这样做。 Especially not when you provide overloads for functions like sort that will be available if you include bits/stdc++.h and do using namespace std;尤其是当您为sort等函数提供重载时,如果您包含bits/stdc++.h并执行using namespace std; . .

You declared an empty vector你声明了一个空向量

int n;
vector<int> v;

So using the subscript operator in this for loop所以在这个 for 循环中使用下标运算符

for(int i=0;i<n;i++)
cin>>v[i];

invokes undefined behavior.调用未定义的行为。

Instead you could either initially declare the vector with n elements after the value of n was entered as for example相反,您可以在输入n的值后最初声明包含n元素的向量,例如

int n;
cin>>n;
vector<int> v( n );
for(int i=0;i<n;i++)
cin>>v[i];

Or you could resize the vector after the value of n becomes known like或者你可以在n的值变得已知之后调整向量的大小

int n;
vector<int> v;
cin>>n;
v.resize( n );
for(int i=0;i<n;i++)
cin>>v[i];

At it would be better to declare the variable n as having an unsigned integer type as for example最好将变量 n 声明为具有无符号 integer 类型,例如

size_t n;

Instead of the for loop you can use the range based for loop您可以使用基于范围的 for 循环代替 for 循环

size_t n = 0;
cin>>n;

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

for ( auto &item : v ) std;:cin >> item;

Within the function sort you need to change the condition in the if statement at least the following way在 function sort中,您需要至少按以下方式更改 if 语句中的条件

void sort( std::vector<int> &v ){
    if ( v.size() < 2 ) return;
    //...

because in general the user can pass an empty vector.因为通常用户可以传递一个空向量。

Instead of using expressions like this v[v.size()-1] you could use the member function back .您可以使用成员 function back而不是使用像v[v.size()-1]这样的表达式。 For example例如

int temp = v.back();

that makes the code more readable.这使代码更具可读性。

I would define the functions the following way without redundant return statements我将按以下方式定义函数,而无需多余的 return 语句

void insert( std::vector<int> &v, int value )
{
    if (v.empty() || not( value < v.back() ) )
    {
        v.push_back( value );
    }
    else
    {
        int tmp = v.back();
        v.pop_back();
        insert( v, value );
        v.push_back( tmp );
    }
}

void sort( std::vector<int> &v )
{
    if (not ( v.size() < 2 ))
    {
        int last = v.back();
        v.pop_back();
        sort( v );
        insert( v, last );
    }
}

Here is a demonstration program.这是一个演示程序。

#include <iostream>
#include <vector>

void insert( std::vector<int> &v, int value )
{
    if (v.empty() || not( value < v.back() ) )
    {
        v.push_back( value );
    }
    else
    {
        int tmp = v.back();
        v.pop_back();
        insert( v, value );
        v.push_back( tmp );
    }
}

void sort( std::vector<int> &v )
{
    if (not ( v.size() < 2 ))
    {
        int last = v.back();
        v.pop_back();
        sort( v );
        insert( v, last );
    }
}

int main()
{
    std::vector<int> v = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
    sort( v );

    for (const auto &item : v)
    {
        std::cout << item << ' ';
    }
    std::cout << '\n';
}

The program output is程序 output 是

0 1 2 3 4 5 6 7 8 9

And advice: try to avoid the using directive和建议:尽量避免使用指令

using namespace std;

it can be a reason of name collisions and sometimes makes the code unclear that is whether there is used a standard C++ function or a user defined function.这可能是名称冲突的原因,有时会使代码不清楚是使用标准 C++ function 还是用户定义的 function。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM