zoukankan      html  css  js  c++  java
  • 【算法排序】代码注释和解析( 1冒泡排序 2选择排序 3插入排序 4快速排序 )

    本文主要针对下述4种不同的排序类型,进行代码的注释和解析:

    1冒泡排序

    2选择排序

    3插入排序

    4快速排序

    冒泡排序

    1、方法1:中间变量

    #!/usr/bin/env python
    #-*- coding:utf-8 -*-
    __author__ = 'Administrator'
    import random,time
    
    #随机产生50个随机数(在1-100之间)
    array=[]
    for i in range(1000):
        pass
        a = random.randrange(1,10001) #random.randrange([start], stop[, step]),  左闭右开
        # 从指定范围内,按指定基数递增的集合中 获取一个随机数。
        # 如:random.randrange(10, 100, 2),结果相当于从[10, 12, 14, 16, ... 96, 98]序列中获取一个随机数。
        # a = random.random()  #random.random()用于生成一个0到1的随机浮点数: 0 <= n < 1.0
        # a = random.randint(1,10) #printrandom.randint(12,20)#生成的随机数n:12<=n<=20  左闭右闭
        array.append(a)  #随机数添加到空列表
    # print(array)  #注意:这里pycharm打印5w随机数据比较的慢,pycharm本身的问题(重装pycharm可以解决)
    #临时解决办法:列表比较大的时候,不打印排序后的列表
    
    
    # array = [871,100,160,755]
    
    def bubble_sort(array):
        count=0
        for i in range(1,len(array)): #外循环,循环列表长度-1次即可(列表长度是4,循环3次即可)
             # 第一次内循环先把最大的放在最后,第二次内循环先把第二大的放在倒数第二,。。。。依次类推
            #参数从1开始,遍历的是列表的长度,而不是遍历的列表本身
            #参数从0开始,遍历的是列表的本身,而不是列表的长度
            for j in range(len(array)-i):  #i=1 len(array)=4  range=3(0,1,2)
                #内循环,相邻的2个数比较,大的数放在右边(1和2比较,2和3比较。。。。)
                if array[j] > array[j+1]:
                    tmp = array[j]    #这里采用了一个中间变量,也可以直接交换
                    array[j] = array[j+1]
                    array[j+1] = tmp
                    count+=1
        print("执行次数:%s" % count)
    start_time = time.time()
    bubble_sort(array)
    end_time=time.time()
    print("执行花费时间(单位秒):%s" % (end_time-start_time))  #计算执行时间
    # print(array) #[100, 160, 755, 871]
    
    # for i in range(1,4):
    #     print(i)  #1,2,3  左闭又开 range
    # for i in range(3):
    #     print(i)  #0,1,2
    
    #涉及知识点
    #1函数
    #2产生5w随机数 random
    #3冒泡排序执行次数 count
    #4冒泡排序执行时间 time
    #5冒泡算法

    2、方法2:直接交换

    #!/usr/bin/env python
    #-*- coding:utf-8 -*-
    __author__ = 'Administrator'
    import random,time
    
    #随机产生50个随机数(在1-100之间)
    array=[]
    for i in range(5000):
        pass
        a = random.randrange(1,101) #random.randrange([start], stop[, step]),  左闭右开
        # 从指定范围内,按指定基数递增的集合中 获取一个随机数。
        # 如:random.randrange(10, 100, 2),结果相当于从[10, 12, 14, 16, ... 96, 98]序列中获取一个随机数。
        # a = random.random()  #random.random()用于生成一个0到1的随机浮点数: 0 <= n < 1.0
        # a = random.randint(1,10) #printrandom.randint(12,20)#生成的随机数n:12<=n<=20  左闭右闭
        array.append(a)  #随机数添加到空列表
    # print(array)  #注意:这里pycharm打印5w随机数据比较的慢,pycharm本身的问题(重装可以解决)
    #临时解决办法:列表比较大的时候,不打印排序后的列表
    
    
    # array = [871,100,160,755]
    
    def bubble_sort(array):
        count=0
        for i in range(1,len(array)): #外循环,循环列表长度-1次即可(列表长度是4,循环3次即可)
            for j in range(len(array)-i):  #i=1 len(array)=4  range=3(0,1,2)
                #内循环,相邻的2个数比较,大的数放在右边(1和2比较,2和3比较。。。。)
                if array[j] > array[j+1]:
                    # tmp = array[j]    #这里采用了一个中间变量(好理解),也可以直接交换(简洁) 31行
                    # array[j] = array[j+1]
                    # array[j+1] = tmp
                    array[j],array[j+1] = array[j+1],array[j]
                    count+=1
        print("执行次数:%s" % count)
    start_time = time.time()
    bubble_sort(array)
    end_time=time.time()
    print("执行花费时间(单位秒):%s" % (end_time-start_time))  #计算执行时间
    # print(array) #[100, 160, 755, 871]
    
    # for i in range(1,4):
    #     print(i)  #1,2,3  左闭又开 range
    # for i in range(3):
    #     print(i)  #0,1,2
    
    #涉及知识点
    #1函数
    #2产生5w随机数 random
    #3冒泡排序执行次数 count
    #4冒泡排序执行时间 time
    #5冒泡算法

    3、方法3:减少交换次数,相对高效

    #!/usr/bin/env python
    #-*- coding:utf-8 -*-
    __author__ = 'Administrator'
    import random,time
    
    #随机产生50个随机数(在1-100之间)
    array=[]
    for i in range(10000):
        pass
        a = random.randrange(1,10001) #random.randrange([start], stop[, step]),  左闭右开
        # 从指定范围内,按指定基数递增的集合中 获取一个随机数。
        # 如:random.randrange(10, 100, 2),结果相当于从[10, 12, 14, 16, ... 96, 98]序列中获取一个随机数。
        # a = random.random()  #random.random()用于生成一个0到1的随机浮点数: 0 <= n < 1.0
        # a = random.randint(1,10) #printrandom.randint(12,20)#生成的随机数n:12<=n<=20  左闭右闭
        array.append(a)  #随机数添加到空列表
    # print(array)  #注意:这里pycharm打印5w随机数据比较的慢,pycharm本身的问题(重装可以解决)
    #临时解决办法:列表比较大的时候,不打印排序后的列表
    
    
    # array = [871,100,160,755]
    
    def bubble_sort(array):
        count=0
        for i in range(len(array)): #外循环,循环列表长度-1次即可(列表长度是4,循环3次即可)
             # 第一次内循环先把最大的放在最后,第二次内循环先把第二大的放在倒数第二,。。。。依次类推
            smallest_index = i    #外循环,假设当前位置的下标对应的那个数是最小的
            for j in range(i,len(array)):  #i=1 len(array)=4  range=3(0,1,2)
                #内循环,相邻的2个数比较,大的数放在右边(1和2比较,2和3比较。。。。)
                if array[smallest_index] > array[j]:  #如果外循环当前位置的下标对应的那个数 比内循环的其中一个数大
                    #说明外循环当前位置的下标对应的那个数不是最小的,需要和内循环中的那个数交换位置
                    # tmp = array[j]    #这里采用了一个中间变量(好理解),也可以直接交换(简洁) 33行
                    # array[j] = array[j+1]
                    # array[j+1] = tmp
                    # array[j],array[j+1] = array[j+1],array[j]
                    smallest_index=j  #把内循环中的那个数的小标置为最小数下标
                    count+=1
            tmp = array[i]
            array[i] = array[smallest_index]
            array[smallest_index] = tmp  #交换次数只会在外循环中进行,在内循环不进行,显著减少了交换次数(执行次数减少是关键)
        print("执行次数:%s" % count)
    start_time = time.time()
    bubble_sort(array)
    end_time=time.time()
    print("执行花费时间(单位秒):%s" % (end_time-start_time))  #计算执行时间
    # print(array) #[100, 160, 755, 871]
    
    # for i in range(1,4):
    #     print(i)  #1,2,3  左闭又开 range
    # for i in range(3):
    #     print(i)  #0,1,2
    
    #涉及知识点
    #1函数
    #2产生5w随机数 random
    #3冒泡排序执行次数 count
    #4冒泡排序执行时间 time
    #5冒泡算法

    二、选择排序

    #!/usr/bin/env python
    #-*- coding:utf-8 -*-
    __author__ = 'Administrator'
    import random,time
    
    #随机产生50个随机数(在1-100之间)
    array=[]
    for i in range(5000):
        pass
        a = random.randrange(1,101) #random.randrange([start], stop[, step]),  左闭右开
        # 从指定范围内,按指定基数递增的集合中 获取一个随机数。
        # 如:random.randrange(10, 100, 2),结果相当于从[10, 12, 14, 16, ... 96, 98]序列中获取一个随机数。
        # a = random.random()  #random.random()用于生成一个0到1的随机浮点数: 0 <= n < 1.0
        # a = random.randint(1,10) #printrandom.randint(12,20)#生成的随机数n:12<=n<=20  左闭右闭
        array.append(a)  #随机数添加到空列表
    # print(array)  #注意:这里pycharm打印5w随机数据比较的慢,pycharm本身的问题(重装可以解决)
    #临时解决办法:列表比较大的时候,不打印排序后的列表
    
    
    # array = [871,100,160,755]
    
    #选择排序的思想:
    #内循环:每个数都和左边第一个数对比,如果小于左边第一个数,就交换位置 57行
    #外循环:每个数都和左边第二个数对比,如果小于左边第二个数,就交换位置;
    #       每个数都和左边第三个数对比,如果小于左边第三个数,就交换位置;
    # 首先在未排序序列中找到最小元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小元素,
    # 然后放到排序序列末尾。以此递归。
    def selection_sort(array):
        count=0
        for i in range(len(array)): #外循环,循环列表本身(列表长度是4,循环4次即可)
            for j in range(i,len(array)):  #i=1 len(array)=4  range=3(0,1,2)
                if array[j] < array[i]:    #[100, 160, 755, 871]  从小到大
                    #外循环的数不变,那内循环的每一个数和外循环的数对比大小
                # if array[j] > array[i]:    #[100, 160, 755, 871]  从大到小
                    tmp = array[i]    #这里采用了一个中间变量(好理解),也可以直接交换(简洁) 31行
                    array[i] = array[j]
                    array[j] = tmp
                    # array[j],array[j+1] = array[j+1],array[j]
                    count+=1
        print("执行次数:%s" % count)
    start_time = time.time()
    selection_sort(array)
    end_time=time.time()
    print("执行花费时间(单位秒):%s" % (end_time-start_time))  #计算执行时间
    # print(array) #[100, 160, 755, 871]
    
    # for i in range(1,4):
    #     print(i)  #1,2,3  左闭又开 range
    # for i in range(3):
    #     print(i)  #0,1,2
    
    #涉及知识点
    #1函数
    #2产生5w随机数 random
    #3排序执行次数 count
    #4排序执行时间 time
    #5选择排序算法
    
    # Example.
    #
    # 29, 64, 73, 34, 20,
    # 20, 64, 73, 34, 29,
    # 20, 29, 73, 34, 64
    # 20, 29, 34, 73, 64
    # 20, 29, 34, 64, 73

    三、插入排序

    #!/usr/bin/env python
    #-*- coding:utf-8 -*-
    __author__ = 'Administrator'
    import random,time
    
    #随机产生50个随机数(在1-100之间)
    array=[]
    for i in range(5000):
        pass
        a = random.randrange(1,5001) #random.randrange([start], stop[, step]),  左闭右开
        # 从指定范围内,按指定基数递增的集合中 获取一个随机数。
        # 如:random.randrange(10, 100, 2),结果相当于从[10, 12, 14, 16, ... 96, 98]序列中获取一个随机数。
        # a = random.random()  #random.random()用于生成一个0到1的随机浮点数: 0 <= n < 1.0
        # a = random.randint(1,10) #printrandom.randint(12,20)#生成的随机数n:12<=n<=20  左闭右闭
        array.append(a)  #随机数添加到空列表
    # print(array)  #注意:这里pycharm打印5w随机数据比较的慢,pycharm本身的问题(重装可以解决)
    #临时解决办法:列表比较大的时候,不打印排序后的列表
    
    
    array = [871,100,160,755]
    
    # 插入排序(Insertion Sort)的基本思想是:将列表分为2部分,左边为排序好的部分,右边为未排序的部分,循环整个列表,
    # 每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子序列中的适当位置,直到全部记录插入完成为止。
    def insertion_sort(array):
        count=0
        for i in range(1,len(array)): #外循环,循环列表的长度(列表长度是4,循环3次即可)
            tmp = array[i]  #先记下来每次外循环走到的第几个元素的值
            # for j in range(i,len(array)):  #i=1 len(array)=4  range=3(0,1,2)
            #     if array[j] < array[i]:    #[100, 160, 755, 871]  从小到大
            #         #外循环的数不变,那内循环的每一个数和外循环的数对比大小
            #     # if array[j] > array[i]:    #[100, 160, 755, 871]  从大到小
            #         tmp = array[i]    #这里采用了一个中间变量(好理解),也可以直接交换(简洁) 31行
            #         array[i] = array[j]
            #         array[j] = tmp
            #         # array[j],array[j+1] = array[j+1],array[j]
            #         count+=1
            while i>0 and array[i-1] > tmp: #当前元素的左边的紧靠的元素比它大,要把左边的元素一个一个的往右移一位,给当前这个值插入到左边挪一个位置出来
            # while i>0 and array[i-1] < tmp: #当前元素的左边的紧靠的元素比它大,要把左边的元素一个一个的往右移一位,给当前这个值插入到左边挪一个位置出来
                # tmp = array[i]
                array[i] = array[i-1] ##把左边的一个元素往右移一位
                i -= 1 #只一次左移只能把当前元素一个位置 ,还得继续左移直到此元素放到排序好的列表的适当位置 为止
                count+=1
            array[i] = tmp  #已经找到了左边排序好的列表里不小于tmp的元素的位置,把tmp放在这里
        print("执行次数:%s" % count)
    
    
        # count=0
        # for index in range(1,len(array)):
        #     current_val = array[index] #先记下来每次大循环走到的第几个元素的值
        #     position = index
        #
        #     while position > 0 and array[position-1] > current_val: #当前元素的左边的紧靠的元素比它大,要把左边的元素一个一个的往右移一位,给当前这个值插入到左边挪一个位置出来
        #         array[position] = array[position-1] #把左边的一个元素往右移一位
        #         position -= 1 #只一次左移只能把当前元素一个位置 ,还得继续左移只到此元素放到排序好的列表的适当位置 为止
        #         count+=1
        #     array[position] = current_val #已经找到了左边排序好的列表里不小于current_val的元素的位置,把current_val放在这里
        #     # print(array)
        # print("执行次数:%s" % count)
    start_time = time.time()
    insertion_sort(array)
    end_time=time.time()
    print("执行花费时间(单位秒):%s" % (end_time-start_time))  #计算执行时间
    print(array) #[100, 160, 755, 871]
    
    # for i in range(1,4):
    #     print(i)  #1,2,3  左闭又开 range
    # for i in range(3):
    #     print(i)  #0,1,2
    
    #涉及知识点
    #1函数
    #2产生5w随机数 random
    #3排序执行次数 count
    #4排序执行时间 time
    #5插入排序算法
    
    # Example.
    #
    # 结果:
    
    # [77, 92, 67, 8, 6, 84, 55, 85, 43, 67]
    # [67, 77, 92, 8, 6, 84, 55, 85, 43, 67]
    # [8, 67, 77, 92, 6, 84, 55, 85, 43, 67]
    # [6, 8, 67, 77, 92, 84, 55, 85, 43, 67]
    # [6, 8, 67, 77, 84, 92, 55, 85, 43, 67]
    # [6, 8, 55, 67, 77, 84, 92, 85, 43, 67]
    # [6, 8, 55, 67, 77, 84, 85, 92, 43, 67]
    # [6, 8, 43, 55, 67, 77, 84, 85, 92, 67]
    # [6, 8, 43, 55, 67, 67, 77, 84, 85, 92]

    四、快速排序

    #!/usr/bin/env python
    #-*- coding:utf-8 -*-
    __author__ = 'Administrator'
    import random,time
    
    #随机产生50个随机数(在1-100之间)
    array=[]
    for i in range(5000):
        pass
        a = random.randrange(1,5001) #random.randrange([start], stop[, step]),  左闭右开
        # 从指定范围内,按指定基数递增的集合中 获取一个随机数。
        # 如:random.randrange(10, 100, 2),结果相当于从[10, 12, 14, 16, ... 96, 98]序列中获取一个随机数。
        # a = random.random()  #random.random()用于生成一个0到1的随机浮点数: 0 <= n < 1.0
        # a = random.randint(1,10) #printrandom.randint(12,20)#生成的随机数n:12<=n<=20  左闭右闭
        array.append(a)  #随机数添加到空列表
    # print(array)  #注意:这里pycharm打印5w随机数据比较的慢,pycharm本身的问题(重装可以解决)
    #临时解决办法:列表比较大的时候,不打印排序后的列表
    
    
    # array = [871,100,160,755]
    
    #快速排序基本思想:第一次递归:以第一个元素为基准,大于基准的数放在右边,小于基准的数放在左边
    #第二次递归:以基准作为分割线,将列表一分为二,列表左边以第一个元素为基准,大于基准的数放在右边,小于基准的数放在左边
    #                                      列表右边以第一个元素为基准,大于基准的数放在右边,小于基准的数放在左边
    # 注意:第一遍快速排序不会直接得到最终结果,只会把比k大和比k小的数分到k的两边。为了得到最后结果,
    # 需要再次对下标2两边的数组分别执行此步骤,然后再分解数组,直到数组不能再分解为止(只有一个数据),才能得到正确结果。
    
    def quick_sort(array,left,right):
    
        '''
    
        :param array:
        :param left: 列表的第一个索引
        :param right: 列表最后一个元素的索引
        :return:
        '''
        count=0
        if left >=right:
            return   #递归退出条件
        low = left
        high = right
        key = array[low] #第一个值
    
        while low < high:#只要左右未遇见
            while low < high and array[high] > key: #找到列表右边比key大的值 为止
                high -= 1
            #此时直接 把key(array[low]) 跟 比它大的array[high]进行交换
            array[low] = array[high]
            array[high] = key
    
    
            while low < high and array[low] <= key : #找到key左边比key大的值
                low += 1
                #array[low] =
            #找到了左边比k大的值 ,把array[high](此时应该刚存成了key) 跟这个比key大的array[low]进行调换
            array[high] = array[low]
            array[low] = key
            count+=1
    
        quick_sort(array,left,low-1) #最后用同样的方式对分出来的左边的小组进行同上的做法  递归
        quick_sort(array,low+1, right)#用同样的方式对分出来的右边的小组进行同上的做法   递归
        # print("执行次数:%s" % count)
    
    start_time = time.time()
    quick_sort(array,0,len(array)-1)
    end_time=time.time()
    print("执行花费时间(单位秒):%s" % (end_time-start_time))  #计算执行时间
    print(array) #[100, 160, 755, 871]
    
    # for i in range(1,4):
    #     print(i)  #1,2,3  左闭又开 range
    # for i in range(3):
    #     print(i)  #0,1,2
    
    #涉及知识点
    #1函数
    #2产生5w随机数 random
    #3排序执行次数 count
    #4排序执行时间 time
    #5快速排序算法
    
    # Example.
    #
    # 结果:
    
    
    
    排序演示
    
    
    
    
    示例
    
    
    假设用户输入了如下数组:
    
    
    
    
    
    下标
    
    
    
    
    
    
    
    
    
    数据
    
    
    
    
    
    
    
    
    
    
    创建变量i=0(指向第一个数据), j=5(指向最后一个数据), k=6(赋值为第一个数据的值)。
    
    我们要把所有比k小的数移动到k的左面,所以我们可以开始寻找比6小的数,从j开始,从右往左找,不断递减变量j的值,我们找到第一个下标3的数据比6小,于是把数据3移到下标0的位置,把下标0的数据6移到下标3,完成第一次比较:
    
    
    
    
    
    下标
    
    
    
    
    
    
    
    
    
    数据
    
    
    
    
    
    
    
    
    
    
    i=0 j=3 k=6
    
    接着,开始第二次比较,这次要变成找比k大的了,而且要从前往后找了。递加变量i,发现下标2的数据是第一个比k大的,于是用下标2的数据7和j指向的下标3的数据的6做交换,数据状态变成下表:
    
    
    
    
    
    下标
    
    
    
    
    
    
    
    
    
    数据
    
    
    
    
    
    
    
    
    
    
    i=2 j=3 k=6
    
    称上面两次比较为一个循环。
    
    接着,再递减变量j,不断重复进行上面的循环比较。
    
    在本例中,我们进行一次循环,就发现i和j“碰头”了:他们都指向了下标2。于是,第一遍比较结束。得到结果如下,凡是k(=6)左边的数都比它小,凡是k右边的数都比它大:
    
    
    
    
    
    下标
    
    
    
    
    
    
    
    
    
    数据
    
    
    
    
    
    
    
    
    
    
    如果i和j没有碰头的话,就递加i找大的,还没有,就再递减j找小的,如此反复,不断循环。注意判断和寻找是同时进行的。
  • 相关阅读:
    [转] java代码块 介绍
    win10多用户远程登录
    [读书笔记] learn python the hard way书中 有关powershell 的一些小问题
    Ansible 汇总
    Shell 研究
    Linux CenOS Python3 和 python2 共存
    Ansible安装
    MySQL 5.7.20绿色版安装详细图文教程
    Mysql常用运算符与函数汇总
    mysql 从陌生到熟练之----数据库备份恢复的实现方法
  • 原文地址:https://www.cnblogs.com/zengluo/p/12605984.html
Copyright © 2011-2022 走看看