python排序算法

python排序算法

  • 冒泡排序法

    def bubble_sort(alist):
        """冒泡排序"""
        for j in range((len(alist)-1)):
            count = 0
            for i in range((len(alist)-j-1)):
                if alist[i] > alist[i+1]:
                    alist[i],alist[i+1] = alist[i+1],alist[i]
                    count += 1
            if 0 == count:
                return   # 如果是有序序列  直接结束函数
    
    if __name__ == "__main__":
        li = [1,4,2,4,56,9,3,12,546,5,7]
        print(li)
        bubble_sort(li)
        print(li)
    
    
    
    """
    时间复杂度
    最优时间复杂度:O(n) (表示遍历一次发现没有任何可以交换的元素,排序结束。)
    最坏时间复杂度:O(n2)
    稳定性:稳定
    
    """
    
    # 运行结果
    [1, 4, 2, 4, 56, 9, 3, 12, 546, 5, 7]
    [1, 2, 3, 4, 4, 5, 7, 9, 12, 56, 546]
    
  • 选择排序

    def select_sort(alist):
        """选择排序"""
        min_index = 0
        n = len(alist)
        for i in range(n-1): # j : n-2 第一个数遍历 到最后第二个
            min_index = i
            for j in range(i+1,n): # 从i+1个下标开始
                if alist[min_index] > alist[j]: # 发现后面的数大于前面的数时
                    min_index = j  # 把下标赋值给 min_index
            alist[i],alist[min_index] = alist[min_index],alist[i] # 交换 当前i下标的值  和  min_index下标的值
    
    
    if __name__ == "__main__":
        alist = [2,43,1,14,52,2341,512,21,3413,3123,5,31,65,4,34,2]
        select_sort(alist)
        print(alist)
    
    
    """
        时间复杂度
        最有时间复杂度:O(n^2)
        最坏时间复杂度:O(n^2)
        稳定性:不稳定(考虑升序每次选择最大的情况)
    
    """
    
    # 运行结果
    [1, 2, 2, 4, 5, 14, 21, 31, 34, 43, 52, 65, 512, 2341, 3123, 3413]
    
  • 插入排序

    """
    def insert_sort(alist):
        "插入排序"
        n = len(alist)
        for j in range(n-1):
            for i in range(j+1,n):
                if alist[i] < alist[j]:
                    alist[i],alist[j] = alist[j],alist[i]
    """
    
    def insert_sort(alist):
        """插入排序"""
        n = len(alist)
        # 从右边的无序列表中取出多少个元素执行这样的过程 
        for j in range(1,n):
    
            # i 代表内存循环的起始位置
            i = j
    
            # 执行从右边的无序列表中取出第一个元素,即i的位置的元素,然后将其插入到前面的正确位置中
            while i > 0: # 可以还成 for i range(j,0,-1)
                if alist[i] < alist[i-1]: # 这是执行的有序列表 把数插入到 相应的位置
                    alist[i],alist[i-1] = alist[i-1],alist[i]
                    i -= 1
                else: # 第一次的时候 如果i下标的这个元素大于 i-1(有序序列的最大元素) 下标的这个元素 那么不用交换了 直接退出循环 因为前面的本来就是有序的
                    break
    
    
    """
    时间复杂度
    最优时间复杂度:O(n) (升序排列,序列已经处于升序状态)
    最坏时间复杂度:O(n2)
        稳定性:稳定
    """
    
    
    if __name__ == "__main__":
        alist = [1,2,4,1,23,12,31,4,12,24,1,245,1251,4,1,3,1,234]
        insert_sort(alist)
        print(alist)
    
    # 运行结果
    [1, 1, 1, 1, 1, 2, 3, 4, 4, 4, 12, 12, 23, 24, 31, 234, 245, 1251]
    
  • 希尔排序

    def shell_sort(alist):
        """希尔排序"""
    
        n = len(alist)
        # gap间隔
        # gap = 4
        gap = n // 2
       
        # gap变化到0之前,插入算法执行的次数
        while gap > 0: # gap 步长包括1 不包括0
        
            # 插入算法,与普通的插入算法的区别就是gap步长
            for j in range(gap,n):
                # j = [gap,gap+1.gap+2,gap+3....n-1]
                i = j
                while i > 0:
                    if alist[i] < alist[i-gap]:
                        alist[i],alist[i-gap] = alist[i-gap],alist[i]
                        i -= gap
                    else:
                        break
            # 缩短gap步长
            gap //= 2
    
    """
    时间复杂度
    最优时间复杂度:根据步长序列的不同而不同
    最坏时间复杂度:O(n2)
        稳定性:不稳定
    """
    
    
    if __name__ == "__main__":
        li = [21,4,1,24,1,1,23,1,4,124,3,41,3,1,3,1,341,2] 
        shell_sort(li)
        print(li)
    
    # 运行结果
    [1, 1, 1, 1, 1, 1, 2, 3, 3, 3, 4, 4, 21, 23, 24, 41, 124, 341]
    
  • 快速排序

    def quick_sort(alist, first, last):
        """快速排序"""
    
        if first >= last:
            return
    
        mid_value = alist[first] # 这个位置 必须是第一个元素 所以是first
        low = first
        high = last
    
        while low < high:
            # high左移
            while low < high and alist[high] >= mid_value:
                high -= 1
            alist[low] = alist[high]
    
            # low右移
            while low < high and alist[low] < mid_value:
                low += 1
            alist[high] = alist[low]
    
        # 从循环退出时,low == high
        alist[low] = mid_value
    
        # 对low左边的列表进行快速排序
        quick_sort(alist, first, low-1)
    
        # 对low右边的列表进行快速排序
        quick_sort(alist,low+1, last)
    
    """
    最优时间复杂度:O(nlogn)
        最坏时间复杂度:O(n2)
        稳定性:不稳定
    
    """
    if __name__ == "__main__":
        alist = [12,14,4,1,1,3,1,24,1,41,5,2,5,36,3,6,1,2]
        print(alist)
        quick_sort(alist, 0, len(alist)-1)
        print(alist)
    
    # 运行结果
    [12, 14, 4, 1, 1, 3, 1, 24, 1, 41, 5, 2, 5, 36, 3, 6, 1, 2]
    [1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 12, 14, 24, 36, 41]
    
  • 归并排序

    def merge_sort(alist):
        """归并排序"""
    
        # 把它的长度求出来
        n = len(alist)
    
        # 退出递归条件
        if n <= 1:
            return alist
    
        # 把它每次分成2份 用到递归
        mid = n // 2
    
        # left序列
        left_li = merge_sort(alist[:mid])  # 递归把这句话执行完了 在执行下面那句话
    
        # right序列
        right_li = merge_sort(alist[mid:])
    
        # 初始化指针
        left_pointer, right_pointer = 0, 0
    
        # 分完以后进行排序
        result = []
        while left_pointer < len(left_li) and right_pointer < len(right_li):
            
            # 左边的第一个元素 和 右边的第一个元素  一直这样比下去
            if left_li[left_pointer] < right_li[right_pointer]:
                result.append(left_li[left_pointer])
                left_pointer += 1
            else:
                result.append(right_li[right_pointer])
                right_pointer += 1
    
        result += left_li[left_pointer:] # 切片就算超了下标不会报错  只会反回空列表
        result += right_li[right_pointer:]
    
        # 组成一个列表 返回回去
        return result
    
    """
    时间复杂度
    最优时间复杂度:O(nlogn)
        最坏时间复杂度:O(nlogn)
        稳定性:稳定
    """
    
    
    if __name__ == "__main__":
        alist = [2,1,4312,2,13,12,3,45,12,4,35,53,6,547,56,34,5,2,1,4]
        print(alist)
        sorted_li = merge_sort(alist)
        print(sorted_li)
        
    # 运行结果
    [2, 1, 4312, 2, 13, 12, 3, 45, 12, 4, 35, 53, 6, 547, 56, 34, 5, 2, 1, 4]
    [1, 1, 2, 2, 2, 3, 4, 4, 5, 6, 12, 12, 13, 34, 35, 45, 53, 56, 547, 4312]
    
  • 二分查找法

    def binay_search(alist, item):
        """二分查找法 递归"""
        n = len(alist)
        
        if n > 0:
    
            mid = n // 2
    
            if alist[mid] == item:
                return True
            elif alist[mid] < item:   # 递归只能用新的列表
                return binay_search(alist[mid+1:],item)
            else:
                return binay_search(alist[:mid],item)
    
        return False
    
    
    def binay_search_2(alist,item):
        """二分查找法 非递归"""
    
        # 求列表的长度
        n = len(alist)
    
        first = 0
        last = n-1
    
        while first <= last:
            mid = (first+last) // 2 # 这个要放在循环里 因为每次都要分
            if alist[mid] == item:
                return True
            elif alist[mid] > item: # 目标在左边
                last = mid-1
            else:                   # 目标在右边
                first = mid+1
        return False
    
    """
    时间复杂度
        最优时间复杂度:O(1)
        最坏时间复杂度:O(logn)
    """
    
    if __name__ == "__main__":
        alist = [1,2,3,4,5,6,7,8,9]
        print(binay_search(alist,4))
        print(binay_search(alist,10))
    
        print(binay_search_2(alist,7))
        print(binay_search_2(alist,45))
    
    # 运行结果
    True
    False
    True
    False
    
  • 排序算法的稳定性

    排序算法的稳定性
    稳定性:稳定排序算法会让原本有相等键值的纪录维持相对次序。也就是如果一个排序算法是稳定的,当有两个相等键值的纪录R和S,且在原本的列表中R出现在S之前,在排序过的列表中R也将会是在S之前。
    
    当相等的元素是无法分辨的,比如像是整数,稳定性并不是一个问题。然而,假设以下的数对将要以他们的第一个数字来排序。
    
    (4, 1)  (3, 1)  (3, 7)5, 6)
    在这个状况下,有可能产生两种不同的结果,一个是让相等键值的纪录维持相对的次序,而另外一个则没有:
    
    (3, 1)  (3, 7)  (4, 1)  (5, 6)  (维持次序)
    (3, 7)  (3, 1)  (4, 1)  (5, 6)  (次序被改变)
    不稳定排序算法可能会在相等的键值中改变纪录的相对次序,但是稳定排序算法从来不会如此。不稳定排序算法可以被特别地实现为稳定。作这件事情的一个方式是人工扩充键值的比较,如此在其他方面相同键值的两个对象间之比较,(比如上面的比较中加入第二个标准:第二个键值的大小)就会被决定使用在原先数据次序中的条目,当作一个同分决赛。然而,要记住这种次序通常牵涉到额外的空间负担。
    
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

只因为你温柔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值