随笔 - 22  文章 - 0  评论 - 0  阅读 - 12085

各种排序算法的Python实现。

大学的算法导论课确实是混过去的,到了毕业的时候结果连个冒泡排序都不能裸写出来,只记得一些算法的基本理论,如分治法、递归、动态规划、回溯、图论、时间空间理论这些。大概知道这些排序算法的实现原理,真在纸上写出来脑子又是一团浆糊。最近在网上看到九章算法的网络课程费用是1299,团购价是799,真是狠不下心去买,也后悔大学里没好好学点算法,浪费了那些学费。

今天花了一天的时间用Python实现了7种排序算法,刚开始的时候觉得非常乱,完全不知道怎么写。不过写着写着思路就变得清晰了,对于排序算法的理解也越发清晰了,好像脑子里有一排数字在比来比去、移来移去,真的是非常有意思。真得感叹一声,抽象能力真的是软件工程师的必备能力啊

排序算法的本质其实是数字的各种比较方式和移动方式。回到我们大一C语言求一个数组中的最大数和最小数的那门上机课上。其实现原理很简单,就是把第一个数字作为初始数字跟后面的数字依次比较,若后面的数字比它大就跳过,若比它小就拿后面的数字替换掉它,直到遍历这个数组结束,最后得出的这个数就是最小数。
def the_min_of_lists(lists):
    min = lists[0]
    for i in range(1,len(lists)):
        if min > lists[i]:
            min,lists[i] = lists[i],min
    return min

  • 冒泡排序(bubble_sort)
        冒泡排序可以把排序的变化过程想象成气泡从水中升起一样,非常的富有美感。谁有程序员没有审美的?    
        上面我们通过拿第一个数跟后面的依次比较,最后得出了最小数。如果我们用同样的方法从剩余的数组中拿出第二小的数,拿出第三小的数,这样我们不就完成了数组的排序么?理一下思路,我们需要两层循环。
def bubble_sort(lists):
    count = len(lists)
    for i in range(0,count):
        for j in range(i+1,count):
            if lists[i] > lists[j]:
                lists[i],lists[j] = lists[j],lists[i]
    return lists

  • 插入排序(insert_sort)
        在玩扑克的时候我们通常会选择把抽到的牌插入到合适的位置,这样就可以保证在抽牌结束之后我们手中的牌是呈序列显示。借鉴此思路,我们可以拿当前的数与排序好的数组比较,若比已排好的数组中的数值小,则已排的数值后移,继续比较,指到遇到比已拍好的数值小的,则将其放入即可。后续重复进行此操作。
def insert_sort(lists):
    for i in range(1,len(lists)):
        key = lists[i]
        j = i-1
        while j>=0:
            if key < lists[j]:
                # key = lists[j]  #这样写会改变key的值,在插入排序的过程中,key值保持不变
                # lists[j+1] = lists[j]
                lists[j+1] = lists[j]
                lists[j] = key
            j-=1
    return lists
  • 快速排序(quick_sort)
        快速排序运用了典型的分治、递归的思想实现排序。取数组第一个数作为一个标准,拿数组的值依次跟它比较,比它小的就放在它的左边,比它大的就放在它的右边,此时这个标准数在排序后的数组中的位置就确定了。左右两边的数组采取上述相同的办法即可。
def quick_sort(lists,left,right):
    if left > right:
        return lists
    low,high = left,right
    key = lists[left] #key即是标准数
    while left < right:
        while left < right and lists[right] >= key:
            right-=1
        lists[left] = lists[right]
        while left < right and lists[left] <= key:
            left+=1
        lists[right] = lists[left]
    lists[right] = key
    quick_sort(lists,low,left-1)
    quick_sort(lists,right+1,high)
    return lists

  • 选择排序(select_sort)
        选择排序跟冒泡排序非常相似,冒泡排序是每次如果比它小就会交换位置,而选择排序不会马上交换位置,而是将比它小的数字的位置保存下来,直到循环结束后才交换位置。
