大三党,大数据专业,正在为面试准备,欢迎学习交流
。
文章详细总结了插入排序、希尔排序、选择排序、归并排序、交换排序(冒泡排序、快速排序)、基数排序、外部排序。从思想
到代码实现
。
1 排序的基本概念
1.1 何为排序
将一组数据元素序列重新排列,使得数据元素序列按某个数据项(关键字)有序。
1.2 稳定排序和不稳定排序
对于任意的数据元素序列,若排序前后所有相同关键字的相对位置都不变,则称该排序方法称为稳定的排序方法。
若存在一组数据序列,在排序前后,相同关键字的相对位置
发生了变化,则称该排序方法称为不稳定的排序方法。
1.3 内部排序和外部排序
若整个排序过程不需要访问外存便能完成,则称此类排序问题为内部排序;
反之,若参加排序的记录数量很大,整个序列的排序过程不可能在内存中 完成,则称此类排序问题为外部排序。
2 插入排序
2.1 基本思想
2.2 插入排序三步曲
定位->挤空->插入
- 在R[1…i-1]中查找R[i]的插入位置,
R[1…j].key R[i].key < R[j+1…i-1].key; - 将R[j+1…i-1]中的所有记录均后移 一个位置;
- 将R[i] 插入(复制)到R[j+1]的位置上
2.3 举例
排序过程:整个排序过程为n-1趟插入,即先将序列中第
1个记录看成是一个有序子序列,然后从第2个记录开始,
逐个进行插入,直至整个序列有序
2.4 算法的代码描述
- 两层循环外层控制无序序列的取值 内层控制岗哨在有序的排序 找到位置跳出插入
- r[0] 作为岗哨 每次从无序依次取出放入 用来和有序序列比较插入
- j控制有序序列 j=i-1 每次都从有序的最后一个开始
- i控制无序序列 从前往后取 和 j顺序相反
- 代码中从小到大排序
- 需要注意第二个循环如果岗哨比所有的值都要小最后会r[0] 和r[0]自己比较一样能够跳出循环
补充 重要 岗哨的目的也是为了防止覆盖 可以思考 如果先移动有序序列就会把无序序列的第一个值覆盖
typedef struct
{
int key;//关键字
float info;//该成员的其他信息
}JD;
void straisort(JD r[],int n)//对长度为n的序列
{
int i,j;
for(i=2;i<=n;i++)
{
r[0]=r[i]//第一个需要排序的设为岗哨 不取因为1看做有序 其余n-1看做无序序列
j=i-1;//从后往前
//需要注意第二个循环如果岗哨比所有的值都要小最后会r[0] 和r[0]自己比较一样能够跳出循环
while(r[0].key<r[j].key)
{
r[j+1]=r[j]
j--;
}
r[j+1]=r[0]
}
}
2.5 时间复杂度
最好情况分析:如果n个值比较。开始1个为有序 n-1为无序。需要进行n-1趟的排序。当序列为初始就是顺序排列。那么每次取出放入岗哨的值都比有序的大,那么每趟只需要比较一次。比较次数为n-1。由于需要放入岗哨再移动到有序的最后所以每趟移动2次。
最坏情况分析:当序列为初始就是逆序排列。一样是n-1趟排序,第1趟比较次数为2(特别注意 岗哨除了跟第一个值比较 还要跟自己比较一次才能跳出循环 回头看代码 )所以应该是 2,3,4…n 等差数列相加。第1趟移动为3次(1是移动到岗哨 2是有序值后移 3 是岗哨移到有序值之前的位置)所以应该是 3,3,4…n+1 等差数列相加
2.6 性能总结+改进直接插入的方法
简单插入排序的本质比较和交换
简单插入排序复杂度由逆序个数决定
如何改进简单插入排序复杂度?
- 分组,比如C(n,2)/2>2C((n/2),2)/2
- 3,2,1有3组逆序对(3,1)(3,2)(2,1)需要交换3次。但相隔较远的3,1交换一次后1,2,3就没有逆序对了。
- 基本有序的插入排序算法复杂度接近O(n)
3 希尔排序(插入排序的改进方法)
3.1 基本思想
分割成若干个较小的子文件,对各个子文件分别进行直接插入排序,当文件达到基本有序时,再对整个文件进行一次直接插入排序。
对待排记录序列先作“宏观”调整,再作“微观”调整
3.2 排序过程
- 首先将记录序列分成若干子序列,
- 然后分别对每个子序列进行直接插入排序,
- 最后待基本有序时,再进行一次直接插入排序
如下
其中,d 称为增量,它的值在排序过程中从大到小逐渐缩小,直至最后一趟排序减
为 1。
3.3 数值演示
记住思想,若干个部分有序最后达到整体有序,使得复杂度最低。
3.4 算法的代码描述
注意看注释,特别注意d[ ]是什么
1三个循环嵌套
2最外循环控制选择不同的d
3二层循环控制依次取出间隔为d的两个值,比较后后移一位
4最内层循环控制 2个值之间的比较换位置
//r[]表示待排序的序列 n表示个数
//d[]表示增量序列 就是d的取值 7 6 5 ..这样
// T表示几种增量序列 d[]的元素个数
void shellsort(JD r[],int
n,int d[],int T)