算法导论-快速排序

快速排序

昨天阿里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;
}

后面这个算法虽然比较直观,直接找到小于与大于的元素,然后交换
在循环结束后,将哨兵放入正确的位置。
但多了几步赋值过程

猜你喜欢

转载自blog.csdn.net/tang_jin2015/article/details/80957840
今日推荐