排序算法之快速排序

 

 

1.快速排序的思路(从小->大)

快速排序在开始时,都会取一个序列最左边的数作为一个key值,目的就是调整序列------把比key值小的数放到key的左边,比key大的数放到key的右边。

然后再以key值的位置为界,key值位置以左的作为一个序列,key值位置以右的又作为一个序列,再在新序列中重复上面的操作。

如:

 

01234
46152

 

首先,4作为key值,第一轮把4放在序列的中间位置,比4小的在4的左边,比4大的在4的右边,得:(为什么排成这样先不用理,等等介绍)

 

01234
21456


然后再以4以左的新序列重复上述操作,再以4已右的新序列重复上面的操作。就是一直把各个序列的第一个数放到合适的位置,来排序整个序列。

 

4以左的序列,key=2:

 

01
21

排完后就是1,2.

以右的序列一样道理

 

具体方法:(小--->大)

以序列: 4,6,1,5,2 为例

 

01234
46152

有两个标记位置的变量 left 和 right。

left一开始指向最左边,就是left = 0,right指向最右边,right = 4

key 一开始等于 序列左边的数,所以key = 4.

 

 


然后就得到第一轮的值:

 

 

01234
21456


可以看到比4小的值已经全部丢到4的左边去,比4大的值也全部被丢到4的右边去

最后分别在左边序列 和 右边序列递归重复上面的操作就可以了。

 

代码:

版本1:


def QuickSort(a,left,right):
    if left>right:
        return
    i = left
    j = right
    key = a[left]
    while i!=j: #左、右指针重合时结束
        #先从右向左扫描
        while i<j and a[j]>=key:
            j-=1
        #再从左向右扫描 顺序一定要先从右开始,否则会错
        while i<j and a[i]<=key:
            i+=1
        t1 = a[i]
        a[i] = a[j]
        a[j] = t1
    #当 i = j时,盖位置的值与a[left]交换
    t2 = a[i]
    a[i] = a[left]
    a[left] = t2
    QuickSort(a,left,i-1)
    QuickSort(a,i+1,right)
    return a
l = [3,1,2,5,9]
res = QuickSort(l,0,len(l)-1)
print(res) #[1, 2, 3, 5, 9]

3. 时间复杂度

快速排序的时间复杂度是分最优情况和最坏情况的。

最优情况:O(nlogn)

最坏情况:O(n^2)

解释:

快速排序的一次划分算法从两头交替搜索,直到left和right重合,因此其时间复杂度是O(n);但整个快速排序算法的时间复杂度与划分的趟数有关。

最优情况:理想的情况是,每次划分所选择的中间数恰好将当前序列几乎等分,经过log2n趟划分,便可得到长度为1的子表。这样,整个算法的时间复杂度为O(nlog2n)。

最差情况:每次所选的中间数是当前序列中的最大或最小元素,这使得每次划分所得的子表中一个为空表,另一子表的长度为原表的长度-1。这样,长度为n的数据表的快速排序需要经过n趟划分,使得整个排序算法的时间复杂度为O(n^2)

更简洁的版本2:

def QuickSort(a):
    if len(a)<2:
        return a
    else:
        key = a[0]
        less = [i for i in a[1:] if i <=key]
        geater = [i for i in a[1:] if i > key]
        return QuickSort(less)+[key]+QuickSort(geater)
l = [3,1,2,5,9]
res = QuickSort(l)
print(res) #[1, 2, 3, 5, 9]

 

Java版本代码:

public class QuickSort {
    public static void quickSort(int[] arr,int left,int right){
        if(left>=right) return;
        int i = left;
        int j = right;
        int key = arr[left];
        while(i!=j){
            while(i<j && arr[j]>=key){
                j--;
            }
            while(i<j && arr[i]<=key){
                i++;
            }
            if(i!=j){
                int t = arr[i];
                arr[i]=arr[j];
                arr[j]=t;
            }
        }
        arr[left]=arr[i];
        arr[i]=key;
        quickSort(arr,left,i-1);
        quickSort(arr,i+1,right);
    }
    public static void main(String[] args) {
        int[] arr = {3,2,1,4,2,3,1};
        quickSort(arr,0,arr.length-1);
        String str="";
        for(int a:arr){
            str+=a;
        }
        System.out.println(str);//1122334
    }
}

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值