快速排序算法(QuickSort)
1.算法思想
快速排序是一种划分交换排序,采用了分治策略,通常称为分治法。
(1)分治法的基本思想
将原问题分解成若干个规模更小但结构与原问题相似的子问题;递归地解这些子问题,然后将这些子问题的解组合成原问题的解。
(2)快速排序的基本思想
设当前待排序的无序区为R[low..high],利用分治法可将快速排序的基本思想描述为:
①分解:
在R[low..high]中任选一个记录作为基准(Pivot),以此基准将当前无序区划分为左、右两个较小的子
区间R[low..pivotpos-1)和R[pivotpos+1..high],并使左边子区间中所有记录的关键字均小于等于基准记录
(不妨记为pivot)的关键字pivot.key,右边的子区间中所有记录的关键字均大于等于pivot.key,而基准记录
pivot则位于正确的位置(pivotpos)上,它无须参加后续的排序。
注意:划分的关键是要求出基准记录所在的位置pivotpos。
划分的结果可以简单地表示为(注意pivot=R[pivotpos]):
R[low..pivotpos-1].keys≤R[pivotpos].key≤R[pivotpos+1..high].keys
其中low≤pivotpos≤high。
②求解:
通过递归调用快速排序对左、右子区间R[low..pivotpos-1]和R[pivotpos+1..high]快速排序。
③组合:
因为当”求解”步骤中的两个递归调用结束时,其左、右两个子区间已有序。对快速排序而言,”组合”步
骤无须做什么,可看作是空操作。
第一步:找到一个基准数;把小于这个数的数都放到左边,把大于这个数的数都放到右边;
第二部:对基准数左边和右边的数,重复第一步;
2.快速排序算法的C语言实现
(1)选取第一个元素作为基准(枢纽元)
/**********快速排序算法*****************/
void QuickSort(char s[],int low,int high)
{
int i;
int last; //记录基准的位置
if(low<high) //当数组中的元素个数大于1时,才进行操作
{
last=low; //选取第一个元素作为基准
//把小于基准元与大于基准元的分开,last记录它们分开的界限
for(i=low+1;i<=high;i++)
{
if(s[i]<s[low])
swap(s,++last,i);
}
swap(s,last,low);//基准元与界限交换,这样的话,基准元两边就是一边大于,一边小于;
QuickSort(s,low,last-1); //对左区间递归排序
QuickSort(s,last+1,high);//对右区间递归排序
}
}
/*交换数组中的两个元素*/
void swap(char s[],int i,int j)
{
int temp;
temp=s[i];
s[i]=s[j];
s[j]=temp;
}
注意:
为排序整个文件,只须调用QuickSort(R,0,n-1)即可完成对R[0..n-1]的排序。
(2)
选取第一个元素作为枢纽元,如果输入是随机的,那么这是可以接受的,但是如果输入是预排序的或是反序的,那么选取第一个元素作为枢纽元就产生一个劣质的分割,因为所有的元素不是被划到这一边就是划到另一边。
随机选取枢纽元是一种安全的做法;
三数中值分割法:使用数组的左端、右端和中心位置上的三个元素的中值作为枢纽元