【数据结构】内部排序算法

34 篇文章 2 订阅
20 篇文章 2 订阅

我总结了一下常见的排序算法。直接写成了类,对于每一种算法的说明都写在了注释里,在调用某个类或者某个排序算法的方法之后,使用python内置的 __doc__方法即可查看具体的某种算法的说明。

class SortingAlgorithms(object):
    '''
    冒泡法:对比模型,原数组上排序,稳定,慢o(n^2)
    插入法:对比模型,原数组上排序,稳定,慢,最优的方法是希尔排序
    选择法:对比模型,原数组上排序,稳定,慢
    归并法:对比模型,非原数组上排序,稳定,快o(n*log2 n),性能最稳定,但辅助空间o(n)
    快速法:对比模型,原数组上排序,不稳定,快,性能最优,但是不稳定,辅助空间o(log2 n)
    堆排序:对比模型,原数组上排序,不稳定,快,空间复杂度为1个辅助空间,比快排稳定
    二叉树排序:对比模型,非数组上排序,不稳定,快
    桶排序:非对比模型,非原数组上排序,不稳定,针对海量紧凑数据快,其他情况下就比较差。空间复杂度同理。
    基数排序:非对比模型,非原数组上排序,稳定,快,桶排序的一般情况。
    基于比较模型的排序算法的复杂度最高可以做到 o(n*log2 n),这是二叉树形比较结构决定的,再有其他方法就只能是空间换时间。
    一种广泛采取的排序算法,是在数据量很大的时候,采取快速排序的方式,而在当分组很小的时候,使用其他稳定的排序方法。
    这样的混合型算法,综合效果是最好的,也就是一般内置排序使用的方法
    详细信息在每个方法的注释里
    '''
    def __init__(self):
        pass

    def straight_insertion_sort(self, lists):
        '''
        直接插入排序, 空间复杂度 o(1),时间复杂度为o(n^2),稳定排序,不消耗额外空间
        '''
        if lists == [] or len(lists) == 1:
            return
        for i in range(1, len(lists)):
            key = lists[i]
            j = i-1
            while j >= 0:
                if lists[j] > key:
                    lists[j+1] = lists[j]
                    lists[j] = key
                j -= 1
        return lists

    def bubble_sort(self, lists):
        '''
        冒泡排序,快速排序的一种,稳定排序,不消耗额外空间
        '''
        if lists == [] or len(lists) == 1:
            return lists
        for i in range(0, len(lists)):
            for j in range(i+1, len(lists)):
                if lists[i] > lists[j]:
                    lists[j], lists[i] = lists[i], lists[j]
        return lists

    def quick_sort_1(self, lists):
        '''
        快速排序,对冒泡排序的改进,不稳定排序,时间复杂度为o(n*log 2n),目前公认的常数项因子最小的先进排序算法.
        其中的关键是分治策略,但是在 Python 中的分治要比 C 语言中的简单得多,但是我仍然用 Python 具体写了一下分治策略
        '''
        if lists == [] or len(lists) == 1:
            return lists
        low, high = 0, len(lists) - 1
        pivot = 0
        while low < high:
            while low < high:
                if lists[pivot] > lists[high]:
                    lists[high], lists[low] = lists[low], lists[high]
                    pivot = high
                    break
                high -= 1
            while low < high:
                if lists[pivot] < lists[low]:
                    lists[high], lists[low] = lists[low], lists[high]
                    pivot = low
                    break
                low += 1
        return self.quick_sort_1(lists[:pivot]) + [lists[pivot]] + self.quick_sort_1(lists[pivot+1:])

    def quick_sort_2(self, lists):
        '''
        快速排序的另外一种写法,简单写法,但是时间消耗要比分治多一些
        '''
        if lists == [] or len(lists) == 1:
            return lists
        left = [i for i in lists[1:] if i < lists[0]]
        right = [i for i in lists[1:] if i >= lists[0]]
        return self.quick_sort_2(left) + [lists[0]] + self.quick_sort_2(right)

    def shell_sort(self, lists):
        '''
        希尔排序,插入排序的一种,时间复杂度为o(n^3/2),不稳定排序,基本思想是如果是正序的话,比较次数就少了很多
        i,j k 三个变量折腾的我有点懵逼,这个排序我看了别人的代码,不是我写的
        '''
        if lists == [] or len(lists) == 1:
            return lists
        count = len(lists)
        step = 2
        group = count / step
        while group > 0:
            for i in range(0, group):
                j = i + group
                while j < count:
                    k = j - group
                    key = lists[j]
                    while k >= 0:  # 直接插入排序的方法
                        if lists[k] > key:
                            lists[k + group] = lists[k]
                            lists[k] = key
                        k -= group
                    j += group
            group /= step
        return lists

    def simple_select_sort(self, lists):
        '''
        简单选择排序,稳定排序,时间复杂度为 o(n^2),查找每一次最小值的时候都要经过 n-1 次比较
        '''
        length = len(lists)
        for i in xrange(0, length):
            key = i
            for j in xrange(i+1, length):
                if lists[key] > lists[j]:
                    key = j
            lists[i], lists[key] = lists[key], lists[i]
        return lists

    def heap_sort(self, L):
        '''
        堆排序,是选择排序的一种优化,利用了树形结构,避免了选择最小元素时每次都经过 n-1 次比较,不稳定排序
        辅助空间只需要一个,空间复杂度为o(1),时间复杂度为 o(n*log2 n),在最坏的情况下,复杂度依然是 o(n*log2 n)
        这是相比快速排序优秀的地方,但是在序列中记录较少的时候不提倡使用,因为建立堆比较耗时。
        '''
        if L == [] or len(L) == 1:
            return L

        def sift_down(L, start, end):  # 调整找到一颗根节点最小的树
            root = start
            while True:
                child = 2*root + 1  # 左子节点,一个辅助空间,指针指示哪一个节点
                if child > end:  # 子节点超出范围
                    break
                if child+1 <= end and L[child] < L[child+1]:  # 左子节点比右子节点小,转换到右子节点
                    child += 1
                if L[root] < L[child]:  # 若根节点比 相对较大的一个子节点小,则互换
                    L[root], L[child] = L[child], L[root]
                    root = child  # 进行树下面下一层的替换
                else:
                    break
            return
        for start in range((len(L)-2)/2, -1, -1):  # 逆序构建一个堆,堆顶的值最大,
            sift_down(L, start, len(L)-1)
        print L
        for end in range(len(L)-1, 0, -1):  # 取堆顶的一个值,放在序列尾部
            L[0], L[end] = L[end], L[0]
            sift_down(L, 0, end-1)
        return L

    def merging_sort(self, lists):
        '''
        归并排序,需要的辅助空间大小和待排记录数量相等,时间复杂度也是 o(n*log2 n),稳定排序,但是额外空间需求比较大,稳定排序
        '''
        if lists == [] or len(lists) == 1:
            return lists

        def merge(list1, list2):
            i, j = 0, 0  # 分别指向两个序列的指针
            result = []
            while i < len(list1) and j < len(list2):
                if list1[i] > list2[j]:
                    result.append(list2[j])
                    j += 1
                else:
                    result.append(list1[i])
                    i += 1
            result += list1[i:]
            result += list2[j:]
            return result

        num = len(lists) / 2
        left = self.merging_sort(lists[:num])
        right = self.merging_sort(lists[num:])
        return merge(left, right)

    def bucket_sort(self, lists):
        '''
        桶排序,非比较模型,适用于数据量非常大,数据紧凑,相同数据很多的情况,比如统计每年高考学生的分数,适用条件比较苛刻,但是有奇效
        '''
        if lists == [] or len(lists) == 1:
            return lists
        mini = min(lists)  # 查找方法
        maxi = max(lists)
        bucket = []
        for _ in xrange(0, maxi+1-mini):
            bucket.append(0)
        for i in lists:
            bucket[i-mini] += 1
        res = []
        for i in xrange(0, len(bucket)):
            while bucket[i] > 0:
                res.append(i+mini)
                bucket[i] -= 1
        return res

    def radix_sort(self, lists):
        '''
        基数排序,针对“正整数”来写的算法函数,本算法只考虑了正整数,其他情况没有考虑,稳定排序,按照千位、百位、十位来排序
        '''
        import math
        k = int(math.ceil(math.log(max(lists), 10)))
        bucket = [[] for _ in range(10)]
        for i in range(1, k+1):
            for j in lists:
                #num =
                bucket[(j%(10**i))/10**(i-1)].append(j)
            del lists[:]
            for z in bucket:
                lists += z
                del z[:]
        return lists

随后再总结一下外排的方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值