交换排序

  交换排序有冒泡排序和快速排序

冒泡排序

  冒泡排序就是每次找出最大(最小)元素,放在集合最前或最后,这是最简单的排序算法

print("未排序之前:",collection)#不能写成+(会提示为不是str类型数据,要写成这样)
    #升序排列

    temp=collection[0]
    length=len(collection)
    for s in range(length-1):
        for i in range(length-1-s):
            if collection[i]>collection[i+1]:#前者大需要换位置,并需要判断他是否是最大的
                temp=collection[i]
                collection[i]=collection[i+1]
                collection[i+1]=temp
            else:
                continue
    print("排序第",s+1,"轮之后:",collection)#print()好占时间啊

快速排序

  快速排序是对冒泡排序的一种改进,冒泡排序作为一种广为人知的最简单的排序算法,存在着很多不足,比如他每趟遍历后只能从当前数列中挑出一个最大(最小)的数值,然后下趟工作再挑出剩下中的最大元素。这样看来,每趟之间几乎是完全独立的,这一趟的排序除了能使带排序的元素减少一个之外,并不会留下任何信息。这很明显就浪费了这一趟又一趟的比较。完全可以从一趟一趟中了解关于带排序的样本的更多信息。

  快速排序就是另外一种思路,他最明显的特点就是“分而治之”。快速排序首先会选择两个游标,游标是移动的,在初始化的时候,我们一般将数组元素的第一个和最后一个元素(注意,代表的数组地址,会移动),然后他们两个交替的向前或者向后移动,每次移动一个元素,然后与一个值比较,(并不会让他们两个相互比较,)我们习惯上将这个值称为key,这个值初始化为数组首元素。

  在比较的过程中,由于两个游标(一个i,一个j)是交替移动的,所以他们必然有相遇的时候,我将每次相遇,看作为一轮比较的结束,这一轮会将待排序的数组分为3个部分,一个部分只有key,另外两个部分分别存放比key小和比key大的元素。这就是分而治之的结果,除了只有一个元素的结果,下一次的分治过程又会从他们里面开始。

  每一轮中的比较结果首先从i或j与key的比较开始,是i还是j怎样都行。我只需要记住,比较是为了将结果向有序的升序(或者降序)去靠拢。每一轮都是为了减小颗粒度。拿升序来说,如果i代表的下标所指的数组元素比key小(因为key代表数组首元素),那么他就应该和key交换,如果没有就向后移动一次,然后换j与key比较。

我的问题

  1)当所有分而治之的结果 的左边都被排序好了,或者颗粒度是最小的,那么右边的就不排了。换句话说,剩下的所有工作都不去做了。

(sort) λ python bubble_sort.py
未排序之前:      [70, 78, 85, 10, 66, 43, 89, 62, 11, 41]
key两边的数组是: [41] [ 70 ] [85, 10, 66, 43, 89, 62, 11, 78]
*************************i,j的值分别为 1 9
key两边的数组是: [41, 11] [ 70 ] [10, 66, 43, 89, 62, 85, 78]
*************************i,j的值分别为 2 8
key两边的数组是: [41, 11, 62, 10, 66, 43] [ 70 ] [89, 85, 78]
*************************i,j的值分别为 6 7
key两边的数组是: [41, 11, 62, 10, 66, 43] [ 70 ] [89, 85, 78]
*************************i,j的值分别为 6 6
key两边的数组是: [10, 11] [ 41 ] [62, 66, 43]
*************************i,j的值分别为 2 3
key两边的数组是: [10, 11] [ 41 ] [62, 66, 43]
*************************i,j的值分别为 2 2
key两边的数组是: [] [ 10 ] [11]
*************************i,j的值分别为 0 0
key两边的数组是: [] [ 41 ] [62, 66, 43]
*************************i,j的值分别为 0 0
key两边的数组是: [] [ 70 ] [89, 85, 78]
*************************i,j的值分别为 0 0
排序之后: [41, 11, 62, 10, 66, 43, 70, 89, 85, 78]
耗费时间: 0.023987293243408203

  2)为什么第二趟都从0开始啊

  解决办法:这个不是程序的原因,而是因为程序递归到第二次时,穿过去的数组中指定的key就是最小的了。   