def select_sort(lists):
    count = len(lists)
    for i in range(0,count):
        min = i
        for j in range(i+1,count):
            if lists[min] > lists[j]:
                min = j
        lists[min],lists[i] = lists[i],lists[min]
    return lists

  • 归并排序(merge_sort)(此命名应包含递归和合并的意思)
        归并排序将数组分成两个已排好的数组,拿这个两个数组的数字依次比较,比较小的那个就放到新的数组中,这样就完成了排序。关键算法部分是如果比较的过程。
#归并排序用两个已拍好的序列比较排序,采用递归的方式实现
def merge_sort(lists):
    if len(lists) < 2:
        return lists
    num = len(lists)/2
    left = merge_sort(lists[:num])
    right = merge_sort(lists[num:])
    return merge(left,right)

def merge(left,right):
    i,j=0,0
    result=[]
    while i<len(left) and j<len(right):
        if left[i] < right[j]:
            result.append(left[i])
            i+=1
        else:
            result.append(right[j])
            j+=1
    result += left[i:]  #若比较结束,将尚未比较完的那组加到result的后面
    result += right[j:]
    return result

  • 希尔排序(shell_sort)
        希尔排序是插入排序的一种优化形式,由shell提出,故命名为shell。其核心思想为每隔一个增量去取数组中的元素,将这些元素组成一个新的数组,对这个数组使用插入排序算法。然后依次减小这个增量继续执行上述操作,这些待增量等于1时,这个数组就会变得有序。
def shell_sort(lists):
    gap = 2
    group = len(lists)/gap
    while group > 1:
        for i in range(0,group):
            j = i+group
            while j < len(lists):
                k = j-group
                key = lists[j]
                while k>=0:
                    if key < lists[k]:
                        lists[k+group] = lists[k]
                        lists[k] = key
                    k -= group
                j+=group
        group /= gap
    return lists

  • 堆排序(heap_sort)
        堆排序是利用了最大堆的性质来进行排序的,即父节点大于左右子树。而我们可以把堆看成一个完全二叉树来进行处理。首先我们要将一个数组变成堆,这是一个建堆的过程,也是算法的核心。若得到堆结构的数组,再进行排序就会变得非常简单。
#堆排序分为最大堆和最小堆,是完全二叉树。
def build_heap(lists,size):
    for i in range(0,(size/2))[::-1]:
        adjust_heap(lists,i,size)

def adjust_heap(list,i,size):
    lchild = 2*i+1
    rchild = 2*i+2
    max = i
    if i < size/2:
        if lchild<size and list[lchild] > list[max]:
            max = lchild
        if rchild<size and list[rchild] > list[max]:
            max = rchild
        if max!=i:
            list[max],list[i] = list[i],list[max]
            adjust_heap(list,max,size)

def heap_sort(lists):
    size = len(lists)
    build_heap(lists,size)
    for i in range(0,size)[::-1]:
        lists[0],lists[i] = lists[i],lists[0]
        adjust_heap(lists,0,i)
  • 基数排序(radix_sort)
        网上的代码实现看得不太懂。主要是用于大数的比较,将数组中的数字前面补0使之保持位数一样,再依次从最高位比较即可。


算法高度体现了人类的智慧,是每一个软件工程师都必须掌握的技能。 纸上来得终觉浅,绝知此事要躬行。在脑海中实现一遍算法,然后在纸上写出来,这样可以避免提笔忘字的尴尬,也能飞快是计算机上打出来,是一个很不错的学习算法的方法。





来自为知笔记(Wiz)


posted on   风满楼。  阅读(1001)  评论(0编辑  收藏  举报
编辑推荐:
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
· .NET 适配 HarmonyOS 进展
阅读排行:
· 本地部署 DeepSeek:小白也能轻松搞定!
· 如何给本地部署的DeepSeek投喂数据,让他更懂你
· 从 Windows Forms 到微服务的经验教训
· 李飞飞的50美金比肩DeepSeek把CEO忽悠瘸了,倒霉的却是程序员
· 超详细,DeepSeek 接入PyCharm实现AI编程!(支持本地部署DeepSeek及官方Dee
< 2025年2月 >
26 27 28 29 30 31 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 1
2 3 4 5 6 7 8

点击右上角即可分享
微信分享提示