这个程序就是按上面讲的过程写的。实际上还可以对这个程序进行优化。在快速排序算法中,每轮比较有且仅有一个 key 值,但是 key 值的位置是不断变化的,只有比较完一轮后 key 值的位置才固定。上面这个程序中每次执行 swap 时实际上交换的是 key 和 a[low] 或 key 和 a[high],而 key 的位置每次都是不一样的。所以既然 key 的位置是“动来动去”的,所以就不必将它赋到数组中了,等最后一轮比较结束后,它的位置“不动”了,再将它赋到数组中。
比如,数组 a 中元素为:3142。如果按从小到大排序,那么 key=3,按上面这个程序就是 3 和 2 互换。2 赋给 a[0] 是必需的,但 key 就没有必要赋给 a[3] 了。但你可以想象 key 是在 a[3] 这个位置,这个很重要。即此时序列变成 2142(key)。
然后 key 和 1 比较,不用换;key 和 4 比较,将 4 赋给 a[3],然后想象 key 在 4 的位置,即此时序列变成 214(key)4。此时 key 左边全是比 key 小的,key 的右边全是比 key 大的。这时 key 的位置就固定了,再将它赋到数组中,即 2134。
# include <stdio.h> void QuickSort(int *, int, int); /*现在只需要定义一个函数, 不用交换还省了一个函数, 减少了代码量*/ int main(void) { int i; //循环变量 int a[] = {900, 2, -58, 3, 34, 5, 76, 7, 32, 4, 43, 9, 1, 56, 8,-70, 635, -234, 532, 543, 2500}; QuickSort(a, 0, 20); /*引用起来很简单, 0为第一个元素的下标, 20为最后一个元素的下标*/ printf("最终排序结果为:\n"); for (i=0; i<21; ++i) { printf("%d ", a[i]); } printf("\n"); return 0; } void QuickSort(int *a, int low, int high) { int i = low; int j = high; int key = a[low]; if (low >= high) //如果low >= high说明排序结束了 { return ; } while (low < high) //该while循环结束一次表示比较了一轮 { while (low < high && key <= a[high]) { --high; //向前寻找 } if (key > a[high]) { a[low] = a[high]; //直接赋值, 不用交换 ++low; } while (low < high && key >= a[low]) { ++low; //向后寻找 } if (key < a[low]) { a[high] = a[low]; //直接赋值, 不用交换 --high; } } a[low] = key; //查找完一轮后key值归位, 不用比较一次就互换一次。此时key值将序列分成左右两部分 QuickSort(a, i, low-1); //用同样的方式对分出来的左边的部分进行同上的做法 QuickSort(a, low+1, j); //用同样的方式对分出来的右边的部分进行同上的做法 }
输出结果是:
最终排序结果为:
-234 -70 -58 1 2 3 4 5 7 8 9 32 34 43 56 76 532 543 635 900 2500
总结