未排序之前:                                                                     [6, 5, 4, 8, 7, 9, 3, 2, 1]
*************************又经过了一次j交换,交换的数组下标j的值为 8 这时的数组为 [1, 5, 4, 8, 7, 9, 3, 2, 6]
*************************又经过了一次i交换,交换的数组下标i的值为 3 这时的数组为 [1, 5, 4, 6, 7, 9, 3, 2, 8]
*************************又经过了一次j交换,交换的数组下标j的值为 7 这时的数组为 [1, 5, 4, 2, 7, 9, 3, 6, 8]
*************************又经过了一次i交换,交换的数组下标i的值为 4 这时的数组为 [1, 5, 4, 2, 6, 9, 3, 7, 8]
*************************又经过了一次j交换,交换的数组下标j的值为 6 这时的数组为 [1, 5, 4, 2, 3, 9, 6, 7, 8]
*************************又经过了一次i交换,交换的数组下标i的值为 5 这时的数组为 [1, 5, 4, 2, 3, 6, 9, 7, 8]
*************************又经过了一次j交换,交换的数组下标j的值为 5 这时的数组为 [1, 5, 4, 2, 3, 6, 9, 7, 8]
*************************又经过了一次i交换,交换的数组下标i的值为 5 这时的数组为 [1, 5, 4, 2, 3, 6, 9, 7, 8]
这一轮过后key两边的数组是:                                                      [1, 5, 4, 2, 3] [ 6 ] [9, 7, 8]
*************************又经过了一次j交换,交换的数组下标j的值为 0 这时的数组为 [1, 5, 4, 2, 3]
*************************又经过了一次i交换,交换的数组下标i的值为 0 这时的数组为 [1, 5, 4, 2, 3]
这一轮过后key两边的数组是:                                                      [] [ 1 ] [5, 4, 2, 3]
*************************又经过了一次j交换,交换的数组下标j的值为 0 这时的数组为 [6, 9, 7, 8]
*************************又经过了一次i交换,交换的数组下标i的值为 0 这时的数组为 [6, 9, 7, 8]
这一轮过后key两边的数组是:                                                      [] [ 6 ] [9, 7, 8]
排序之后: [1, 5, 4, 2, 3, 6, 9, 7, 8] L: [1, 5, 4, 2, 3, 6, 9, 7, 8]

  第一次版本,失败了

def quick_sort(collection):
    length=len(collection)
    i=0
    j=length-1
    if(length>1):
        key=collection[0]
        print("新一轮的排序开始了i,j,key的值分别为",i,j,key,"被排序的数组是:",collection,'此次被排序数组的长度是:',length)
        while(i<j):
            while(collection[j]>key):
                j=j-1
            collection[i],collection[j]=collection[j],collection[i]
            print('*'*25+'又经过了一次j交换,交换的数组下标j的值为',j,'这时的数组为',collection)
            while(collection[i]<key):
                if(i<j):
                    i=i+1
                break
            collection[i],collection[j]=collection[j],collection[i]
            print('*'*25+'又经过了一次i交换,交换的数组下标i的值为',i,'这时的数组为',collection)
        print("这一轮过后key两边的数组是:"+' '*53,collection[0:i],'[',key,']',collection[i+1:length],'整个数组为:',collection,'\n')#要加逗号啦
        # L.extend(collection)
        #递归
        if(i>0):
            # print('现在的L是:',L)
            print('对%s的左边排序'%(key))
            print('%s左边返回的结果是'%(key),quick_sort(collection[0:i]),'key是',key)
            # s=quick_sort(collection[0:i])
            # if(s!=-1):
            #     L.extend(s)
            # L.append(key)
            # print("s是:",s,'key是',key)
        if(j>0):#为什么这里不能写成elif类,因为这两个判断应该是相互独立的,即在分而治之的过程中,i代表的左边
            #没有元素了,然后在处理右边,如果改成elif,那么情况就会变成如果i<0了,那么就会不管右边了,即判断
            #右边需不需要处理的判断就会只有满足了第一个条件之后才会进入。
            # print('右边返回的结果是',quick_sort(collection[j+1:length]))
            print('对%s的右边进行排序'%(key))
            print('%s右边返回的结果是'%(key),quick_sort(collection[j+1:length]))
            # s=quick_sort(collection[j+1:length])
            # if(s!=-1):
            #     L.extend(s)
            # print("s是:",s)
            # print('现在的L是:',L)
    # print("此轮被排序的数组长度为1")
    elif(length>0):
        return collection#忽略了一点,原以为这里即使不写else return也会只有在数组长度等于1的长度下被返回的,即返回单个数,但实际情况可能不是这样的。
    print('这里已经没有元素了')
    return -1

