插入排序
算法思想:每次将一个待排序的序列插入到前面一个已排好序的子序列当中。
- 直接插入排序
1)查找L(i)在L[1,i-1]中的插入位置
2)将L[k,i-1]中的所有元素向后移动一个位置
3)将L(i)复制到L(k)位置
代码
时间复杂度分析:假设排序后,数据需要从小到大排列
最优情况:初始数据序列为顺序,只需要进行n次比较就好,时间复杂度为O(N)
最差情况:初始序列为逆序,外面的循环需要经历n次,内部循环总共需要经历n次比较交换,时间复杂度为O(N^2)
- 希尔排序
先将排序表分割成d个形如L[i,i+d,i+2d,…,i+kd]的特殊组,分别对每一个组进行直接插入排序,逐步减小增量d,当整个表中的元素呈现“基本有序时”,再对全体记录进行一次直接插入排序
对于d的取值变化,初始化为n/2取下界,然后每一次迭代除2取下届,直到d=1
代码
交换排序
- 冒泡排序
假设待排序表长为n,从后往前两两比较相邻元素的值,如果A[i-1]<A[i],交换他们两者的位置。每一轮迭代后可以确定乱序子序列的中最大值放置在正确的位置;最多迭代n次;为了减少不必要的比较,当某一轮迭代过程中不存在元素交换时,代表数组有序,可以提前跳出循环
代码实现
3. 快速排序
在待排序表中人去一个元素pivot作为基准,通过一趟排序将待排序分为两部分,左边部分元素都小于pivot,右边的元素都大于pivot,一次划分将会将pivot放在正确的位置
划分思路:初始化标记low为划分部分第一个元素的位置,high最有最后一个元素的位置,然后不断移动两个标记并交换元素
1)high向前移动找到第一个比pivot小的元素
2)low向后移动找到第一个比pivot大的元素
3)交换当前low和high位置的元素
4)重复步骤1,2,3,直到low大于等于high
代码实现
时间复杂度分析:
如过pivot选择比较好,每次均匀地划分数组,这样树的最小高度为log2(n),即只需要划分log2(n)次;最差的情况就是pivot是最大值(最小值),这样退化为了选择排序;每次划分的比较交换复杂度为O(n),因此最优的时间复杂度为O(nlog2(n)),最差为O(n^2)
选择排序
- 直接选择排序
每一趟在后面n-i+1个待排序元素中选取最小的元素作为前面有序子序列的第i个元素,迭代n-1次,待排序元素只剩下一个,排序完成
代码实现
最优、最差的时间复杂度都为O(n^2) - 堆排序
大根堆初始化:对所有具有双亲节点含义编号从大到小作出如下调整
1)如果孩子节点均小于双亲节点,则该节点的调整结束
2)如果存在孩子节点大于双亲节点,则将最大的孩子节点与双亲节点进行交换,并对进行了交换的孩子节点进行步骤1,2,直到出现情况1或者递归遍历到了叶子节点
代码实现
堆插入:将新的节点放置在末端,然后向上进行调整
归并排序
归并
时间复杂度为O(nlogn):每一趟归并需要访问的数据为O(n),需要遍历的趟的次数为O(logn)。
基数排序
其中r就是d的取值范围,这个地方d的取值范围是[0,9],因此r=10。