排序算法

结构化编程
  • 一行一行执行

  • 有条件控制语句 if...else...

  • 有循环控制语句 while(exp) do...

伪代码
  • 伪代码的好处
    1.不用纠结于语法的细节,因为语法是你自己定的
    2.可以体会语言设计者的想法,因为语法是你自己定的
a <- {    //<-是赋值的意思
    '0': 23
    '1': 43
    '2': 239
    '3': 1321
    '4': 90
    'length': 5
}
min <-  a['0']
index <- 1
while index < a['length']
    if a[index] < min
        min <- a[index]
    end
    index <- index + 1
end
print min

流程图:


流程图

高德纳在他的著作《计算机程序设计艺术》里对算法的特征归纳:

  • 输入:一个算法必须有零个或以上输入量。
  • 输出:一个算法应有一个或以上输出量,输出量是算法计算的结果。
  • 明确性:算法的描述必须无歧义,以保证算法的实际执行结果是精确地匹配要求或期望,通常要求实际运行结果是确定的。
  • 有限性:依据图灵的定义,一个算法是能够被任何图灵完备系统模拟的一串运算,而图灵机只有有限个状态、有限个输入符号和有限个转移函数(指令)。而一些定义更规定算法必须在有限个步骤内完成任务。
  • 有效性:又称可行性。能够实现,算法中描述的操作都是可以通过已经实现的基本运算执行有限次来实现
冒泡排序
  • 冒泡排序(Bubble Sort,台湾译为:泡沫排序或气泡排序)是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。
  • 冒泡排序算法的流程如下:
    1.比较相邻的元素。如果第一个比第二个大,就交换他们两个。
    2.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
    3.针对所有的元素重复以上的步骤,除了最后一个。
    4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。


  • 伪代码:
选择排序(selection sort)
  • 每次找出最小(大)的放在最前面,找的过程也是两两对比,确定出最值来。

  • Eg:6,4,2,3,1,5

  • 第一步找出这里面最小的放在最前面,其他的位置不变:1,6,4,2,3,5

  • 第二步继续以上操做找出出第一个被确定的以外的最小的一个:1,2,6,4,3,5


    如图所示,是寻找最小值,相当于每轮都要和每一个元素进行对比得出最小值放入有序区。
  • 伪代码:
插入排序(起扑克牌法)
  • 第一步将第一个元素划分到有序区
  • 取第二个元素和有序区的元素从后往前的进行对比
  • 如果新元素小于有序区里被比较的元素,那么新元素移动到被比较元素的前面去
  • 新元素依次跟有序元素对比,直到插入到合适位置
  • 再取新元素,重复步骤2-4,直到排序完成
快排法(Quick sort)
  • 通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
  • 先取出一个元素,称为 “基准”(pivot)
  • 然后对数列进行一次比较排序,与基准作比较,比基准值小的摆放在基准前面,比基准值大的摆在基准的后面(相同的数可以到任一边)。这次操作结束之后,这个基准就基本位于数列的中间位置。这个称为分区(partition)操作;
  • 然后在对基准两边的区,分别进行1-2操作,取出不同的基准,分成不同区,最终达成有序排列。


    根据动图我们很好理解,第一次以15为基准,分了左右两个区,接着是5,4,3依次为基准,最终确定了右边的序列,接着在来分左边区,步骤一样。排序就完成啦。
计数排序(Counting Sort)
  • 在此之前介绍的排序是比较排序,需要两两比较的,但是计数排序不是基于比较的排序算法,其核心在于将输入的数据值转化为键存储在额外的桶内。


  • 如图,我们根据最大值做了1-9的桶,然后将数列按照对应数值进桶,桶里进行记次,进来几个就几次,出桶也一样,有几次就出几次桶,这样一次进桶出桶操作就排完序了。
  • 伪代码:
桶排序 (Bucket sort)

桶排序的工作的原理:假设输入数据服从均匀分布,将数据分到有限数量的桶里,每个桶再分别排序。

  • 设置空桶的范围,比如1-100,101-200这样子的范围;
  • 接着遍历all输入数据,并且把数据一个一个放到对应的桶里去;
  • 对每个不是空的桶进行排序;
  • 从不是空的桶里把排好序的数据拼接起来,排序就完成了。
  • 和计数排序的区别就在于桶,桶排序是每个桶是一个值,而这里是一个范围,同时桶排序还需要在桶内进行二次排序。
基数排序(Radix sort)

设想一下,假如我们要排序1-10万,难道我们还要排10万个桶吗?所以就可以使用基数排序,它是基于进制的一个排序。

  • 基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。
  • 先分配所有元素的个位,按照个位分配到0-9
  • 先入先出,这样有了第一次基于个位数的排序
  • 接着分配十位,百位,直到当前进制所有元素都为0
  • 通过多次的进桶出桶保证了当前进制的大小排序,通过每一次进桶出桶均是先进先出,因而保证了每一次的排序是基于前一次排序的。


堆排序

最大堆:
1.最大堆中的最大元素出现在根节点即堆顶
2.堆中每个父节点的元素值都大于等于其孩子的节点(若存在)
3.最大堆调整:保持最大堆性质,是创建最大堆的核心子程序
4.堆排序则是利用了最大堆可以记录最大值这样一个特性。

  • 最初将待排序序列(R1,R2,……Rn)进行一次最大堆调整,得到一个堆顶(最大值)
  • 将堆顶R1与最后一个元素Rn交换,分成一个新的完全二叉树(R1-Rn-1)和一个有序区(Rn)
  • 对新的完全二叉树继续最大堆调整,得到新的最大堆后重复第二个步骤,如此反复执行,直到有序区里n-1个元素,此时排序完成。


你可能感兴趣的:(排序算法)