今天自己写了个《算法导论》上的快速排序,出现了stackover flow(栈溢出)的问题,经过排查,成功解决,特来分享,希望能帮到有类似问题的网友。
所谓的栈溢出就是数据越界
代码如下(错误版):
# include
#define SIZE 10
void qsort(int *array, int min, int max);//快速排序
int Partition(int array[], int min, int max);//就地重排
void swap(int *p1, int *p2); //交换
int main(void)
{
int array[SIZE] = { 43, 6, 76, 2, 9, 3, 88, 3, 6, 0 };
qsort(array, 0, SIZE);
for (int k = 0; k < SIZE; k++) //打印输出排序后的数组
printf("%d,", array[k]);
return 0;
}
void swap(int *p1, int *p2){//交换函数
int temp;
temp = *p1;
*p1 = *p2;
*p2 = temp;
}
int Partition(int array[], int min, int max){//就地重排
int i, key;
key = array[min];
i = min - 1;
for (int j = min; j < max; j++){//判断并交换
if (array[j]>key){
i++;
swap(&array[i], &array[j]);
}
}
swap(&array[i++], &key);//把主元放到中间
return i++;
}
void qsort(int *array, int min, int max){//递归
if (min < max){
int i = Partition( array, min, max);
qsort(array, min, i--);
qsort(array, i++, max);
}
}代码如下 (正确版):
# include
# define TSIZE 45
#define SIZE 10
void swap(int *p1, int *p2);
int Partition(int array[], int min, int max);
void qsort(int *array, int min, int max);
int main(void)
{
int array[SIZE] = { 43, 6, 76, 2, 9, 3, 88, 3, 6, 0 };
qsort (array,0,SIZE);
for (int k = 0; k < SIZE; k++)
printf("%d,", array[k]);
return 0;
}
void swap(int *p1, int *p2){//交换
int temp;
temp = *p1;
*p1 = *p2;
*p2 = temp;
}
int Partition(int array[], int min, int max){//重排交换,从大到小
int i, key;
key = array[min]; //指定第一个值为分界线
i = min - 1;
for (int j = min; j < max ; j++){
if (array[j]>key){
i++;
swap(&array[i], &array[j]);
}
}
swap(&array[++i], &key);//修正1
return ++i ;//修正2
}
void qsort(int *array, int min, int max){ //递归调用快排
if (min < max){
int i = Partition( array, min, max);
qsort(array, min, --i);//修正3
qsort(array, ++i, max);//修正4
}
}
在正确版代码中请注意看到我标注的“修正”,那几行就是要改的地方。把i++改成++i,为什么改成这样就可以避免溢出呢?因为
这两者是不一样的,虽然两者都是给i增加1,当写成i++时,程序是先用i的值之后再改变i,而++i则是先改变再用,很多情况下两者是可
以互换(你也可以使用 i = i+1的形式,但是没有人会相信你是一个真正的C程序员--《C primer plus》)。
但是在这里,如果你写成i++,那么到了递归阶段,第一次调用 qsort (array,min,i++)就会导致i为-1,有兴趣可以自己在大脑里推演推演(嗯,这是个快速杀死脑细胞的好方法),但是我们都知道,数组都是从0开始的。所以stackover flow就变得理所当然了。这也是为什么改成++i 就可以运行的原因。
最后,热烈欢迎大家的指正和批评,热烈欢迎大家一起探讨。
参考:
http://v.163.com/movie/2010/12/S/4/M6UTT5U0I_M6V2T7IS4.html (MIT算法导论公开课)