#产生排序数组
# collection=random.sample(range(1,100),10)
# collection =[6,5,4,8,7,9,3,1,2]
collection= [94, 37, 97, 31, 26, 79, 10, 35, 40, 6]
startTime=time.time()
print("未排序之前:"+' '*68,collection)#不能写成+(会提示为不是str类型数据,要写成这样)
print("排序之后:",quick_sort(collection),'L:',L)
endTime=time.time()
print("耗费时间:",endTime-startTime)

  失败的原因是:

未排序之前:                                                                     [94, 37, 97, 31, 26, 79, 10, 35, 40, 6]
新一轮的排序开始了i,j,key的值分别为 0 9 94 被排序的数组是: [94, 37, 97, 31, 26, 79, 10, 35, 40, 6] 此次被排序数组的长度是: 10
*************************又经过了一次j交换,交换的数组下标j的值为 9 这时的数组为 [6, 37, 97, 31, 26, 79, 10, 35, 40, 94]
*************************又经过了一次i交换,交换的数组下标i的值为 1 这时的数组为 [6, 94, 97, 31, 26, 79, 10, 35, 40, 37]
*************************又经过了一次j交换,交换的数组下标j的值为 9 这时的数组为 [6, 37, 97, 31, 26, 79, 10, 35, 40, 94]
*************************又经过了一次i交换,交换的数组下标i的值为 2 这时的数组为 [6, 37, 94, 31, 26, 79, 10, 35, 40, 97]
*************************又经过了一次j交换,交换的数组下标j的值为 8 这时的数组为 [6, 37, 40, 31, 26, 79, 10, 35, 94, 97]
*************************又经过了一次i交换,交换的数组下标i的值为 3 这时的数组为 [6, 37, 40, 94, 26, 79, 10, 35, 31, 97]
*************************又经过了一次j交换,交换的数组下标j的值为 8 这时的数组为 [6, 37, 40, 31, 26, 79, 10, 35, 94, 97]
*************************又经过了一次i交换,交换的数组下标i的值为 4 这时的数组为 [6, 37, 40, 31, 94, 79, 10, 35, 26, 97]
*************************又经过了一次j交换,交换的数组下标j的值为 8 这时的数组为 [6, 37, 40, 31, 26, 79, 10, 35, 94, 97]
*************************又经过了一次i交换,交换的数组下标i的值为 5 这时的数组为 [6, 37, 40, 31, 26, 94, 10, 35, 79, 97]
*************************又经过了一次j交换,交换的数组下标j的值为 8 这时的数组为 [6, 37, 40, 31, 26, 79, 10, 35, 94, 97]
*************************又经过了一次i交换,交换的数组下标i的值为 6 这时的数组为 [6, 37, 40, 31, 26, 79, 94, 35, 10, 97]
*************************又经过了一次j交换,交换的数组下标j的值为 8 这时的数组为 [6, 37, 40, 31, 26, 79, 10, 35, 94, 97]
*************************又经过了一次i交换,交换的数组下标i的值为 7 这时的数组为 [6, 37, 40, 31, 26, 79, 10, 94, 35, 97]
*************************又经过了一次j交换,交换的数组下标j的值为 8 这时的数组为 [6, 37, 40, 31, 26, 79, 10, 35, 94, 97]
*************************又经过了一次i交换,交换的数组下标i的值为 8 这时的数组为 [6, 37, 40, 31, 26, 79, 10, 35, 94, 97]
这一轮过后key两边的数组是:                                                      [6, 37, 40, 31, 26, 79, 10, 35] [ 94 ] [97] 整个数组为: [6, 37, 40, 31, 26, 79, 10, 35, 94, 97]

