C程序,帮我解释一下(20分)

小唐

Unregistered / Unconfirmed
GUEST, unregistred user!
以下是书上的例程,有些地方不懂,我在程序中加了我的理解和疑问,请给予指点
#include <stdio.h>
#include <stdlib.h>
void quick_sort(int array[], int first, int last)
{
int temp, low, high, list_separator;


low = first;
high = last;
list_separator = array[(first + last) / 2];
//得到数组中间的位置的值
do

{
while (array[low] < list_separator) //当list_separator左边的数小于list_separator
low++;
//循环找到list_separator左边的不小于list_separator的数的位置
while (array[high] > list_separator) //当list_separator右边的数大于list_separator
high--;
//循环找到list_separator右边的不大于list_separator的数的位置

if (low <= high) //为什么要if,觉得这个条件肯定会成立
{
temp = array[low];
//这句和下面两句将数组元素值交换
array[low++] = array[high];
array[high--] = temp;
}
}
while (low <= high);
//觉得这个条件将永远成立,会造成无限循环
if (first < high) //觉得这个条件绝对成立,没必要if
quick_sort(array, first, high);
if (low < last) //觉得这个条件绝对成立,没必要if
quick_sort(array, low, last);
}
void main(void)
{
int values[100], i;

for (i = 0;
i < 100;
i++)
values = rand() % 100;
quick_sort(values, 0, 99);
for (i = 0;
i < 100;
i++)
printf("%d ", values);
}
 
1. if (low <= high) //为什么要if,觉得这个条件肯定会成立
这个是因为:如果第一次循环到low=list_separator-1,high=list_separator+2
这时执行:if (low <= high)
{
temp = array[low];

array[low++] = array[high];
array[high--] = temp;
}
使得low=list_separator,high=list_separator+1
接着执行假设第二次循环执行,使得low=list_separator+1,high=list_separator
这时就使得low>high,所以才加上if (low <= high)
 
下面的道理也就差不多都是这样的
 
小唐:
list_separator是一个值,不是指针.所以:
while (array[low] < list_separator)
low++;
//用low向前搜索整个数组.直到找到有不小于中间项值的的为止.
while (array[high] > list_separator)
high--;
//用high向后搜索整个数组,直到找到有不大于中间项值的的为止.
而不是在仅中间值的左右搜索.所以要判断是否low<=high.一旦low>high.
则说明数组中比中间值大的全被交换到中间项的右边.比中间值小的全到了左边.
则交换过程的循环结束.你可以自己验证一下.
然后因为low>high.所以从first到high.以及从low到last把整个数组切成左右两半.
(当然,左数组里任何一个值小于等于右数组里任何一个值).
再对两个子数组进行相同的操作.因此子数组越切越小.所以需要判断子数组是否不可
再分.当其不可再分时,就停止递归调用.
以下几句代码就是做这个判断的.当子数组只有一两个的时候.判断式就会为假.
不会再进行递归调用. 你可以自己验证一下.
if (first < high)
quick_sort(array, first, high);
if (low < last)
quick_sort(array, low, last);
 
kazema:
谢谢,看了你的解释后,我又上机验证了一下,确实如你所说。
  以下是我的一些心得,看是不是还有什么需要纠正的地方。
  我取的数组是{7,3,1,4,6},首先list_separator为1,因为7比1大,
while (array[low] < list_separator)
low++;

上面的while不成立,只执行
while (array[high] > list_separator)
high--;
这两行,6>1,条件成立,high--后high为3,4>1,条件成立,high--后high为2,1>1,条件不成立,
所以high为2。
因为low=0,high=2,所以if (low<=high)是成立的,于是将{7,3,1,4,6}中的7和1交换,
得到{1,3,7,4,6},这时再来看while (low<=high),由于low=1,high=1,条件成立,
继续循环。
第二遍循环
这时, while (array[low] < list_separator)
low++;
由于array[low]=3,list_separator=1,条件不成立,不执行low++
接下来, while (array[high] > list_separator)
high--;
因为array[high]=3,list_separator=1,条件成立,执行high--后high为0,
继续while,这时array[0]=1,list_separator=1,条件不成立,所以high为0
这时运行到这一句
if (low <= high)
由于low=1,high=0,条件不成立,所以不执行里面的交换数据的语句
接下来运行到这一句
while (low <= high);
由于条件不成立,退出while循环
到了这一句
if (first < high)
由于first为0,high也为0,所以条件不成立,
继续往下执行到这一句:
if (low < last)
quick_sort(array, low, last);
由于low为1,last为4,所以low<last是成立的,
于是对{1,3,7,4,6}中的{3,7,4,6}进行递归运算


#include <stdio.h>
#include <stdlib.h>
void quick_sort(int array[], int first, int last)
{
int temp, low, high, list_separator;


low = first;
high = last;
list_separator = array[(first + last) / 2];

do

{
while (array[low] < list_separator)
low++;
//用low向右搜索整个数组.直到找到大于等于(不小于)中间项值的数值
//并将该值在数组中的索引位置保存到low
//而不是仅在中间值的左方搜索,有可能搜索到中间值的右方
while (array[high] > list_separator)
high--;
//用high向左搜索整个数组,直到找到小于等于(不大于)中间项值的数值
//并将该值在数组中的索引位置保存到high
//而不是仅在中间值的右方搜索,,有可能搜索到中间值的左方

if (low <= high) //经过以上两个while后,low和high的大小关系不确定,所以要用if
//low代表大于等于中间值的值的索引位置,high表示小于等于中间值的值的索引位置
//当low<=high时,说明大值出现在中间项值的左边,
//这不符合快速排序法从小到大排序的规则,必须对调过来才行
{
temp = array[low];

array[low++] = array[high];
array[high--] = temp;
}
}
while (low <= high);
//对不符合规则的数通过循环不断交换直至最后都符合规则
//即实现low>high,使小于等于中间项值的数出现在中间项值的左边,
//使大于等于中间项值的数都出现在中间项值的右边
if (first < high)
quick_sort(array, first, high);
if (low < last)
quick_sort(array, low, last);
}
void main(void)
{
int values[100], i;

for (i = 0;
i < 100;
i++)
values = rand() % 100;
quick_sort(values, 0, 99);
for (i = 0;
i < 100;
i++)
printf("%d ", values);
}
 
对! 就是这样:)
 
shigongping:
你的解答我没有理解,不过还是要说声谢谢!
kazema:
再次说声谢谢,以后还要向你多多请教。
 
顶部