排序算法之快速排序
2016-10-10 23:54
176 查看
1、算法描述
快排算法是由C.A.R Hoarse提出的一种算法,该算法是目前实践中使用最频繁、实践效率最好的排序算法。快排是一种运用分治思想的算法;主要思想为:对待排序数组S={d1,d2,......,dn},从中找出元素V,我们称之为划界元素,将剩下的元素中小于或等于V的元素移到V的前面,将大于V的元素移到V的后面,这样V就找到了它最终的排序位置,并将S划分为两两不相交子数组S1和S2,其中S1中的元素均小于等于V,S2中的元素均大于等于V,这样的过程称为一次排序。然后在此基础上递归地在子序列S1和S2上进行上述的排序过程,直到所有的子序列都只包含0或1个元素停止。因此快速排序过程可归纳为四个步骤:
(1)、取划界元素:即在待排序数组S中选择某个元素作为其划界元素;
(2)、移动元素:将S中除去V的元素集划分成两个不相交的子序列S1和S2,满足S1中的元素均小于等于V,S2中的元素均大于等于V;
(3)、返回V的最终位置;
(4)、递归地在S1和S2上进行上述3个步骤。
注:对于划界元素的选取,从理论上讲没有限制,但在实际中一般采用3种方式:即选择待排序元素中的第一个元素或最后一个元素或者居中的那个元素。快排是一个不稳定的排序算法,主要是因为在进行最后一步划界元素与S[i+1]交换的时候有可能打破前面元素的稳定性。
2、算法实现
假设有待排数组S={49,55,25,97,60,27,49,50}按照快排算法进行排序。过程如下:先设置变量p和r表示数组的首尾元素的下标,选取数组元素最右边的50作为划界元素,记为S[r],然后对S[p],S[p+1],......,S[r-1]组成的子序列进行划分。接下来:
首先,设置变量i=p-1;即最前面元素的前一个,设置变量j=p;反复执行如下步骤:一、执行i+1,如果S[j]<=S[r],交换S[i+1]与S[r]的值,i=i+1;j=j+1;如果S[j]>=S[r],i不变,j=j+1;二、到j=r-1时停止步骤一。
重复执行上述步骤直至停止后,交换S[i+1]与S[r]的值,划界元素就放在了它最终位置上,其左边的元素均小于等于它,右边的元素均大于它。
快排的每一次递归执行过程中主要执行了两个操作:一是数据交换;二是返回划界元素的最终位置。
实现代码如下
void
quickSort(int
data[],int
p,int
r);
3、算法时间复杂度分析
如果参加排序的元素原本就是有序的,这时快排的时间效率最低,时间复杂度为O(N2),在最好情况下和一般情况下效率还是比较高的,时间复杂度为O(NlogN)。
快排算法是由C.A.R Hoarse提出的一种算法,该算法是目前实践中使用最频繁、实践效率最好的排序算法。快排是一种运用分治思想的算法;主要思想为:对待排序数组S={d1,d2,......,dn},从中找出元素V,我们称之为划界元素,将剩下的元素中小于或等于V的元素移到V的前面,将大于V的元素移到V的后面,这样V就找到了它最终的排序位置,并将S划分为两两不相交子数组S1和S2,其中S1中的元素均小于等于V,S2中的元素均大于等于V,这样的过程称为一次排序。然后在此基础上递归地在子序列S1和S2上进行上述的排序过程,直到所有的子序列都只包含0或1个元素停止。因此快速排序过程可归纳为四个步骤:
(1)、取划界元素:即在待排序数组S中选择某个元素作为其划界元素;
(2)、移动元素:将S中除去V的元素集划分成两个不相交的子序列S1和S2,满足S1中的元素均小于等于V,S2中的元素均大于等于V;
(3)、返回V的最终位置;
(4)、递归地在S1和S2上进行上述3个步骤。
注:对于划界元素的选取,从理论上讲没有限制,但在实际中一般采用3种方式:即选择待排序元素中的第一个元素或最后一个元素或者居中的那个元素。快排是一个不稳定的排序算法,主要是因为在进行最后一步划界元素与S[i+1]交换的时候有可能打破前面元素的稳定性。
2、算法实现
假设有待排数组S={49,55,25,97,60,27,49,50}按照快排算法进行排序。过程如下:先设置变量p和r表示数组的首尾元素的下标,选取数组元素最右边的50作为划界元素,记为S[r],然后对S[p],S[p+1],......,S[r-1]组成的子序列进行划分。接下来:
首先,设置变量i=p-1;即最前面元素的前一个,设置变量j=p;反复执行如下步骤:一、执行i+1,如果S[j]<=S[r],交换S[i+1]与S[r]的值,i=i+1;j=j+1;如果S[j]>=S[r],i不变,j=j+1;二、到j=r-1时停止步骤一。
重复执行上述步骤直至停止后,交换S[i+1]与S[r]的值,划界元素就放在了它最终位置上,其左边的元素均小于等于它,右边的元素均大于它。
快排的每一次递归执行过程中主要执行了两个操作:一是数据交换;二是返回划界元素的最终位置。
实现代码如下
void
quickSort(int
data[],int
p,int
r);
int partition(int data[],int p,int r);
int main()
{
int data[]={49,55,25,97,60,27,49,50};
cout<<"排序前的数组为:"<<endl;
for(int i=0;i<8;i++){
cout<<data[i]<<" ";
}
cout<<endl;
quickSort(data,0,7);
cout<<"排序后的数组为:"<<endl;
for(int i=0;i<8;i++){
cout<<data[i]<<" ";
}
cout << endl;
system("pause");
return 0;
}
int partition(int data[], int p, int r)
{
int temp=data[r];//选择划界元素
int i=p-1;//最前面元素的前一个,保证交换后小于等于划界元素的元素的位置在大于划界元素的位置的前面
int j;
for(j=p;j<r;j++){
if(data[j]<=temp){ //数据交换
int temp1;
temp1=data[i+1];
data[i+1]=data[j];
data[j]=temp1;
i+=1;
}
}
int temp2;
temp2=data[i+1];
data[i+1]=data[r];
data[r] =temp2;
return i+1;//返回划界元素的最终位置
}
void quickSort(int data[], int p, int r)
{
int position=0;
if(p<r)
{
position=partition(data,p,r); //根据划界元素返回的位置对左右子序列进行递归操作
quickSort(data,p,position-1);
quickSort(data,position+1,r);
}
}
3、算法时间复杂度分析
如果参加排序的元素原本就是有序的,这时快排的时间效率最低,时间复杂度为O(N2),在最好情况下和一般情况下效率还是比较高的,时间复杂度为O(NlogN)。
相关文章推荐
- Java技术栈(2)排序算法(冒泡,快速排序)
- 排序算法——快速排序
- Java中常见的数组排序算法(包括冒泡,选择,插入,快速排序)
- 排序算法-快速排序
- 排序算法之快速排序
- 排序算法之快速排序详解
- 排序算法之快速排序
- 排序算法——快速排序的图解、代码实现以及时间复杂度分析
- JAVA中排序算法(冒泡排序、选择排序、插入排序、快速排序)
- JavaScript排序算法系列——快速排序
- 【JAVA算法】排序算法 -- 快速排序
- Java排序算法总结之(二)——基于交换排序(冒泡排序、快速排序)
- 排序算法系列——快速排序
- 排序算法系列之快速排序 (5)
- 白话排序算法(归并排序,快速排序)
- 排序算法之快速排序
- 算法 排序算法之交换排序--冒泡排序和快速排序
- 06_程序员必须掌握的8大排序算法_快速排序
- 排序算法之 —— 快速排序(五)
- 排序算法-快速排序(及求第K小元素)