zoukankan      html  css  js  c++  java
  • 程序员修炼之路-(3)排序(上):基本排序

    基本排序

    对于所有排序算法,被排序元素需要满足下列数学性质:

    Ø  自反性(reflextivefor all vv=v

    Ø  对称性(antisymmetricfor all v and wif v<w then w>v and if v=w then w=v

    Ø  传递性(transitivefor all vw and xif v<=w and w<=x then v<=x

    对于包含这样元素的数组,我们才能对其排序。

    1.1 选择排序(selection sort)

    思路与实现

    选择排序的思路很简单:数组的前半部分是排好序的,那么之后不断从后半部分选择出最小元素,交换到后半部分的第一个位置上。


    实现思路很清晰,要注意的是要用数组下标记录min的位置,然后才能swap,避免低级错误


    选择排序的特点

    1)输入不敏感:在任何输入上的性能总是n平方,不存在最好、平均、最坏情况之分。

    2)数据移动最小化keyswap次数仅为n-1。这也是在众多排序算法中,选择排序的与众不同之处

    1.2 冒泡排序(bubble sort)

    思路与实现

    冒泡排序不断交换两个元素的位置,将最大元素冒泡到数组末尾。


     


    基本排序的思想很简单,所以实现时一般循环体比较好写,难的是循环条件。例如,冒泡排序的inner loop写成j<i-1,没想好是<还是<=,结果造成最后一个元素永远不会被排序。


    冒泡排序与选择排序类似,在任何输入上性能都一样。但是swap次数却与输入相关。

    1.3 插入排序(insertion sort)

    思路与实现

    与选择排序很类似,插入排序也将数组看成前后两部分。但是插入排序是将后半部分第一个元素,插入到它应在的位置上。生活中最典型的例子就是玩牌时排序手中的牌,但编程实现中,我们要挪动数组中的元素才能将后面的牌插入到它应在的位置。



    实现时想到了两种做法:

    1) 第一种是比较后将A[i]向前swap,然后inner loop下一次迭代继续比较A[i]与前一个元素,后面能看到JDK 6中就是采用这种实现方式,但能够证明这种方式inner loopbody中操作更多,整体上比第二种方式要慢(《算法设计与分析基础》插入排序的一道练习题)。

    2) 另一种则较为标准,将A[i]与前面元素逐个比较找到其位置,比较过程中将这些大于A[i]的元素后移。注意循环终止条件对后面代码的推导作用。


    插入排序的特点

    在已经或几乎排好序的数组上,运行的非常快。因为每一轮比较都会立即或很快结束。怎么定义几乎排好序?这里引入逆序对inversion)的概念,指与最终顺序相反的两个元素。当逆序对少于数组长度的常数倍时就认为数组是部分排序的(partially sorted)。当逆序对很少时,插入排序要快于任何其他排序算法(选择、冒泡、归并、快速排序等)。同时,插入排序对小数组也是个不错的排序算法,这也是为什么JDK 6Arrays.sort()中对长度小于7的原始类型的小数组用插入排序,而大数组时用快速排序(JDK 7中已升级为DualPivotQuicksort)。


    以下是总结的插入排序的几种典型应用情况:

    1) 每个元素都离最终位置不远。

    2) 只有少数元素不在最终位置。

    3) 小数组拼接到一个已排序的大数组后面。

    4) 很小的数组。

     

  • 相关阅读:
    洛谷 P1202 [USACO1.1]黑色星期五Friday the Thirteenth 题解
    洛谷 P1957 口算练习题 题解
    洛谷 P2036 Perket 题解
    洛谷 P2369 EXCEEDED WARNING A 题解
    洛谷 P1184高手之在一起 题解
    洛谷 P1897电梯里的爱情 题解
    Python做的眼睛护士
    Python-Tkinter的Entry详解
    Python的TkinterButton做为父窗口
    Python用Tkinter的Frame实现眼睛护士的倒计时黑色屏幕
  • 原文地址:https://www.cnblogs.com/xiaomaohai/p/6157634.html
Copyright © 2011-2022 走看看