定义
快速排序是对冒泡排序的一种改进。
基本思想:
通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
算法思想
假设序列中有 n 个数,将这 n 个数放到数组 a 中。
算法:
设置两个变量 i、j,排序开始的时候:low=0,high=n–1。
(1)以数组第一个元素为关键数据,赋给变量 key,即 key=a[0]。
(2)从high 开始向前搜索,即由后开始向前搜索(high–),找到第一个小于 key 的值 a[high],将 a[high] 和 a[low] 互换。
(3)然后再从 low 开始向后搜索,即由前开始向后搜索(++low),找到第一个大于 key 的 a[low],将 a[low] 和 a[high] 互换。
(4)重复第 2、3 步,直到 low=high。此时就能确保序列中所有元素都与 key 比较过了,且 key 的左边全部是比 key 小的,key 的右边全部是比 key 大的。
第一轮比较后序列就以 key 为中心分成了左右两部分,然后分别对左右两部分分别递归执行上面几个步骤,直到排序结束。
a={50,10,90,30,70,40,80,60,20};
代码:
#include<stdio.h>
int Split(int *a,int low,int high) /*将比key大的放一边,比key小的放一边*/
{
int key,temp;
key=a[low];
while(low<high)
{
while(low<high&&a[high]>=key)
high--;
{
temp=a[low];
a[low]=a[high];
a[high]=temp;
}
while(low<high&&a[low]<=key)
low++;
{
temp=a[low];
a[low]=a[high];
a[high]=temp;
}
}
return low;
}
void Quicksort(int *a,int low,int high)
{
int p;
if(low<high)
{
p=Split(a,low,high);
Quicksort(a,low,p-1);
Quicksort(a,p+1,high);
}
}
void main()
{
int n,a[1000],i;
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
Quicksort(a,0,n-1);
printf("最终排序结果:\n");
for(i=0;i<n;i++)
printf("%d ",a[i]);
}
快速排序优化
1,优化选取key
三数取中法。即取三个关键字先进行排序,将中间数作为key,一般是取左端,右端和中间三个数,也可以随机选取。
在Split函数代码的第3行与第4行之间增加这样一段代码。
int m=low+(high-low)/2 /*计算数组中间元素的下标*/
if(a[low]>a[high])
{
temp=a[low];
a[low]=a[high];
a[high]=temp;
}
if(a[m]>a[high])
{
temp=a[m];
a[m]=a[high];
a[high]=temp;
}
if(a[m]<a[low])
{
temp=a[m];
a[m]=a[low];
a[low]=temp;
}
2,优化不必要的交换
将a[0]用作哨兵或临时变量。将key备份到a[0],采用替换而不是交换的方式。
int Split(int *a,int low,int high) /*将比key大的放一边,比key小的放一边*/
{
int key,temp;
int m=low+(high-low)/2;
if(a[low]>a[high])
{
temp=a[low];
a[low]=a[high];
a[high]=temp;
}
if(a[m]>a[high])
{
temp=a[m];
a[m]=a[high];
a[high]=temp;
}
if(a[m]>a[low])
{
temp=a[m];
a[m]=a[low];
a[low]=temp;
}
key=a[low];
a[0]=key;/*将key备份到a[0]*/
while(low<high)
{
while(low<high&&a[high]>=key)
high--;
a[low]=a[high];/*采用替换而不是交换的方式进行操作*/
while(low<high&&a[low]<=key)
low++;
a[high]=a[low];/*采用替换而不是交换的方式进行操作*/
}
a[low]=a[0];/*将key数值替换回a[low]*/
return low;
}
3,优化小数组时的排序方案
当high-low小于等于数组长度阀值时用直接插入法;
当high-low大于数组长度阀值时用快速排序。
4,优化递归操作
void Quicksort(int *a,int low,int high)
{
int p;
while(low<high)
{
p=Split(a,low,high);
Quicksort(a,low,p-1);
low=p+1; /*尾递归*/
}
}
#include<stdio.h>
void quicksort(int a[],int low,int high)
{
int i,j,key;
i=low;
j=high;
key=a[i];
if(i>=j)
return ;
while(i<j)
{
while(i<j&&a[j]>=key)
j--;
a[i]=a[j];
while(i<j&&a[i]<=key)
i++;
a[j]=a[i];
}
a[i]=key;
quicksort(a,low,i-1);
quicksort(a,i+1,high);
}
void main()
{
int a[10000];
int i,n;
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
quicksort(a,0,n-1);
for(i=0;i<n;i++)
printf("%d ",a[i]);
}
选择排序:
void choosesort(int a[],int n)
{
int i,j,min,tmp;
for(i=0;i<n-1;i++)
{
min=i;
for(j=i+1;j<n;j++)
{
if(a[j]<a[min])
min=j;
}
if(i!=min)
{
tmp=a[i];
a[i]=a[min];
a[min]=tmp;
}
}
}
直接插入排序:
void insertsort(int a[],int n)
{
int i,j,key;
for(i=1;i<n;i++)
{
key=a[i];
for(j=i-1;j>=0;j--)
{
if(a[j]>key)
a[j+1]=a[j];
else
break;
}
a[j+1]=key;
}
}
希尔排序:
void shellsort(int a[],int n)
{
int i,j,key,step;
for(step=n/2; step>=1; step=step/2)
{
for(i=step; i<n; i++)
{
key=a[i];
for(j=i-step; j>=0; j=j-step)
{
if(a[j]>key)
a[j+step]=a[j];
else
break;
}
a[j+step]=key;
}
}
}
归并排序:
b[10000];
void mergesort(int a[],int low,int high)
{
int i,j,k,mid;
if(low==high)
return;
i=low;
k=i;
mid=(low+high)/2;
j=mid+1;
mergesort(a,low,mid);
mergesort(a,mid+1,high);
while(i<=mid&&j<=high)
{
if(a[i]<=a[j])
{
b[k]=a[i];
i++;
}
else
{
b[k]=a[j];
j++;
}
k++;
}
while(i<=mid)
{
b[k]=a[i];
i++;
k++;
}
while(j<=high)
{
b[k]=a[j];
j++;
k++;
}
for(i=low;i<=high;i++)
a[i]=b[i];
}