快速排序

来源:互联网 发布:c语言编写银行家算法 编辑:程序博客网 时间:2024/06/05 14:08

最近看了一些关于快速排序的教程,感觉有些东西必须要弄清楚,不然会云里雾里的,所以写了这篇博客,首先说明一下,快速排序需要递归的基础

我们首先来看什么是快速排序?

通俗的讲,快速排序是一种排序的算法,它的思想是,先将要排序的数据分为两部分,其中一部分中的所有数据要比另一部分的所有数据小,然后在用同样的方法(递归)来将这

两部分的数据进行分割,直到将所有数据都变成有序序列

那么如何将数据分为两部分,一部分小的数据和一部分大的数据呢?

我们通常会先找出数据的第一个数据所对应的有序时的位置,这里我要说的是这连个位置是不同的,前一个是未排序的位置,后一个是排完序的位置,比如说我们现在有一个数据集合A = {2, 5, 3, 8, 4, 9},我们思维上认为 8 是在第四个位置上,而排完序后 8 是在 第五个位置上 即A = {2, 3,4, 5, 8, 9},然后我们对这个数据左边的数据在进行同样的排序(左边的还是无序),最后我们对右边的进行同样的排序。最终我们就会得到最终结果。

这里我们先不管如何找到第一个数据所对应的排完序时的位置怎样找,先来看一段代码体会一下这个过程

#include<stdio.h>int main(void){int a[7] = {2, 7, 4, 8, 6, 9,-7};//这里我们用数组来存放数据集合int i;QuickSort(a, 0, 6);//第一个参数是我要处理数据段的首元素的地址, 第二个参数是 从数组中元素下标为 0 的元素开始排,第三个参数是 终止元素的下标,也就是说这段代码实现的功能是对从地址为 a 偏移量为0 的元素开始,一直到偏移量为6的元素进行快速排序for(i = 0; i < 7; i++){printf("%d   ",a[i]);}printf("\n");return 0;}void QuickSort(int * a, int low, int high){int Post;if(low < high){Post = Find(a, low, high);  //从数组的 low 找到 hight,也就是说我现在要找到地址为a所对应元素它在排完序之后所对应的位置,这个位置我用变量Post 来保存QuickSort(a, low, Post-1);   //对 Post 的左边的数据进行快排,使用递归对左边的数据进行同样的函数调用,这里我们要注意,调用完Find函数之后,数组中第一个元素的位置已经改变到我们所希望的位置了,也就是排完序的位置QuickSort(a, Post+1, high); //对 Post 的右边的数据进行快排}}
我们试着用这段不完整的代码跑一下 数据集合A = {2, 5, 3, 8, 4, 9},首先由我们的代码得知这个数据集合被保存到一个名为a的数组中,然后进入QuickSort 函数,把数组名也就是第一个元素的地址传给 QuickSort 的第一个参数,我们要把这个数组中的所有元素都排序,所以我们把第一个元素的偏移地址 0 传给第二个参数,把最后一个元素的偏移地址 5 传给第三个参数

很显然,如果你传入的low参数大于或等于high参数,就不需要比较,因为刚开始的时候low和high在数据集合的两边,然后向中间跑,如果相等或跑过头就停止了。

我们用一个find函数找到第一个元素排完后的位置,很显然,2排完后的位置仍然是 0 即在数组的第一个元素上,这时 Post的值为0,然后再次调用QuickSort 函数对2左边的数据集合进行排序,我们发现2的左边没有元素,在代码中给QuickSort传入的参数low为0,high为-1,从代码中可以看到直接跳过 if 然后 2 左边的数据集合排序完成,然后对 2 右边的数据集合进行排序,第一个元素是 5 ,它排完序后对应的位置时第四个,所以经过find函数后 5 数组中第四个元素的值就为5了,然后再对5左右的数据集合进行排序,一次类推,最终全部排完

说了这么多,大家肯定想知道这个 find函数是如何对数组中的元素进行操作的呢?欧克,下来先笼统的讲一下find 函数的操作流程

首先我们要确定我们要找哪一个元素排完序的位置,我们要清楚的是,find 所处理数据段的第一个元素不是a[0],而是 a[low],因为a[0] 是我们定义整个数组的第一个元素,而在我们进行排序的过程中,使用递归,会使得QuickSort中接收的实参发生变化,而每一次处理的数据段,第一个元素肯定是以 low 为下标所对应的元素,然后我们要确定的是在那一区间去找(对比),即在某一个区间内被找的这个元素所对应的位置,所以我们的find 有三个参数,第一个是要操作元素所需要的指针,第二个是第一个元素地址的偏移量同时是区间的开始端,第三个是区间的结束端。

下来我们来看Find函数的代码

int Find(int * a, int low, int high){int val;val = a[low]; //这条语句保证了在进行 找位置的时候始终是从 要排序的那一段的数据的第一个元素开始,对这个元素进行查找元素while(low < hight){while(low < hight && a[hight] > val){--hight;}// 从这个while中出来有两种情况 第一种是 low == hight 第二种是 a[hight] < vala[low] = a[high];while(low < hight && a[low] < val){++low;}a[high] = a[low];}a[low] = val;return low;//或者return high 因为当程序跳出总while的时候,low 和 high 一定是相等的}
同样的道理我们,跑一边元素集合就对这个过程非常清楚了,在这里我就不累赘的跑了。

最后我还想说的是,一定要弄清楚递归的过程,每一次调用都是不同的参数,千万不能弄混了,最好用纸画出来

0 0
原创粉丝点击