04-10大排序

十大经典排序算法

https://mp.weixin.qq.com/s/putWU_FBF7cZJkuVpCy0sw

img

1.冒泡

def bubble_sort(data):
    for i in range(len(data)-1):
        exchange = False
        for j in range(len(data)-i-1):
            if data[j]>data[j+1]:
                data[j],data[j+1]=data[j+1],data[j]
                exchange=True
        if not exchange:  # 一趟没有交换,说明data是有序的
            return data
    return data

2.快排

def once_sort(data,left,right):
    temp = data[left]       # 选出第一个元素作为temp
    while left<right:
        while left<right and data[right]>temp:
            right -=1
        data[left]=data[right]

        while left<right and data[left]<temp:
            left+=1
        data[right]=data[left]

    data[left]=temp
    return left

def quick_sort(data,left,right):
    if left<right:
        mid = once_sort(data,left,right)
        data = quick_sort(data,left,mid-1)   # temp左边排序
        data = quick_sort(data,mid+1,right)  # temp右边排序,不用管mid
    return data

3.选择排序

li = [4,5,6,,7,8,9,9,54]
1、选择 li[0:n],最小下标为0,找出最小的元素,所对应的下标与0交换,交换值
2、选择 li[1:n], 最小下标为1,找出最小的元素,所对应的下标与1交换,交换值
3、反复
def select_sort(data):
    for i in range(len(data)-1):  # 当前N-1个数字排列好了,最后一个也就好了
        min_index = i
        for j in range(i+1,len(data)):  # [1~n]
            if data[j]<data[min_index]:
                min_index = j           # 最小下标交换

        if min_index != i:
            data[min_index],data[i]=data[i],data[min_index]

    return data

4.插入排序

li = [43,34,354,342,21]
1、把第一个当做有序区,其他作为无序区
2、从[1:n]开始,选取temp=li[i], j =i-1
3、li[i],与li[i-1]比较 , 每次与前一个比较
4、若li[i]比temp大的话,li[i]向后移动1位
def insert_sort(data):
    for i in range(1,len(data)):
        temp = data[i]  # 取出当前为未排序的数
        j = i-1
        while j>=0 and data[j]>temp:  # 未排序的temp < 排序的数
            data[j+1]=data[j]        # 排序好的数,往后移一位
            j -= 1
        
        data[j+1] = temp  # 未排序的temp > 排序的数,将temp插入到空出的位置

    return data

5.希尔排序

分组插入排序
1、分组标准gap=len(data)//2,gap//=2
2、插入排序
3、gap替换1
def shell_sort(data):
    gap = len(data)//2  # 取li长度的1/2
    while gap>0:
        # 插入排序 gap ---> 1
        for i in range(gap,len(data)):
            temp = data[i]
            j = i-gap
            while j >= 0 and data[j]>temp:
                data[j+gap]=data[j]
                j -= gap
            data[j+gap] = temp
    
        gap //= 2

    return data

6.二路归并排序

二路归并
1. 先分解
    将列表分解成一个个元素
2. 再合并
    合并成 2段有序列表,列表越来越大

# merge 
英 [mɜ:dʒ]      美 [mɜ:rdʒ]      
融入;(使)混合;相融;渐渐消失在某物中 
def merge(data,left,mid,right):
    temp = []
    i,j = left,mid+1

    # 两段有序,[left~mid]   [mid+1~right]
    while i<=mid and j<=right:
        if data[i]<data[j]:
            temp.append(data[i])
            i+=1
        else:
            temp.append(data[j])
            j+=1
    
    # 一段已经为空
    while i<=mid:      # i=mid也是要计算的 
        temp.append(data[i])
        i+=1
    while j<=right:    # j=mid+1,没有=的话,就会漏掉mid
        temp.append(data[j])
        j+=1

    # temp赋值给data[left:right]
    data[left:right+1] = temp
    return data


def merge_sort(data,left,right):
    if left<right:
        mid = (left+right)//2

        # 分解
        merge_sort(data,left,mid)
        merge_sort(data,mid,right)

        # 合并
        merge(data,left,mid,right)

    return data

7.堆排序

1.根据列表,构造堆,调整使堆有序
2.得到堆顶元素,为最大元素,去掉堆顶
3.将堆最后一个元素放到堆顶
4.调整使堆有序,堆顶元素为第二大元素
5.重复3

非线性排序:通过比较元素间的相对次序,复杂度不能突破O(nlogn)

线性排序:可以达到线性时间运行

8.计数排序

抽屉原理,统计每个数出现的次数
小范围:输入的数据必须是有确定范围的整数。
时间复杂度O(n+k)   n个0~k之间的整数
空间复杂度O(n+k)
1.找出待排序数组的min,max
2.创建max+1长度的数组空间,元素初始化为0
3.统计重复元素出现的次数
4.对所有的计数累加
5.反向填充目标数组

9.桶排序

鸽巢排序,稳定
要求:data服从均匀分布
时间复杂度:当n=k时,达到O(n), O(n+k), 最坏O(n^2)
空间复杂度: O(n+k)
步骤:
1.设置一个定量的数组当作空桶;
2.遍历输入数据,并且把数据一个一个放到对应的桶里去;
3.对每个不是空的桶进行排序;
4.从不是空的桶里把排好序的数据拼接起来。

10.基数排序

时间复杂度:O(n*k)  k为关键字
空间复杂度: O(n+k)
1.按照低位先排序,然后收集
2.按照高位排序,再收集
3,依次类推
posted @ 2018-10-07 21:26  venicid  阅读(138)  评论(0编辑  收藏  举报