python 冒泡排序,插入排序,归并排序,快速排序实现code

 
import time
import random

time.clock()

class BubbleSort(object):
    """冒泡排序算法"""
    def sort_inc(self, nums):
        """如果数组长度为n,那么时间复杂度:
        一共比较n-1次,
        第X次     比较次数
        1           n-1
        2           n-2
        ...
        n-1         1
        时间复杂度为比较次数的和:1 + 2 + 3 + 。。。。 + n-1 = n(n-1)/2
        复杂度去除常数和低阶项,结果是O(n^2)
        """
        length = len(nums)
        if length == 1:
            return nums
        for i in range(length-1):
            for j in range(i+1, length):
                if nums[i] > nums[j]:
                    nums[i], nums[j] = nums[j], nums[i]
        return nums


class InsertSort(object):
    """插入排序算法"""
    def sort_inc(self, nums):
        """如果数组长度为n,那么时间复杂度:
        一共比较n-1次,数组元素从1 -> n-1
        第X次     比较次数
        1           <=1
        2           <=2
        ...
        n-1         <= n-1
        时间复杂度为比较次数的和:1 + 2 + 3 + 。。。。 + n-1 = n(n-1)/2
        复杂度去除常数和低阶项,结果是O(n^2)"""
        length = len(nums)
        if length == 1:
            return nums
        for i in range(1, length):
            key = nums[i]
            for j in range(i-1, -1, -1):
                if key < nums[j]:
                    nums[j+1] = nums[j]
                else:
                    nums[j+1] = key
                    break  # 从这里退出循环是不会执行下面的else的
            else:  # 不是从break退出的,所以所有的数字都比key大,key应该放在第一个
                nums[0] = key
        return nums


class MergeSort(object):
    """合并排序"""
    def sort_inc(self, nums):
        length = len(nums)
        if length == 1:
            return nums

        sorted_num1 = self.sort_inc(nums[:length >> 1])
        sorted_num2 = self.sort_inc(nums[length >> 1:])

        # 将1和2排序
        length1 = len(sorted_num1)
        length2 = len(sorted_num2)
        l1 = 0
        l2 = 0
        ret = []
        while True:
            if l1 < length1 and l2 < length2:
                if sorted_num1[l1] < sorted_num2[l2]:
                    ret.append(sorted_num1[l1])
                    l1 += 1
                else:
                    ret.append(sorted_num2[l2])
                    l2 += 1
            elif l1 == length1:
                ret += sorted_num2[l2:]
                break
            elif l2 == length2:
                ret += sorted_num1[l1:]
                break
            else:
                print("ERROR: l1 = %d, l2 = %d" % (l1, l2))
                exit(-1)
        return ret


class FastSort(object):
    def sort_inc(self, nums, left, right):
        if left >= right:
            return

        key = nums[left]  # 记录基准值
        keng = left  # 记录坑的索引值
        i = left
        j = right

        # 填坑,退出循环时i = j = keng
        while i < j:
            # 从右往左找小值
            while i < j:
                if nums[j] < key:  # 找到小值拿去填坑,将坑至于当前位子
                    nums[keng] = nums[j]
                    keng = j
                    break
                j -= 1

            # # 从左往右找大值
            while i < j:
                if nums[i] > key:
                    nums[keng] = nums[i]
                    keng = i
                    break
                i += 1

        # 坑填完后,把key填到坑里
        nums[keng] = key
        self.sort_inc(nums, left, keng-1)
        self.sort_inc(nums, keng+1, right)

        return nums


def test_func(className, *args):
    test = className()
    begin = time.clock()
    ret = test.sort_inc(*args)
    end = time.clock()
    cost_time = end - begin
    print(str(className) + "running time:	", cost_time)
    return ret, cost_time


mt = 0
ft = 0
it = 0
bt = 0

# 是否测试
isMergeSort, isFastSort, isInsertSort, isBubbleSort = True,  True,  False, False

test_count = 1000  # 测试次数
data_length = 10000  # 生成测试数据个数

for x in range(test_count):
    # random test data
    testlist = []
    for i in range(data_length):
        testlist.append(random.randint(1, 1000000))  # 测试数据范围

    # test part       #############################################
    if isMergeSort:
        l1, t1 = test_func(MergeSort, testlist.copy())
        mt += t1

    if isFastSort:
        l2, t2 = test_func(FastSort, testlist.copy(), 0, len(testlist) - 1)
        ft += t2

    if isInsertSort:
        l3, t3 = test_func(InsertSort, testlist.copy())
        it += t3

    if isBubbleSort:
        l4, t4 = test_func(BubbleSort, testlist.copy())
        bt += t4

print("test %d times, data length is %d" % (test_count, data_length))
if isMergeSort:
    print("MergeSort:	", t1 / test_count)

if isFastSort:
    print("FastSort:	", t2 / test_count)

if isInsertSort:
    print("InsertSort:	", t3 / test_count)

if isBubbleSort:
    print("BubbleSort:	", t4/test_count)

时间复杂度:

冒泡排序:

  1+2+。。。+n-1 ~ n2/2

插入排序:

  最优:以及排序好的数组:n-1

  最差:逆序数组:和冒泡一样,1+2+。。。+n-1 ~ n2/2

归并排序:

  自己些的分析见下面的文章,时间复杂度:nlogn

  https://www.cnblogs.com/gsp1004/p/10825941.html

  多说一句,我最开始以为空间复杂度是nlogn。但实际是n

  我的错误理解:按照树展开,每层有n个元素,一共logn层,但是并不是这样的,

  正确的顺序的:归并排序的递归会先将树从左子节点一直执行到最底部的叶子节点,所以空间复杂度:n/2 + n/4 + n/8 + ... + 1 ~ n

快速排序:

  快排的时间复杂度到底怎么算的现在还是木有搞懂,因为最优就变成了类似归并O(nlogn),最差就变成了类似冒泡O(n2),但是说什么平均时间复杂度是O(nlogn)。。。这个待研究。

  但是快排是原地排序,不需要开辟新的内存,也就是空间复杂度是0

自己测试的这几个排序的时间:

  插入和冒泡是一个量级,但是插入快一些。但是数据量大了后,就真的弱爆了。看下面1w数据执行时间对比就知道了。但是数据量小的时候,比如就几十个(30个以内?),差异不大,貌似用插入会更快一点点~~~

  快排和归并是一个量级,但是快排要快一些。这一点我很费解,为什么快排会快一些???有一个坑要研究一下子。。。

100w数据:

<class '__main__.MergeSort'>running time: 6.76003047388366

<class '__main__.FastSort'>running time: 5.620691225466125

10w数据:

<class '__main__.MergeSort'>running time: 0.5305758325035888

<class '__main__.FastSort'>running time: 0.4379082312716691

1w数据:

<class '__main__.MergeSort'>running time: 0.049988164087996834

<class '__main__.FastSort'>running time: 0.032162911379993483

<class '__main__.InsertSort'>running time: 3.9088220416271278

<class '__main__.BubbleSort'>running time: 6.644870537276558

1w数据跑1k次:

test 1000 times, data length is 10000

MergeSort: 3.865276552134844e-05

FastSort: 2.9817472595865978e-05

test 1000 times, data length is 10000

MergeSort: 3.639758325856235e-05

FastSort: 2.8445983728389024e-05

原文地址:https://www.cnblogs.com/gsp1004/p/10839682.html