Python实现常用查找与排序算法

 

查找算法

二分查找

import doctest

def binary_search(alist, item):
    """
    >>> alist=[1,3,4,7,11,18,29]
    >>> binary_search(alist,1)
    0
    >>> binary_search(alist,7)
    3
    >>> binary_search(alist,18)
    5
    >>> binary_search(alist,31)

    """

    binary_index = int(len(alist)/2)
    if alist == []:
        return None
    elif alist[binary_index] > item:
        return binary_search(alist[:binary_index], item)
    elif alist[binary_index] < item:
        result = binary_search(alist[binary_index + 1:], item)
        return  None if result is None else result + binary_index + 1
    elif alist[binary_index] == item:
        return binary_index

if __name__ == "__main__":
    doctest.testmod(verbose=True)

排序算法 

选择排序

原理:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。

稳定性:不稳定

最差时间复杂度:O(n^2)

平均时间复杂度:O(n^2)

import doctest
def select_sort(alist, reverse=False): """ >>> alist = [1,7,4,8,6,9,2,5,3] >>> select_sort(alist) [1, 2, 3, 4, 5, 6, 7, 8, 9] >>> select_sort(alist, reverse=True) [9, 8, 7, 6, 5, 4, 3, 2, 1] """ alist = alist[:] def select_sort_(alist, reverse): if alist == []: return [] item = max(alist) if reverse else min(alist) alist.remove(item) return [item] + select_sort_(alist,reverse) return select_sort_(alist, reverse) if __name__ == "__main__": doctest.testmod(verbose=True)

 

冒泡排序 

原理:依次比较相邻两个元素大小,交换两元素位置使之满足递增或递减关系,完成一次从序列头到序列尾部的过程称为一次冒泡,一次冒泡会产生最大或最小值于队列尾部,下一次冒泡序列长度减1,序列尾部的有序序列长度加1

稳定性:稳定

最差时间复杂度:O(n^2)

平均时间复杂度:O(n^2)

import doctest

def bubbing_sort(alist, reverse=False): """ >>> alist = [1,7,4,8,6,9,2,5,3] >>> select_sort(alist) [1, 2, 3, 4, 5, 6, 7, 8, 9] >>> select_sort(alist, reverse=True) [9, 8, 7, 6, 5, 4, 3, 2, 1] """ def swap(alist, index1, index2): temp = alist[index1] alist[index1] = alist[index2] alist[index2] = temp pass alist = alist[:] for cnt in range(len(alist) - 1): for index1 in range(len(alist) - 1 - cnt): index2 = index1 + 1 if (alist[index1] > alist[index2] and reverse == False) or (alist[index1] < alist[index2] and reverse == True): swap(alist, index1, index2) return alist if __name__ == "__main__": doctest.testmod(verbose=True)

 

插入排序

原理:将序列元素依次插入到序列首部的有序序列中,即每个元素执行一次有序插入操作

稳定性:稳定

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

平均时间复杂度:O(n2)

import doctest

def insert_sort(alist, reverse=False):
    """
    >>> alist = [1,7,4,8,6,9,2,5,3]
    >>> insert_sort(alist)
    [1, 2, 3, 4, 5, 6, 7, 8, 9]

    >>> insert_sort(alist, reverse=True)
    [9, 8, 7, 6, 5, 4, 3, 2, 1]

    """
    result = alist[:1]
    for val in alist[1:]:
        for sort_val in result:
            if (val < sort_val and reverse == False) or (val > sort_val and reverse == True):
                result.insert(result.index(sort_val), val)
                break
        else:
            result.insert(len(result), val)
    return result

if __name__ == "__main__":
    doctest.testmod(verbose=True)

 

快速排序 

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

性质:不稳定

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

平均时间复杂度:O(nlogn)

import doctest
import copy
import random

