读书人

关于wiki上快速排序例子的一个有关问题

发布时间: 2013-09-05 16:02:06 作者: rapoo

关于wiki上快速排序例子的一个问题
例子如下,我的问题是,其中有这样一句:
/* 关键数据放到‘中间’ */
swap(&a[left],&a[j]);
这句话在干什么?
我理解是a[left]是要比较的值,然后i,j分别为从头,尾两个方向进行交换,如果小于A[left]就放到头这边,大于就放到尾那边,最后ij会重叠在中间的莫个位置,
但这时候他把这个重叠点和a[left]交换了,我觉得有问题,ij相交的那个值和a[left]一样正好应该是左右两边的一个分界,左边永远小于它,右边永远大于他。交换后没有任何意义,而且导致了取了一个左边最大的数作为了左边递归的下一个pivot。这样左边的递归效率永远是最差的。

但我运行校验了下,又不符和我所想,请教下,我错在哪了?
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

#include <stdio.h>
int a[100] = { 1, 2, 8, 7, 9, 5, 6, 4, 3, 66, 77, 33, 22, 11 };

/* 输出数组前n各元素 */
void prt(int n) {
int i;
for (i = 0; i < n; i++) {
printf("%d\t", a[i]);
}
printf("\n");
}

/* 数据交换 */
void swap(int *a, int *b)
{
int tmp;
tmp = *a; *a = *b; *b = tmp;
}

void quick_sort(int a[], int left, int right)
{
int i = left + 1, j = right;
int key = a[left];

if (left >= right) return;

/* 从i++和j--两个方向搜索不满足条件的值并交换 *
* 条件为:i++方向小于key,j--方向大于key */
while (1) {
while (a[j] > key) j--;
while (a[i] < key&&i<j) i++;
if(i >= j) break;
swap(&a[i],&a[j]);
if(a[i]==key)j--;
else i++;
}

/* 关键数据放到‘中间’ */
swap(&a[left],&a[j]);

if(left < i - 1) quick_sort(a, left, i - 1);
if(j + 1 < right) quick_sort(a, j + 1 , right);

}

int main(void) {

/* 排序与输出 */


quick_sort(a, 0, 13);
prt(14);

return 0;
} 快速排序 算法
[解决办法]
不是啊。 比如8 7 6 5 10 9快排,第一次排序最终i和j都指向5这个数,
/* 关键数据放到‘中间’ */
swap(&a[left],&a[j]);
这样操作之后刚好保证了5 7 6 8 10 9,它这样一换刚好保证了8在排序的正确位置上,因为下把左递归的时候是quick_sort(a, left, i - 1);指的是5 7 6这三个数进行递归排序。这样8的位置已经排正确了,不需要参与之后的递归排序。
[解决办法]
a[j]最终指向的是小于a[left]的值,因为你的所有元素都是和a[left]比较,如果不交换a[left]和a[j]的话,你左侧的元素就不一定小于a[j]

读书人网 >C语言

热点推荐