算法学习-02(希尔排序,计数排序,桶排序,基数排序)

希尔排序

# 希尔排序
# 希尔排序是对插入排序的升级改造
# 它的大致流程是
# 1、将长度为n的序列 分为d = n//2组
# 2、使每一组变的有序
# 3、将序列分为 d1 = d // 2 组
# 4、将每一组变的有序
# 5、直到最后 d 小于等于 0

def inster_sort_gap(li,gap):
    for i in range(gap,len(li)):
        tmp = li[i]
        j = i - gap
        while j >= 0 and tmp > li[j]:
            li[j+gap] = li[j]
            j -= gap
        li[j+gap] = tmp

def shell_sort(li):
    n = len(li)
    gap = n // 2
    while gap > 0:
        inster_sort_gap(li,gap)
        gap //= 2

计数排序

#计数排序
    对列表进行排序,已知列表中的数范围都在0到100之间。
    设计时间复杂度为O(n)的算法
#eg:
    1 3 2 4 1 2 3 1 3 5
# 分配0-5六个桶,遇到一个数,在相应的桶上加一
0
1 1+1+1
2 1+1
3 1+1+1
4 1
5 1

复杂度 O(n)
占用空间 O(n)

# 计数排序
def count_sort(li, max_count):
    count = [0 for _ in range(max_count+1)]
    for i in li:
        count[i] += 1
    li.clear()
    for ind, val in enumerate(li):
        for i in range(val):

桶排序

# 如果计数排序中,如果元素的范围比较大(比如在1到1亿之间),如何改造算法

# 桶排序(Bucket Sort):
    把元素放在不同的桶里,对每个桶里面的元素保持有序