def quick_sort(alist, reverse=False):
    """
    >>> alist = [1,7,4,8,6,9,2,5,3]
    >>> quick_sort(alist)
    [1, 2, 3, 4, 5, 6, 7, 8, 9]

    >>> quick_sort(alist, reverse=True)
    [9, 8, 7, 6, 5, 4, 3, 2, 1]

    """
    alist = copy.copy(alist)
    def quick_sort_(alist, reverse):
        if alist == []:
            return []

        dichotomy_index = random.randint(0, len(alist) - 1)
        dichotomy_val = alist[dichotomy_index]
        alist.pop(dichotomy_index)
        left_list = []
        right_list = []
        for val in alist:
            if (val >= dichotomy_val and reverse == True) or (val < dichotomy_val and reverse == False):
                left_list += [val]
            else:
                right_list += [val]

        return quick_sort_(left_list, reverse) + [dichotomy_val] + quick_sort_(right_list, reverse)
    return quick_sort_(alist, reverse)

if __name__ == "__main__":
    doctest.testmod(verbose=True)

 

归并排序 

原理:将序列通过递归二分拆分到不可分,不可分的序列可以认为是有序序列,然后将两个有序序列合并为一个有序序列,直到整个序列变为一个有序序列

稳定性:稳定

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

平均时间复杂度:O(nlogn)

import doctest

def merger_sort(alist, reverse=False):
    """
    >>> alist = [1,7,4,8,6,9,2,5,3]
    >>> merger_sort(alist)
    [1, 2, 3, 4, 5, 6, 7, 8, 9]

    >>> merger_sort(alist, reverse=True)
    [9, 8, 7, 6, 5, 4, 3, 2, 1]

    """
    
    def merger(a, b):
        result = []
        for n in range(len(a) + len(b)):
            if a == []:
                return result + b
            elif b == []:
                return result + a
            elif (a[0] < b[0] and reverse == False) or (a[0] > b[0] and reverse == True):
                result += [a.pop(0)]
            else:
                result += [b.pop(0)]
        return result

    def merger_sort_(alist):        
        contre_index = int(len(alist)/2)
        left_list = alist[:contre_index]
        right_list = alist[contre_index:]
        if len(left_list) >= 2:
            left_list = merger_sort_(left_list)
        if len(right_list) >= 2:
            right_list = merger_sort_(right_list)
        return merger(left_list,right_list)

    return merger_sort_(alist)

if __name__ == "__main__":
    doctest.testmod(verbose=True)

 

堆排序

原理:堆排序也是选择排序的一种,他是利用完全二叉树的结构,从而构造出最大堆或最小堆,将堆顶元素替换到堆尾,如此反复,从而构造出有序序列

稳定性:不稳定

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

平均时间复杂度:O(nlogn)

import doctest

def heap_sort(alist, reverse=False):
    """
    >>> alist = [1,7,4,8,6,9,2,5,3]
    >>> heap_sort(alist)
    [1, 2, 3, 4, 5, 6, 7, 8, 9]

    >>> heap_sort(alist, reverse=True)
    [9, 8, 7, 6, 5, 4, 3, 2, 1]

    """
    
    A = alist[:]
    def perc_down(A, i, N):
        Ai = A[i]
        def perc_down_(A, i, N):
            temp = A[i]
            child = i * 2 + 1

            if child  < N - 1 and ((A[child] < A[child + 1]  and reverse == False) or (A[child] >= A[child + 1] and reverse == True)):
                child += 1
            if child < N and ((Ai < A[child] and reverse == False) or (Ai >= A[child] and reverse == True)):
                A[i] = perc_down_(A, child, N)
            else:
                A[i] = Ai
            
            return temp
        perc_down_(A, i, N)

    def swap(A, a, b):
        temp = A[a]
        A[a] = A[b]
        A[b] = temp

    for n in list(range(int(len(A)/2)))[::-1]:
        perc_down(A, n, len(A))

    for n in list(range(len(A)))[::-1]:
        swap(A, 0, n)
        perc_down(A, 0, n)


    return A

if __name__ == "__main__":
    doctest.testmod(verbose=True)

 

posted @ 2019-08-27 21:23  pengliangyuan  阅读(799)  评论(0编辑  收藏  举报