对94的左边排序
新一轮的排序开始了i,j,key的值分别为 0 7 6 被排序的数组是: [6, 37, 40, 31, 26, 79, 10, 35] 此次被排序数组的长度是: 8
*************************又经过了一次j交换,交换的数组下标j的值为 0 这时的数组为 [6, 37, 40, 31, 26, 79, 10, 35]
*************************又经过了一次i交换,交换的数组下标i的值为 0 这时的数组为 [6, 37, 40, 31, 26, 79, 10, 35]
这一轮过后key两边的数组是:                                                      [] [ 6 ] [37, 40, 31, 26, 79, 10, 35] 整个数组为: [6, 37, 40, 31, 26, 79, 10, 35]#这里该向下递归的没有递归

这里已经没有元素了
94左边返回的结果是 -1 key是 94
对94的右边进行排序
94右边返回的结果是 [97]
这里已经没有元素了
排序之后: -1 L: []
耗费时间: 0.008994817733764648

  我猜想可能是因为对左边或右边进行排序的时候没有响应的判断逻辑。

3)修正

while(i<j):#这里不应该是i<j-1,即使这样能避免有些交换数组下标的重复,但会产生下面的问题,当排序三个元素的数组中key为中间值时,会忽略右边的元素。
            print('先输出i=%s  j=%s'%(i,j))
            while(collection[j]>key):
                j=j-1
            collection[i],collection[j]=collection[j],collection[i]
            print('*'*25+'又经过了一次j交换,交换的数组下标j的值为',j,'这时的数组为',collection)
            while(collection[i]<key):
                i=i+1
            collection[i],collection[j]=collection[j],collection[i]#正是这一句导致了重复定位ij的结果,因为即使上面的while
            #起了作用,这句也会运行的。
            print('*'*25+'又经过了一次i交换,交换的数组下标i的值为',i,'这时的数组为',collection)

新一轮的排序开始了i,j,key的值分别为 0 2 4 被排序的数组是: [4, 5, 3] 此次被排序数组的长度是: 3
先输出i=0  j=2
*************************又经过了一次j交换,交换的数组下标j的值为 2 这时的数组为 [3, 5, 4]
*************************又经过了一次i交换,交换的数组下标i的值为 1 这时的数组为 [3, 4, 5]
先输出i=1  j=2
*************************又经过了一次j交换,交换的数组下标j的值为 1 这时的数组为 [3, 4, 5]
*************************又经过了一次i交换,交换的数组下标i的值为 1 这时的数组为 [3, 4, 5]
这一轮过后key两边的数组是:                                                      [3] [ 4 ] [5] 整个数组为: [3, 4, 5]

对4的左边排序
4左边返回的结果是 [3] key是 4
对4的右边进行排序
4右边返回的结果是 [5]
这里已经没有元素了
2右边返回的结果是 -1
这里已经没有元素了
6左边返回的结果是 -1 key是 6
对6的右边进行排序

  

最新文章

  1. Spring中的JDK动态代理
  2. Apache Commons CLI命令行启动
  3. C#函数式编程之由函数构建函数
  4. 包含中文的字符串中截取前N个字符
  5. JS 自定义回调函数callback
  6. JS跨域请求 JSONP B/S全代码
  7. shell 实现主板测试
  8. Graph Cuts学习笔记2014.5.16----1
  9. C#多线程编程的同步也线程安全
  10. node.js 生成二维码
  11. ld: framework not found FileProvider for architecture arm64
  12. 浅谈getResource方法
  13. 物联网将在2018年实现大规模发展--IBM的四大预测
  14. 【内核】嵌入式linux内核的五个子系统
  15. ISO8601时间格式
  16. gozmq的安装与使用
  17. [Gradle] 发布构件到本地仓库
  18. git源站安装
  19. kubernetes 滚动更新发布及回滚
  20. Tornado之架构概述图

热门文章

  1. springMVC接受对象实体并且对象实体里面又有对象集合方式
  2. 细数SuperComputer最新排名和常见Benchmark类型
  3. latex问题总结
  4. dispatch_group_t踩过的坑
  5. ActiveMQ学习笔记(1)----初识ActiveMQ
  6. [SCOI2009]windy数 数位dp
  7. django框架-DRF工程之认证功能
  8. 别了WindowsXP
  9. List Slider
  10. 管理ONS(Oracle Notification Service)