看正月点灯笼老师的笔记—快速排序
作者:互联网
这是快排的代码。
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #define N 1086 int a[N]; int partition(int L, int R) { int i = L, j = L; int p = a[R]; for (; i <= R; i++) { if (a[i] < p) { int t = a[i]; a[i] = a[j]; a[j] = t; j++; } } a[R] = a[j]; a[j] = p; return j; } void quick_sort(int L, int R) { if (L < R) { int m = partition(L, R); quick_sort(L, m - 1); quick_sort(m + 1, R); } } int main(void) { int n; scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%d", &a[i]); } quick_sort(0, n - 1); for (int i = 0; i < n; i++) { printf("%d ", a[i]); }puts(""); system("pause"); return 0; }
我在这主要想讲一下 patition 这个函数。其中运用了一个十分巧妙的算法,由于我不知道这个算法叫什么名字,
但我愿称之为 区间移动
1,首先 定义 i 指向 区间最后一个元素的位置, j 指向 区间的第一个元素的位置
2,将 i 和 j 初始化为 0,此时区间并无元素,所以需要 i 遍历一遍数组,把满足条件的数组添加到 i 和 j 之间,
3,怎么添加元素到区间里面呢?
原来 是通过 i 去试探元素是否符合条件,若符合条件,则 i 继续试探下一个元素, j 留下来指向区间的第一个元素,这样 i 和 j 就错开了
若符合条件 , 则把 i 指向的元素和 j 指向的元素交换位置,这样就把整个区间向后移动一位了,然后 i 继续试探下一个元素
不过这样原本区间元素的首尾的位置就交换了一下,所以最后得到的区间里的元素位置相对于原数组的位置是不同。
稍微总结一下,不管是否满足条件 i 都是要试探下一个元素的,所以 i 始终是加 1 的。真正改变区间长度的是 j ,若 j 加 1 使区间后移,若 j 不变,则区间扩大。
4,最后一个问题,在 partiiton 这个函数的区间的移动条件是 数组元素小于最后一个元素(其实应该反过来说是大于等于,不过代码写出来的判定条件就是这个),
那么问题来了,当 i 移动到数组的最后一个元素时,这个元素确实满足区间的条件,应该呆在区间里,所以循环就此结束。
这没有问题,有问题的是快速排序,因为快排需要的不是左边元素全部小于右边的,而是数组中间有一个元素,左边全部小于这个元素,右边全部大于这个元素,正月老师称之为 支点,
而 partition 中,数组最后一个元素就一直被用做支点,作为判断条件,
所以在函数最后还要交换一下区间头尾,即 a[i]和 a[j] ,
使数组分隔开,做到 partition.
标签:partition,指向,int,元素,笔记,灯笼,数组,区间,排序 来源: https://www.cnblogs.com/asdfknjhu/p/12374264.html