zoukankan      html  css  js  c++  java
  • 排序算法

    排序算法的稳定性:让原本相等的键值维持的纪录维持相对次序

    冒泡排序(BUbble Sort)

    从头往后走,每次比较相邻的两个数字,一次循环将最大(最小)的数字放在最后,经过n-1次冒泡完成排序。

    冒泡:每次将最大的值往后移到相应的位置(第一次最大,第二次次大,依次往后)

    #关键代码
    for i in range(n-1):
        flag = 0
        for j in range(n-1-j):
            if bubble[j] > bubble[j+1]:
                bubble[j], bubble[j+1] = bubble[j+1], bubble[j]
                flag = 1
        if flag == 0: #该序列不需要进行排序
            return bubble
    

    时间复杂度:O(n2)

    稳定性:稳定

    选择排序

    从未排序的序列中选择一个次小的让前面去放

    #关键代码
    n = len(alist)
    for j in range(n-1):
        min_index = j
        for i in range(j+1, n):
            if alist[min_index] > alist[i]:
                min_index = i
        alist[j], alist[min_index] = alist[min_index], alist[j]
    

    时间复杂度:O(n2)

    稳定性:不稳定

    插入算法

    把后面序列的数字插入到前面序列合适的位置

    #关键代码
    for i in range(1, n):
        while i > 0:
            if alist[i] < alist[i-1]:
                alist[i], alist[i-1] = alist[i-1], alist[i]
                i -= 1
            else:
                break
    

    时间复杂度:O(n2)

    稳定性:稳定

    希尔排序

    对插入算法的改进。其基本思想是:先比较距离远的元素,而不是像简单交换排序算法那样先比较相邻的元素,这样可以快速减少大量的无序情况,从而减轻后续的工作。被比较的元素之间的距离逐步减少,直到减少为1,这时的排序变成了相邻元素的互换。

    #关键代码实现
    def shell_sort(alist):
    """希尔排序"""
    n = len(alist)
    gap = n//2
    
    while gap > 0:
        for j in range(gap, n):
            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 //= 2
    

    最坏时间复杂度:O(n2)

    稳定性:不稳定

    快速排序

    基本思想:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

    #关键代码
    def quick_sort(alist, first, last):
        if first == last:
            return 
        mid_value = alist[0]
        low = firsst
        high = last
        
        while low < high:
            #high左移
            while low < high and alist[high] >= mid_value:
                high -= 1
            alist[low] = alist[high]
            
            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) (经过多少次对半折分可以拆到1,nlog2n)

    最坏时间复杂度:O(n2)

    稳定性:不稳定

    归并算法

    基本思想:先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,即二路归并

    #关键代码
    def merge_sort(alist):
        """归并排序"""
        n = len(alist)
        if n <= 1
            return alist
        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
            elif: 
            result.append(right_li[right_pointer])
            right_pointer += 1
        
        result += left_li[left_pointer:]
        result += right_li[right_pointer:]
        return result
    

    最优时间复杂度:O(nlogn) (理解:纵向是logn级序列拆分,横向进行n次比较)

    最坏时间复杂度:O(nlogn)

    稳定性:稳定

    时间上是最小的,但是空间上,需要额外的开销,前面的算法是在原有的列表上进行排序的。

    搜索算法——二分查找

    二分查找,又称为折半查找。查找对象:有序的顺序表。

    def binary_search(alist, item):
        """二分查找"""
        n = len(alist)
        if n > 0:
            mid = n//2
            if alist[mid] == item:
                return True
            elif item < alist[mid]:
                return binary_search(alist[:mid], item)
            else:
                return binary_search(alist[mid:], item)
        return False
        
    # 非递归
    def binary_search(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(logn) (普通遍历查找时间复杂度是O(n))

    最优时间复杂度:O(1)

  • 相关阅读:
    Java开发必会的Linux命令
    为什么跳槽加薪会比内部调薪要高?
    程序员跳槽的最佳时机选择
    推荐!国外程序员整理的Java资源大全
    JavaScript最全编码规范
    window.open子窗口获取父窗口的值
    js获取iframe中的元素
    js数组合并为一个字符串
    js中for循环(原生js)
    js字符串截取为数组
  • 原文地址:https://www.cnblogs.com/wemo/p/9041047.html
Copyright © 2011-2022 走看看