一、排序基本概念
1、排序概念
假设含有n个记录的序列为{r1,r2,r3……rn},其相应的关键字分别为{k1,k2……kn},需确定1,2……n的一种排序p1,p2,……pn,使其相应的关键字满足kp1<=kp2<=……kpn非递减(或非递增)关系,即使得序列成为按关键字有序的序列{rp1,rp2……rpn},这样的操作称为排序。
注意:(1)通常将数据元素称为元素。
(2)排序的依据是关键字之间的大小关系。
(3)关键字ki可以是记录r的主关键字,也可以是次关键字,甚至是若干数据项的组合。
2、组合排序的问题
例:大学为了选拔在主学科上更优秀的学生,要求对所有学生的所有科目总分降序排序,并且在同样总分的情况下将语数外总分做降序排名。
编号 姓名 语 数 外 物 化 历 政 生 地 总分 语数外 1 令狐冲 85 60 84 86 89 94 87 83 85 753 229 2 郭靖 66 64 56 45 76 56 56 78 76 573 186 3 杨过 85 78 64 68 84 78 73 88 64 682 227 4 张无忌 84 85 67 90 87 83 94 79 84 753 236
分析:这就是对总分和语数外总分两个次关键字的组合排序。
解决方案一(比较土):对于组合排序问题,可以先排序总分,若总分相等的情况下,再排序语数外总分。
解决方案二(推荐):把总分与语数外都当成字符串首尾连接在一起(注意不足三位前面补零),很容易得到令狐冲的“753229”要小于张无忌的“753236”,于是张无忌就排在令狐冲的前面。
结论:从这个例子也可以看出,多个关键字的排序最终都可以转化为单个关键字的排序。
二、排序的稳定性
1、基本概念假设ki=kj(1<=i<=n,1<=j<=n,i!=j),且在排序前的序列中ri领先于rj(即i<j)。如果排序后ri领先于rj,则称所用的排序算法是稳定的;反之,若可能使得排序后的序列中rj领先ri,则称所用的排序算法是不稳定的。
注意:(1)只要一组关键字实例不稳定,就可认为此排序方法不稳定。
(2)排序算法是否稳定,要通过分析才能得出。
2、举例分析
如下表经过对总分的降序排序后,总分高的排在前列。
编号 姓名 总分 1 令狐冲 753 2 郭靖 573 3 杨过 682 4 张无忌 753 此时对于令狐冲和张无忌而言,未排序时令狐冲在前,那么他们总分排序后,分数相等的令狐冲依然应该在前,这样才算稳定的排序。
编号 姓名 总分 1 令狐冲 753 4 张无忌 753 3 杨过 682 2 郭靖 573 如果他们两者颠倒了,则此排序是不稳定的。
编号 姓名 总分 4 张无忌 753 1 令狐冲 753 3 杨过 682 2 郭靖 573
三、排序的分类
1、内排序与外排序——待排序记录是否全部放置在内存中内排序——在排序的整个过程中,待排序的所有记录全部被放置在内存中。
内排序排序算法性能的3个影响因素:
(1)时间性能——高效率的内排序算法应该是具有尽可能少的关键字比较次数和尽可能少的记录移动次数。
(2)辅助空间——执行算法需要的辅助存储空间
(3)算法复杂性——算法本身的复杂度不是算法的时间复杂度,算法太过复杂会影响排序的性能。
外排序——由于排序的记录个数太多,不能同时放置在内存,整个排序过程需要在内外存之间多次交换数据才能进行。
2、插入排序、交换排序、选择排序和归并排序——根据排序过程中借助的主要操作把内排序分为插入排序、交换排序、选择排序和归并排序
理论 计算复杂性理论…… 自适应排序…… 交换排序 冒泡排序 快速排序 选择排序 选择排序 堆排序 插入排序 插入排序 希尔排序 归并排序 归并排序 分布排序 珠排序…… 桶排序…… 并发排序 双调排序器 两两排序网络 混合排序 Spread排序…… 积木排序…… 其他 拓扑排序 3、简单算法和改进算法——按照算法的复杂度
冒泡排序、简单选择排序和直接插入排序属于简单算法;希尔排序、堆排序、归并排序、快速排序属于改进算法。
四、排序常用到的结构和函数
1、排序用的顺序表结构#define MAXSIZE 10 //用于排序数组个数的最大值,可根据需要修改
typedef struct
{
int r[MAXSIZE+1];//用于存储要排序数组,r[0]用作哨兵或临时变量int length;//用于记录顺序表的长度
}2、排序最常用的数组两元素的交换
void swap(SqList *L,int i,int j)//交换L中数组r下标为i和j的值
{
int temp=L->r[i];
L->r[i]=L->r[j];
L->r[j]=temp;
}
学习排序算法的目的更多并不是为了去在现实中编程排序算法,而是通过学习来提高我们编写算法的能力,以便于去解决更多复杂和灵活的应用性问题
排序(一)__综述