快速排序
昨天阿里3面,被问了快速排序,我看看之前的博客,这个排序漏了
快排的基本思想:
1.分而治之的思路,选取一个哨兵节点
2.将小于key的元素放在哨兵的左边,将大于key的元素放在右边
快排的时间复杂度为On(logn),最差的情况为O(n2),即所有元素都是有序的。每次只能走一位元素。
快排是不稳定的算法,无法保证相等两个元素的位置是原来的先后顺序
代码如下
/**
* Created by tj on 2018/7/8.
*/
public class Sort {
public int partition(int a[],int left,int right)
{
int start=left;
int last=right;
//
int key=a[right];
//对本次partition内的元素进行遍历,
while(start<last)
{
//设置结束条件,必须有等于,否则会卡在这个哨兵节点,以右边元素为哨兵,先遍历左侧
//取得索引,将last赋值给这个数,哨兵已经在key中,不用担心第一次的last元素
while(start<last&&a[start]<=key)
{
start++;
}
if(start<last)
{
a[last]=a[start];
}
//完成一次左边的遍历后,得到第一个大于key的值此时,last与start的元素值相同
//对右侧元素遍历,得到第一个小于的元素,并将该小于的数值赋值给start
while(start<last&&a[last]>=key)
{
last--;
}
if(start<last)
{
a[start]=a[last];
}
//一次遍历结束,获得第一个大于的元素与第一个小于的元素,接着下一轮,直到start==last
}
a[last]=key;
return last;
}
public void quickSort(int a[],int left,int right)
{
//分割点
int location;
if(left<right)
//有一个判断的结束标记,否则将会不断location无线递归
{
location=partition(a,left,right);
//对左边快排,分而治之的思想
quickSort(a,left,location-1);
//右边快排
quickSort(a,location+1,right);
}
}
public static void main(String[]args){
Sort newTest=new Sort();
int a[]={5,4,9,1,7,6,2,3,5};
newTest.quickSort(a,0,8);
for(int i=0;i<9;i++)
{
System.out.println(a[i]+" ");
}
}
}
运行结果:
1 2 3 4 5 5 6 7 9
算法分析:
根据哨兵节点,在左侧获得比其大的元素位置i,赋值给右侧值;
对右侧遍历,获得小于哨兵元素位置j,赋给i
一次遍历完成两个元素的位置交换
partition也可以换成:
int partition(int a[],int left,int right)
{
int start=left;
int last=right;
int key=a[right];
int temp;
printf("%d\n ",key);
while(start<last)
{
//小于等于
while(start<last&&a[start]<=key)
{
start++;
}
while(start<last&&a[last]>=key)
{
last--;
}
//从前面与后面分别找,找到后前后进行交换元素
if(start<last)
{
temp=a[start];
a[start]=a[last];
a[last]=temp;
}
}
//将正确的值入位
a[right]=a[last];
a[last]=key;
return last;
}
后面这个算法虽然比较直观,直接找到小于与大于的元素,然后交换
在循环结束后,将哨兵放入正确的位置。
但多了几步赋值过程