在学习快速排序之前,我们先看一个故事:
假如你是一个农场主,家里没钱,就是有地,地也不多!面积是 2180 m* 500m。现在你需要将这块地均匀分成方块,且分出的方块要尽可能的大。
图 1- 1 你家的地
已知:面积 2180 * 500
要求:分成方块,方块尽可能的大。
图1-2 分下
是不是应该这样分呢,保证分出来的是最大面积的正方形。还剩余180 * 500 面积,问题规模由2180 * 500 ,是不是缩小到了 180*500。OK,我们继续按照之前的思路:
发现问题在不断的简化, 最终我们肯定能按要求分出 最大的方块。
解决分地的过程,我们发现就2个步骤:
1.找出基本条件,就是较长的一边的长度按另一边长度来划分。
2.不断将问题分解,缩小规模,直至符合步骤1。
以上解决问题的思路,称之为分而治之。
快速排序是一种常用的排序算法,在c#语言库中函数sort实现的就是快速排序,用的也是分而治之的思想。
我们用快速排序对数组进行排序:
现在数组:{10,3,11,2,15,0} 2个指针:left,right 分别指向数组的第一个元素 和最后一个元素。 key:我们取一个元素当做 比较值。
整体思路是:比key小的放在key的左边,比key大的放在key的右边。
具体:从right出发向 数组头(左边)去找比key小的值,遇到则指针停下。然后left向后(右边)开始找比key大的数,遇到则指针停下。前提条件是:left 不等于 right 。
操作如下:
key 取第一个元素 key = 10. 用l,r 分别记录left、right 。我们用l,r去移动指针。
首先从右边开始找比key小的值,0比key(10)小,此时 r 指针停下。
现在从左边开始找比key大的值,10不比key(10)大,l指针继续往右走,3比key(10)小,OK,继续移l,11比key(10)大,此时指针停下。
11根0交换位置:
好,,继续重复上面的步骤:
步骤1:先移动右指针r向左移动,遇到比 key(10)小的,指针r停下
步骤2:然后再移动左指针l向右移动,遇到比 key(10)大的,指针l停下
步骤1操作: 15比key(10)大,r继续左移,r指针来到2的位置,2比10小,指针r停下
步骤2操作:左指针l 右移在位置2
当指针r,l 指向同一位置的时候,该位置上的元素 与key 交换:2与10 交换。
此刻:指针r,l 指向同一个位置,把数组一分为2,然后左右两边的数组 用递归,调用快排的方法 最终达到有序。
直接上代码:
1 public static void Quick(int[] arr, int left, int right)
2 {
3 //数组初始判断
4 if (arr == null || arr.Length == 0) return;
5 if (left > right) return;
6
7 int L = left;//记录指针
8 int R = right;//记录指针
9 int key = arr[left];
10
11 while (L != R)//左指针不等于右指针
12 {
13 while (arr[R] >= key && R > L)//右指针指向元素 大于key 继续往左走,直到小于key的时候才停下
14 {
15 R--;
16 }
17 while (arr[L] <= key && R > L)//左指针指向元素 小于key 继续往右走,直到大于key的时候才停下
18 {
19 L++;
20 }
21 //r,l 都停下 指针指向的元素进行交换
22 if (R > L)
23 {
24 int temp = arr[R];
25 arr[R] = arr[L];
26 arr[L] = temp;
27 }
28 }
29 //说明2个指针指向同一位置,此位置上的元素与key交换
30 arr[left] = arr[R];
31 arr[R] = key;
32 Quick(arr, left, R - 1);//左数组继续上述操作
33 Quick(arr, R + 1, right);//右数组继续上述操作
34 }
以上就是快速排序,哪里写的不好,欢迎大家提出批评和建议~