【算法排序】代码注释和解析( 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.
#
# 结果:

排序演示



示例


假设用户输入了如下数组:

下标
0
1
2
3
4
5
数据
6
2
7
3
8
9

创建变量i=0(指向第一个数据), j=5(指向最后一个数据), k=6(赋值为第一个数据的值)。

我们要把所有比k小的数移动到k的左面,所以我们可以开始寻找比6小的数,从j开始,从右往左找,不断递减变量j的值,我们找到第一个下标3的数据比6小,于是把数据3移到下标0的位置,把下标0的数据6移到下标3,完成第一次比较:

下标
0
1
2
3
4
5
数据
3
2
7
6
8
9

i=0 j=3 k=6

接着,开始第二次比较,这次要变成找比k大的了,而且要从前往后找了。递加变量i,发现下标2的数据是第一个比k大的,于是用下标2的数据7和j指向的下标3的数据的6做交换,数据状态变成下表:

下标
0
1
2
3
4
5
数据
3
2
6
7
8
9

i=2 j=3 k=6

称上面两次比较为一个循环。

接着,再递减变量j,不断重复进行上面的循环比较。

在本例中,我们进行一次循环,就发现i和j“碰头”了:他们都指向了下标2。于是,第一遍比较结束。得到结果如下,凡是k(=6)左边的数都比它小,凡是k右边的数都比它大:

下标
0
1
2
3
4
5
数据
3
2
6
7
8
9

如果i和j没有碰头的话,就递加i找大的,还没有,就再递减j找小的,如此反复,不断循环。注意判断和寻找是同时进行的。
 

 

posted @ 2016-05-15 23:32  王同佩  阅读(633)  评论(0编辑  收藏  举报