一、算法思想
快速排序利用的是一种分治思想的排序方法,也是冒泡排序的一种优化。
二、排序过程
1、先选取一个值作为快速排序的基准,作为学习可以选择第一个数据作为基准,将比基准大的数放在右边,比基准小的数放在左边
2、将第一个数据下标记为i,最后一个数据下标记为j,选取第一个作为基准后,就从右向左进行寻找,如果数据比基准数大,就继续向左找(j--),如果数据比基准数小,就将该数放到基准数的位置,转向同理从左向右寻找比基准数大的值,如此往复,直至i=j时,一次排序就结束,基准数左边数全比基准数小,基准数右边全比基准数大,基准数到达最终有序时的位置。
3、将基准数左右两部分继续进行2操作(分治),直至每一个部分的无序区的数据量为一(此时也就是每一个部分变成有序,整体也就有序)
三、代码实现
递归版代码如下:
void QuickSort(int *a,int left,int right)
{
if(left>=right)//递归退出条件
{
return ;
}
int i=left;
int j=right;
int tmp=a[i];//首元素作为基准数
while(i<j)
{
while(i<j&&a[j]>=tmp)//此处必须加等 否则当最后只剩两个相等的数时 就会死循环下去
{
j--;
}
a[i]=a[j];
while(i<j&&a[i]<=tmp)
{
i++;
}
a[j]=a[i];
}
a[i]=tmp;
QuickSort(a,left,i-1);//分开后的左右两部分再分别进行快速排序
QuickSort(a,i+1,right);
}
非递归版代码如下(就是利用出栈与入栈操作):
1.将上面的void QuickSort(int *a,int left,int right)改为带有返回值的int QuickSort(int *a,int left,int right)函数 返回值为当i
等于j时候的下标i或j
2.定义一个栈(这里简易代表为Stack mystack,实现方法与普通C语言写的栈一样,需要用到PushStack(struct Stack*mystack,int i)入栈函数,PopStack(struct Stack *mystack,int i)出栈函数与Empty(struct Stack *mystack))判空函数
void QuickSortStack(struct Stack *mystack,int *a,int left,int right)
{
int tmp=0;//用于记录基准数一次排序后的下标(也就是分割点)
PushStack(mystack,left);//先要对栈进行初始化 以便可以进入循环
PushStack(mystack,right);
while(!Empty(mystack))
{
right=PopStack(mystack);
left=PopStack(mystack);
tmp=QuickSort(a,left,right);
if(left<tmp-1)//如果分段结果中其中一段只有一个数据 则其有序 无需再继续进行排序
{
PushStack(myastck,left);//这里一定要注意要根据你前面的出栈顺序进行入栈 否则无法实现配对 分段便会出现错误 我这里是先入起始再入终止 出栈时便是先出终止再出起始
PushStack(mystack,tmp-1);
}
if(right>tmp+1)
{
PushStack(myastck,tmp+1);
PushStack(mystack,right);
}
}
}
补充:快速排序为不稳定排序(简单理解为快速排序导致数据进行了跳跃式的交换 原相等两个数据的相对位置发生了改变 例 下标为1的数据2排在下标为2的数据2的前面 快速排序以后下标为2的数据2当前的下标值先于原来下标为1的数据2)
时间复杂度平均为O(nlogn);