def bucket_sort(li,n=100,max_num=10000):
    """
    :param li: 需要排序的列表
    :param n: 分多少个桶
    :param max_num: 最大数
    :return:
    """
    buckets = [[] for _ in range(n)]
    for var in li:
        i = min(var // (max_num // n), n-1)  # i 表示var放到几号桶里面
        buckets[i].append(var)  # 把var 放到对应的桶里
        # 保持桶内的顺序
        for j in range(len(buckets[i])-1, 0, -1):
            if buckets[i][j] < buckets[i][j-1]:
                buckets[i][j], buckets[i][j-1] = buckets[i][j-1], buckets[i][j]
            else:
                break
    sorted_li = []
    for buc in buckets:
        sorted_li.extend(buc)
    return sorted_li
# 范围特别大,用的不是太多
# 桶排序的效率
# 取决于数据的分布,也就是需要对不同数据排序时,采取不同的分桶策略
    # 平均分布---
    # 不平均,90%的数在某一个桶里
    #
# 平均情况时间复杂度:O(n+k)
# 最坏情况时间复杂度:O(n**2k)
# 空间复杂度:O(nk)
# 还可以优化,比如内部排序过程

基数排序

# 先行知识点: 基于多关键字排序
    eg:对员工表进行薪资排序,薪资相同的按照年龄排序
          先按照年龄进行排序,再按照薪资进行稳定的排序

#对 32,13,19,52,54,94,3,17 的排序,也可以看作是多关键字排序
#先对个位数进行桶排序,再对十位数进行桶排序

时间复杂度,O(kn)
空间复杂度,O(k+n)
k表示数字位数

快排 nlogn  # logn=log(2,n)
计数排序 kn  # k=log(10,n)

当长度是固定的,数值范围越来越大,达到一定程度100000000...,基数排序的性能会变差

缺陷在于,需要占用空间

字符串的排序
# abcd
# ab00  #在面加0

数字排序,是在前面001 ,012,123

小数?

# 基数排序
def radix_sort(li):
    max_num = max(li)  # 取出最大值,99->2, 888->3, 10000->5
    it = 0  # 7--> it=0  77-->it=2, it等于0的时候,取个位数,it=1的时候,取的是十位数
    while 10 ** it <= max_num:          # 在每次里面进行分桶
        buckets = [[] for _ in range(10)]  # 0-9 共计 10个 桶
        for var in li:
            # 分到几号桶,看的是哪一位的数
            # 怎么取出对应位置上的数字
            # 987 it=0 取第一位7 987%10=7
            #     it=1 取第二位8 987//10=98 98%10=8
            #     it=2 取第三位9 987//100=9 9%10=9
            # 所以,公式: (987//10**it) % 10
            digit = (var // 10 ** it) % 10
            buckets[digit].append(var)
        # 已经做好了分桶
        # 把数重新写进li
        li.clear()
        for buc in buckets:
            li.extend(buc)
        it += 1

原文地址:https://www.cnblogs.com/yxiaodao/p/11933531.html

时间: 2024-12-24 11:28:29

算法学习-02(希尔排序,计数排序,桶排序,基数排序)的相关文章

基数、希尔、计数、桶排序

一.基数排序 import random from timewrap import * def list_to_buckets(li, iteration):#这个是用来比较每个位置的大小的数字 """ 因为分成10个本来就是有序的所以排出来就是有序的. :param li: 列表 :param iteration: 装桶是第几次迭代 :return: """ buckets = [[] for _ in range(10)] print('bu

九大排序算法及其实现- 插入.冒泡.选择.归并.快速.堆排序.计数.基数.桶排序

  闲着的时候看到一篇“九大排序算法在总结”,瞬间觉得之前数据结构其实都有学过,但当初大多数都只是老师随口带过,并没有仔细研究一下.遂觉:这是欠下的账,现在该还了.   排序按照空间分类: In-place sort不占用额外内存或占用常数的内存 插入排序.选择排序.冒泡排序.堆排序.快速排序. Out-place sort:归并排序.计数排序.基数排序.桶排序. 或者按照稳定性分类: stable sort:插入排序.冒泡排序.归并排序.计数排序.基数排序.桶排序. unstable sort

算法学习【第五篇】:排序算法与二分法

排序算法稳定性 冒泡排序 思路:首先,列表每两个相邻的数比较大小,如果前边的比后边的大,那么这两个数就互换位置.就像是冒泡一样 代码关键点 趟数:n-1趟 无序区 依次类推就会得到排序结果.冒泡排序的效率还是很低的 代码示例    (这是基于顺序表实现的,链表还要关注一下节点) # 思路:列表中两个相邻的数比较大小,如果前边的比后边的大,那么这两个就互换位置 def bubblr_sort(li): for i in range(1,len(li)-1):#表示趟数 for j in range

经典算法之排序问题(二):桶排序、鸽巢排序

鸽巢排序: 鸽巢排序, 也被称作基数分类, 是一种时间复杂度为(Θ(n))且在不可避免遍历每一个元素并且排序的情况下效率最好的一种排序算法. 但它只有在差值(或者可被映射在差值)很小的范围内的数值排序的情况下实用. 当涉及到多个不相等的元素, 且将这些元素放在同一个"鸽巢"的时候, 算法的效率会有所降低.为了简便和保持鸽巢排序在适应不同的情况, 比如两个在同一个存储桶中结束的元素必然相等 我们一般很少使用鸽巢排序, 因为它很少可以在灵活性, 简便性, 尤是速度上超过其他排序算法. 事实

算法学习之希尔排序的简洁实现

Java 代码实现: 1 @Test 2 public void ShellSort(){ 3 4 int[] array={9,8,7,6,5,4,3,2,1}; 5 int j,temp; 6 7 System.err.println(Arrays.toString(array)); 8 //gap为步长,每次取半 9 for(int gap=array.length/2;gap>0;gap/=2){ 10 for(int i=gap;i<array.length;i++){ 11 tem

排序算法学习之希尔排序

直接插入排序对待排数量较少且基本有序的序列,其执行效率是非常高的,希尔排序正是利用了这点,将一个无序的序列拆分成几个子组,然后对几个子组分别进行插入排序. 注意,这儿的分组并不是简单的{a1,a2,a3,b1,b2,b3,c1,c2,c3}(相同字母为一组),而是进行{a1,b1,c1,a2,b2,c2,a3,b3,c3},因为我们一次分组排序的目的是将各个子组中较小的放到整个序列前面,较大的放到整个序列后面,以形成基本有序,然后减少分组数量{a1,b1,a2,b2,a3,b3,a4,b4,a5

啊哈!算法 学习1 排序 - 简单的桶排序

//排序10个0-100之间数字 //定义int数组 //这里生成包含101个个数数组是以为要对应输入的值 到对应到数组的index 譬如输入10 对应a[10] int a[101]; //数组赋值 生成 for (int i = 0; i < 101; i++) { a[i] = 0; } //声明变量 int x; //循环输入10个数字 for (int i = 0; i < 10; i++) { //读取输入值 scanf("%d",&x); //输入值对

算法学习笔记(四):合并排序

算法思想:基本的思想为分治算法,也就是将一个问题分成多个更小的部分递归解决.具体到合并排序,就是将待排序序列分为小的序列,递归进行排序,然后合并. 步骤: 1.分解:将n个元素分成各含n/2个元素的子序列 2.解决:用合并排序对两个子序列递归排序 3.合并:合并两个已排序的子序列以得到排序结果 在对子序列排序时,其长度为1时递归结束. 算法复杂度:O(nlgn) 代码实现: void divide_sort(int arr[],int p,int r) { if(p<r) { int q = (

数据结构与算法学习02:链表

一.链表 链表是一种动态集合,它是由一系列元素组成的一个列表. 数组也可以实现列表这种数据结构,但数组是静态的,而链表是动态. 通常,我们定义一个结点类(或结构体)来表示链表的元素,它由两部分组成:数值域和指针域.数值域存储当前结点的键,指针域存储下一个节点的地址. template <class Type> struct nodeType { Type info; nodeType<Type> *link; }; 链表的一些基本操作如下: 初始化为空表 判断是否为空 打印(遍历)