前言
最近听米老师讲了一遍排序,之前上课老师也讲过,这次又听了一遍,对排序有了更进一步的认识。接下来介绍一下最常见的几种排序,以及自己对排序的理解。
插入排序
插入排序包括:直接插入排序与shell排序
1.直接插入排序
概念:通过线性搜索来确定待插入记录的位置
算法:图中每一行的数据表示插入了第i个记录后的序列。实下画线表示即将插入的第i+1个记录,虚线下画线表示第i个记录插入后的新位置。箭头连线从下一个待插入元素位置指向最终插入位置。
直接插入排序算法是稳定的,因为每次插入只与临近记录逐个比较,直到找到第一个不大于新纪录的值停止。
总结:直接插入排序是与有序数列比较排序
2.shell排序
与直接插入的不同:shell与直接插入排序不同的是,shell排序不是着眼于相邻记录之间的比较,而是对那些不相邻的记录进行比较和移动。
概念:shell排序通过分组进行排序,先将待排序序列分为若干个子序列,而且要保证子序列中的记录在原始数组中不相邻,且间距相同,分别对这些子序列进行插入排序;然后减少记录间的间距,减少小序列个数,将原始序列分为更大、更有序的子序列,分别进行插入排序;重复进行下去,直到最后间距减少为1(整个序列比较接近于正序状态),然后对整个序列进行插入排序。
总结:不相邻且间距相同,说白了就是高中学过的二分法,然后两两比较,最后变成一组有序数列。
选择排序
选择排序包括:直接选择排序与堆排序
1.直接选择排序
概念:算法思想是逐个找出第i个小的记录,并将这个记录与数组的第i个位置的记录交换,第i小的记录一次交换到位。
算法:图中每行表示第i次选择(0≤i<n-1)后的序列,带箭头的连线连接下一轮准备交换的两个记录。第一轮循环中,首先下标Smallest=0,从数组第一个记录向后扫描,发现34比45小,于是Smallest=1,继续向后扫描,发现12又比29小,于是Smallest=3,再向后扫描发现前面没有比12更小的数,于是12就是最小记录,12与45交换位置,依次类推,直到最后末序列中只剩下1个记录,这时整个数组都已经排好序。
直接选择排序算法是不稳定的:排序前,34在34'之前,34在第二轮就被交换到了数组下标为6的位置。34'所处的下标为4,由于算法是从前向后扫面,再第4轮(i=3)它先于34被选择出来,因此排序的结果是(34',34),不稳定。
总结:从小到大排序,拿出无序中的第一个数跟后的数比较,扫面出最小数,然后第一个数跟最小数交换位置,依次类推,就好比生活中买水果,大家在选择好坏水果的时候,其实就是利用的直接选择排序。
2.堆排序
概念:堆有两种,最大堆和最小堆。接下来介绍的是最大堆的排序算法。最大堆满足以下条件:堆中的每个父结点中的数据项都要大于或等于其子结点中的数据项。因此,最大堆的堆顶记录就是整个堆中的最大记录。次大记录则存放在堆顶的左或右子结点中,堆排序正是利用这一点来查找剩余记录中的最大记录。
算法:例如,待排序数组为{45,29,32,12,34,34',78},转化为堆得数组{78,34,45,12,29,34',32},如图(a)将堆顶最大记录78删除到数组末端后,序列变为{32,34,45,12,29,34',|78},竖线后面的数字表示已排好序,待调整结构如图(b),重新建堆后得到序列{45,34,34',12,32|78},如图(c),再次减掉堆顶45,并从根节点向下调整为新堆,得到序列{34,32,34',12,29|45,78}如图(d)。类似重复直到堆为空。34,34',12,32|78},如图(c),再次减掉堆顶45,并从根节点向下调整为新堆,得到序列{34,32,34',12,29|45,78}如图(d)。类似重复直到堆为空。
堆排序是不稳定的:因为在建堆过程中,二叉树的父子结点之间的移动不能保证两个重复记录一定保持原始输入顺序。例如图(c)之后,第三个出堆得就是34,最终排序结果为{12,29,32,34',45,78},算法不稳定。
总结:堆排序是在一堆数中找最大的放到树根,次大的放到树根下,然后把最大的删掉,把次大的放到树根,然后删掉,依次类推,直至树根为空,序就排好了。
先介绍到这,后边会再写一篇有关交换排序的,争取下次代码也能弄懂。