简体   繁体   中英

Quicksort Algorithm giving segmentation fault error

I'm trying to create a program that takes a vector with 5 elements and sorts them according to their distances (what "distance" means is besides the point here).

But it gives me the " segmentation fault " error everytime I execute it:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct 
{
char ID[8];
char Content[4];
int distance;

} DATA;


void sort(DATA *z, int l){

DATA p; //pivot
DATA t;
int aux=(l-1); //pivot's position
int i,j;

p.distance=z[l-1].distance;


if(l==1){return;}

for(i=0; i<l; i++){

    if((z[i].distance)<(p.distance)){

        continue;
    }


    if((z[i].distance)>(p.distance)){

        t=z[i];

            for(j=i; j<aux; j++){

                z[j]=z[j+1];

            }

            z[aux]=t;
            aux--;
    }

}


sort(z,aux-1);
sort(&z[aux+1],l-aux);

}

int main(){

DATA *z;
int l=5;
int i;

z=(DATA*)malloc(5*sizeof(DATA));

z[0].distance=5;
z[1].distance=1;
z[2].distance=4;
z[3].distance=3;
z[4].distance=2;

sort(z,l);

for(i=0; i<5; i++){

    printf("%d\n",z[i].distance);
}

free(z);

}

I don't see where the problem might be. Please help if you can.

You're calling sort recursively without checking what the value of the second argument is. Executing your code with gdb produced this output:

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400661 in sort (z=0x602010, l=-513) at main.c:21
21  p.distance=z[l-1].distance;
(gdb) bt
#0  0x0000000000400661 in sort (z=0x602010, l=-513) at main.c:21
#1  0x000000000040077c in sort (z=0x602010, l=-511) at main.c:51
#2  0x000000000040077c in sort (z=0x602010, l=-509) at main.c:51
#3  0x000000000040077c in sort (z=0x602010, l=-507) at main.c:51
#4  0x000000000040077c in sort (z=0x602010, l=-505) at main.c:51
#5  0x000000000040077c in sort (z=0x602010, l=-503) at main.c:51
#6  0x000000000040077c in sort (z=0x602010, l=-501) at main.c:51
#7  0x000000000040077c in sort (z=0x602010, l=-499) at main.c:51
#8  0x000000000040077c in sort (z=0x602010, l=-497) at main.c:51
#9  0x000000000040077c in sort (z=0x602010, l=-495) at main.c:51
#10 0x000000000040077c in sort (z=0x602010, l=-493) at main.c:51
#11 0x000000000040077c in sort (z=0x602010, l=-491) at main.c:51
#12 0x000000000040077c in sort (z=0x602010, l=-489) at main.c:51
#13 0x000000000040077c in sort (z=0x602010, l=-487) at main.c:51
#14 0x000000000040077c in sort (z=0x602010, l=-485) at main.c:51
#15 0x000000000040077c in sort (z=0x602010, l=-483) at main.c:51
#16 0x000000000040077c in sort (z=0x602010, l=-481) at main.c:51
#17 0x000000000040077c in sort (z=0x602010, l=-479) at main.c:51
#18 0x000000000040077c in sort (z=0x602010, l=-477) at main.c:51
#19 0x000000000040077c in sort (z=0x602010, l=-475) at main.c:51
#20 0x000000000040077c in sort (z=0x602010, l=-473) at main.c:51
#21 0x000000000040077c in sort (z=0x602010, l=-471) at main.c:51
#22 0x000000000040077c in sort (z=0x602010, l=-469) at main.c:51

You can compile your code with debug symbols like this gcc -g main.c Then execute it with gdb gdb a.out After it loads just type run to run it and you will see the segmentation fault. Type bt for the back trace.

This line looks suspicious

sort(&z[aux+1],l-aux);

l is the length, aux +1 the new base index, so the new length should be l - aux -1

However as others have said, you need to debug / put in diagnostic printfs. It's hard to debug a function like that ion screen.

As has been pointed out by several comments , you could use gdb to find the location of the Segmentation Fault . I did that on your original code , and found that it breaks at line

p.distance=z[l-1].distance;  // statement 1

As pointed out by Malcolm , it happens because you are not passing in the the length of the arrays correctly in your recursive calls to sort function.The correct recursive calls should be (remember c arrays are zero-based)

sort(z,aux); // left half of the array , excluding the pivot
sort(&z[aux+1],l-aux-1); // right half of the array.

Furthermore the statement 1 should ideally be placed after you check ,

if(l <= 1){return;}

Notice , how I changed the comparison from l == 1 to l <= 1 as you also have to check the case for l = 0 .Even after these changes , your loop for traversing the array , had some problems , which I tried to fix as best as I could while maintaining the original code structure. This is the code

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct 
{
char ID[8];
char Content[4];
int distance;

} DATA;


void sort(DATA *z, int l){

DATA p; //pivot
DATA t;
int aux=(l-1); //pivot's position
int i,j;




if(l <= 1){return;}
p.distance=z[l-1].distance;
for(i=0; i<l; i++){

if(i >= aux)
    break; // to avoid going over the right of pivot unnecessarily
if((z[i].distance)<(p.distance)){

    continue;
}


if((z[i].distance)>(p.distance)){

    t=z[i];

        for(j=i; j<aux; j++){

            z[j]=z[j+1];

        }

        z[aux]=t;
        aux--;
        i--; // You have changed the array and brought in a new element , 
       //and you should consider it too for comparison with pivot. 
}

}


sort(z,aux); // left half of the array , excluding the pivot
sort(&z[aux+1],l-aux-1); // right half of the array.

}

int main(){

DATA *z;
int l=5;
int i;

z=(DATA*)malloc(5*sizeof(DATA));

z[0].distance=5;
z[1].distance=1;
z[2].distance=4;
z[3].distance=3;
z[4].distance=2;

sort(z,l);

for(i=0; i<5; i++){

printf("%d\n",z[i].distance);
}

free(z);

}

But I would suggest that you consider writing the traversal loop differently as right now its moving around too many elements and is in fact O(n^2). While using quicksort the desired behavior is that it be O(n) . I recommend looking up the algorithm in a good book like CLRS algorithm book.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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