其他算法(希尔排序,计数排序,桶排序,基数排序)

1.希尔排序

  属于一种插入分组排序算法

  首先取一个整数d1=n/2,将元素分为d1个组,每组相邻量元素之间距离为d1,在各组内进行直接插入排序;

  取第二个整数d2=d1/2,重复上述分组排序过程,直到di=1,即所有元素在同一组内进行直接插入排序。

  希尔排序每趟并不使某些元素有序,而是使整体数据越来越接近有序;最后一趟排序使得所有数据有序。

例:

  对于如下数列,第一次d=4

  我们可以做如下变换

  

  归位

  第二次d=2,我们在做交换

  归位

  第三次d=1,我们在做交换,此时是相邻元素间做交换,这步还不是太直观

  

代码

def insert_sort_d(li, d):
    for i in range(d, len(li)): # i表示摸到牌的位置
        j = i - d
        tmp = li[i]
        while j >= 0 and li[j] > tmp:
            li[j+d] = li[j]
            j -= d
        li[j+d] = tmp


def shell_sort(li):
    d = len(li) // 2
    while d > 0:
        insert_sort_d(li, d)
        d //= 2

li = [5,7,4,6,3,1,2,9,8]
shell_sort(li)
print(li)

2.计数排序

  现在有一个列表,已知列表中的数范围都在0到100之间。设计算法在O(n)时间复杂度内将列表进行排序

  创建一个列表,统计每个数出现次数

import random

def count_sort(li, max_val=100):
    count = [0 for i in range(max_val+1)]
    for v in li:
        count[v] += 1
    li.clear()
    for a,b in enumerate(count):
        for i in range(b):
            li.append(a)

li = [random.randint(0,100) for i in range(100)]
count_sort(li)
print(li)

3.桶排序(最快最简单的排序)

  基本思想是将一个数据表分割成许多个buckets,每个buckets在各自排序

代码

def bucket_sort(lis):
    max_num = max(lis)
    # 创建一个元素全是0的列表当作桶
    bucket = [0] * (max_num + 1)
    # [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    # 把所有元素放入桶内,即对应元素+1,桶内没有就是0
    for i in lis:
        bucket[i] += 1
    # [0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1]
    # 存储排序好的元素
    sort_num = []
    # 取出桶内元素
    for j in range(len(bucket)):
        if bucket[j] != 0:
            # 这步用于保证不去重操作
            for k in range(bucket[j]):
                sort_num.append(j)
    return sort_num


lis = [10, 5, 2, 7, 6, 8, 3, 1, 4]
print(bucket_sort(lis))

说明:

  桶排序是稳定的,它是常见排序中最快的一种,通常情况下比快排还要快

  桶排序最大的问题就是消耗的内存比较大,算是牺牲了空间,换取了时间

4.基数排序(时间复杂度O(kn),空间复杂度O(k+n),k代表数字位数) 

  多关键字排序:假如现在有一个员工表,要求按照薪资排序,年龄相同的员工按照年龄排序

  关键点,我们可以对个位和个位比较,十位和十位比较

import math
import random

def list_to_buckets(li, i):
    # i 表示按哪一位装桶 0表示个位 1表示十位
    buckets = [[] for _ in range(10)]
    for val in li:
        digit = val // (10 ** i) % 10
        buckets[digit].append(val)
    return buckets


def buckets_to_list(buckets):
    return [val for bucket in buckets for val in bucket]
    # li = []
    # for bucket in buckets:
    #     for val in bucket:
    #         li.append(val)
    # return li


def radix_sort(li):
    max_val = max(li)
    k = math.floor(math.log10(max_val)) + 1 # n表示需要装拆桶多少次
    for i in range(k):
        li = buckets_to_list(list_to_buckets(li, i))
    return li



li = list(range(100))
random.shuffle(li)
print(radix_sort(li))

 

posted @ 2018-10-01 23:29  -Learning-  阅读(350)  评论(0编辑  收藏  举报