(原创)选择排序与快速排序及D&C算法的延伸

一、选择排序

(尊重原创,转载请注明出处。)

选择排序是一种速度较慢的排序算法,运行时间为O(n2),这里只进行简单的逻辑分析和实现。大致是对待分析的数组(或者其它数据结构)尽心一遍遍的遍历,每次都找出里头最大或最小的那个,然后放入一个新的数组。实现如下:

def find_max(list):
    max = list[0]
    index = 0;
    for i in range(1,len(list)):
        if list[i] >= max:
            max = list[i]
            index = i
    return index

def sort_list(list):
    new_list = []
    while len(list) > 0:
        index = find_max(list)
        new_list.append(list.pop(index))
    return new_list

print sort_list([3,2,4,3,7,6,0,7,6,3]);

二、快速排序(最快的排序算法之一,D&C的典范)

1. 在将快速排序之前,我们先讨论一种著名的递归式问题解决方法——分而治之(D&C)。

D&C策略的包括两个步骤:
a. 找出一个尽可能简单的基线条件。
b. 不断的将问题分解,缩小规模,使其越来越靠近基线条件,直到最终符合基线条件。

2. 快速排序的逻辑分析

a. 先在数组中找一个元素作为基准值。(注意,基准值的选择直接影响了快速排序的性能高度,后面再讨论,这里先将第一个元素作为基准值)然后将数组中所有小于它的元素放在左边,大于它的元素放在右边。(这里是从小到大排序,反之)。
b. 对左右两边的元素分别再选出基准值,在分成两边。
c. 不断重复该步骤。
d. 当某边的元素个数为1个或为0个时,则该处达到基线条件。
e. 当所有的边都达到基线条件时,排序完成。

3. 分析——快速排序的实现思想正是使用了D&C策略

a. 首先找到了基线条件,某个数组的个数为1或为0时,该序列为排好的顺序。
b. 当数组个数为3个时,取出一个,进行对分,剩下的两个就满足了。
c. 4个时,可能会出现一边为0,一边为3的情况,再将3的那边进行对分,又可以满足了。
d. 以此类推,不管数组有多长,只要对整个数组进行不断的对分,减小规模,最后总能满足基线条件,达到排序的目的。
以上的的证明方式即为归纳证明。

4. 归纳证明

归纳证明是一种证明算法可行性的方式。包括两个步骤:基线条件和归纳条件。
即先证明对0个或者1个元素是有效的(基线条件),然后在证明如果0个或者1个元素有效,那么3个、4个、5个.........任意长度都有效(归纳条件)。
归纳证明经常与D&C策略配合使用。

5.基准值的选择

我们知道,选择排序的运行时间为O(n2),而快速排序的运行时间平均情况下为O(n*log n),最糟情况下为O(n2)。
a. 最糟情况:当我们每次都选择第一个数作为基准值的时候,调用栈的高度将是n,所以在栈调用上的花费的运行时间为O(n),且每次调用的运行时间为O(n),于是算法最终的运行时间为:O(n)*O(n)=O(n2)
b. 平均情况:如果我们每次都尽量的取靠近中间的值,那么调用栈的高度将是log n,所以在栈调用上花费的运行时间为O(log n),又因为每次调用的运行时间为O(n),于是算法最终的运行时间为:O(n)*O(log n)=O(n*log n)
其实只要我们每次都随机取一个元素作为基准值,就可以达到平均情况。下面贴上最糟情况的实现:

def quick_sort(list):
    if len(list) < 2:
        return list;
    else:
        v_num = list[0];
        v_front = [];
        v_behind = [];
        for i in list[1:] :
            if i <= v_num:
                v_front.append(i);
            else:
                v_behind.append(i);
        return quick_sort(v_front) + [v_num] + quick_sort(v_behind);

print quick_sort([3,5,1,2,6,8,7,0,123,213,432,21]);


以上就是选择排序和快速排序啦,有错的地方,欢迎大家评论指正!!


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值