基本概念
排序: 使记录按关键字递增或递减排列
关键字重复不影响记录顺序的排序称为稳定排序;影响记录顺序的称为不稳定排序。
仅在内存中进行的排序称为内部排序;涉及内外存交换的排序称为外部排序。
内部排序:插入排序、选择排序、交换排序、归并排序、分配排序。
排序算法的步骤:
1、比较两个关键字大小
2、改变指向记录的指针或移动记录本身的位置
1、插入排序
基本思想:每次将一个待排序的记录按其关键字大小插入到前面已经排好序的子文件中的适当位置,知道全部记录插入完成为止
1.1 直接插入排序
Code:
void InsertSort(SeqList R)
{
int i,j;
for (i = 2; i <= n; i++) //从第二项开始插入
{
if(R[i].key < R[i-1].key //如果当前项的key小于前一项的key 则前一项应该后移一位 将当前项插入到前一项的位置上
{
R[0] = R[i]; //用于判断结束条件 同时存放当前项副本
j = i-1;
do{
R[j+1] = R[j]; //将前一项后移一位
j--; //从右向左比较插入
} while(R[0].key < R[j].key) //当前项的key>=排序项的key时结束比较
R[j+1] = R[0]; //插入当前项到排序位置
}
}
}
基本思想:以第一项为有序区第一个元素 拿第二个key跟第一个key比较 小的话就把第一个后移一位 把第二个插入到第一个的位置;大于等于的话就继续拿第三个跟已经排好的第一第二个从后往前比较 若第三项的key小于排好的第二项的key 则把已经排好的第二项后移一位 继续拿第三项去比较已经排好的第一项 若第三项仍然小于排好的第一项 则第一项后移一位 第三项插入到第一项的位置;若第三项大于等于排好的第一项的key 则将第三项插入到第二项后移之后空出来的位置上;若第三项key大于等于已经排好的第二项的key 则插入到最后(阿弥陀佛 绕口令一般 也就自己能看懂。。。)
形象一点:打牌 抓牌的时候 每抓一张都会放到“你认为最合适的”地方,这个中间的思维过程就是插入排序。
1.2 希尔排序 (分组排序后再排序)
Code:
void ShellSort(SeqList R)
{
int increment = n; //初始增量 >0
do{
increment = increment/3+1; //计算下一个增量
ShellPass(R,increment); //调用排序函数
}while(increment > 1); //=1时结束
}
void ShellPass(SeqList R,int d)
{
for(int i = d+1;i < n; i++) //n为R的元素总数量
{
if(R[i].key < R[i-d].key)
{
R[0] = R[i]; //R[0]暂存单元 当前循环的元素暂存于此
j = i - d; //计算插入位置
do{
R[j+d] = R[j]; //后移
j = j -d; //前一条记录的位置
} while(j > 0 && R[0].key < R[j].key); //当前记录的key >= 前一位记录的key时结束
R[j+d] = R[0]; //将当前记录插入到正确的位置上
}
}
}
基本思想:将记录按某增量(步长)分组(跨增量位置的记录归为一组);然后对每组数据进行插入排序(因为每组的数据要比分组前少很多 所以相对比较快);对进行过第一次分组排序的数据再次按某递减的增量(步长)进行分组(递减不一定是减1 可以根据实际情况确定递减多少);然后对第二次分组的记录执行插入排序(因已经经过一次插入排序 所以每个分组相对来说顺序比较整齐 所以循环次数相对较少);再次递减增量(步长)重复上面的插入操作,知道步长为1结束插入排序。
这里的步长选取没有固定的规则,所以只能根据实际情况实际分析。希尔排序法是不稳定的(重复的值排序后顺序可能与排序前顺序不一样)。
形象一点:全球分工协作 每人完成其中的一部分工作(例如制造、组装等等) 一个部门完成一个零部件 一个工厂完成一个产品 多个工厂协作完成一批成品。