没有合适的资源?快使用搜索试试~ 我知道了~
常用的经典排序算法,适合于即将要找工作的朋友们,哈哈
资源详情
资源评论
资源推荐
排序算法一览
第 10 章 排序
10.1 基本概念
排序(Sorting)是计算机程序设计中的一种重要操作,其功能是对一个数据元素集合或序列重新排列成一个按数据元素
某个项值有序的序列。作为排序依据的数据项称为“排序码”,也即数据元素的关键码。为了便于查找,通常希望计算
机中的数据表是按关键码有序的。如有序表的折半查找,查找效率较高。还有,二叉排序树、 B-树和 B+树的构造过
程就是一个排序过程。若关键码是主关键码,则对于任意待排序序列,经排序后得到的结果是唯一的;若关键码是次
关键码,排序结果可能不唯一,这是因为具有相同关键码的数据元素,这些元素在排序结果中,它们之间的的位置关
系与排序前不能保持。
若对任意的数据元素序列,使用某个排序方法,对它按关键码进行排序:若相同关键码元素间的位置关系,排序前与
排序后保持一致,称此排序方法是稳定的;而不能保持一致的排序方法则称为不稳定的。
排序分为两类:内排序和外排序。
内排序:指待排序列完全存放在内存中所进行的排序过程,适合不太大的元素序列。
外排序:指排序过程中还需访问外存储器,足够大的元素序列,因不能完全放入内存,只能使用外排序。
10.2 插入排序
10.2.1 直接插入排序
设有 n 个记录,存放在数组 r 中,重新安排记录在数组中的存放顺序,使得按关键码有序。即
r[1].key≤r[2].key≤……≤r[n].key
先来看看向有序表中插入一个记录的方法:
设1<j≤n,r[1].key≤r[2].key≤……≤r[j-1].key,将 r[j]插入,重新安排存放顺序,使得 r[1].key≤r[2].key≤……
≤r[j].key,得到新的有序表,记录数增1。
【算法 10.1】
① r[0]=r[j]; //r[j]送 r[0]中,使 r[j]为待插入记录空位
i=j-1; //从第 i 个记录向前测试插入位置,用 r[0]为辅助单元, 可免去测试 i<1。
② 若 r[0].key≥r[i].key,转④。 //插入位置确定
③ 若 r[0].key < r[i].key 时,
r[i+1]=r[i];i=i-1;转②。 //调整待插入位置
④ r[i+1]=r[0];结束。 //存放待插入记录
【例 10.1】向有序表中插入一个记录的过程如下:
r[1] r[2] r[3] r[4] r[5] 存储单元
2 10 18 25 9 将 r[5]插入四个记录的有序表中,j=5
r[0]=r[j];i=j-1; 初始化,设置待插入位置
2 10 18 25 □ r[i+1]为待插入位置
i=4,r[0] < r[i],r[i+1]=r[i];i--; 调整待插入位置
2 10 18 □ 25
i=3,r[0] < r[i],r[i+1]=r[i];i--; 调整待插入位置
2 10 □ 18 25
i=2,r[0] < r[i],r[i+1]=r[i];i--; 调整待插入位置
2 □ 10 18 25
i=1,r[0] ≥r[i],r[i+1]=r[0]; 插入位置确定,向空位填入插入记录
2 9 10 18 25 向有序表中插入一个记录的过程结束
直接插入排序方法:仅有一个记录的表总是有序的,因此,对 n 个记录的表,可从第二个记录开始直到第 n 个记录,
逐个向有序表中进行插入操作,从而得到 n 个记录按关键码有序的表。
【算法 10.2】
void InsertSort(S_TBL &p)
{ for(i=2;i<=p->length;i++)
if(p->elem[i].key < p->elem[i-1].key) /*小于时,需将 elem[i]插入有序表*/
{ p->elem[0].key=p->elem[i].key; /*为统一算法设置监测*/
for(j=i-1;p->elem[0].key < p->elem[j].key;j--)
p->elem[j+1].key=p->elem[j].key; /*记录后移*/
p->elem[j+1].key=p->elem[0].key; /*插入到正确位置*/
}
}
【效率分析】
空间效率:仅用了一个辅助单元。
时间效率:向有序表中逐个插入记录的操作,进行了 n-1 趟,每趟操作分为比较关键码和移动记录,而比较的次数和
移动记录的次数取决于待排序列按关键码的初始排列。
最好情况下:即待排序列已按关键码有序,每趟操作只需 1 次比较 2 次移动。
总比较次数=n-1 次
总移动次数=2(n-1)次
最坏情况下:即第 j 趟操作,插入记录需要同前面的 j 个记录进行 j 次关键码比较,移动记录的次数为 j+2 次。
平均情况下:即第 j 趟操作,插入记录大约同前面的 j/2 个记录进行关键码比较,移动记录的次数为 j/2+2 次。
由此,直接插入排序的时间复杂度为 O(n2)。是一个稳定的排序方法。
10.2.2 折半插入排序
直接插入排序的基本操作是向有序表中插入一个记录,插入位置的确定通过对有序表中记录按关键码逐个比较得到的。
平均情况下总比较次数约为 n2/4。既然是在有序表中确定插入位置,可以不断二分有序表来确定插入位置,即一次比
较,通过待插入记录与有序表居中的记录按关键码比较,将有序表一分为二,下次比较在其中一个有序子表中进行,
将子表又一分为二。这样继续下去,直到要比较的子表中只有一个记录时,比较一次便确定了插入位置。
二分判定有序表插入位置方法:
① low=1;high=j-1;r[0]=r[j]; // 有序表长度为 j-1,第 j 个记录为待插入记录
//设置有序表区间,待插入记录送辅助单元
② 若 low>high,得到插入位置,转⑤
③ low≤high,m=(low+high)/2; // 取表的中点,并将表一分为二,确定待插入区间*/
④ 若 r[0].key<r[m].key,high=m-1; //插入位置在低半区
否则,low=m+1; // 插入位置在高半区
转②
⑤ high+1 即为待插入位置,从 j-1 到 high+1 的记录,逐个后移,r[high+1]=r[0];放置待插入记录。
【算法 10.3】
void InsertSort(S_TBL *s)
{ /* 对顺序表 s 作折半插入排序 */
for(i=2;i<=s->length;i++)
{ s->elem[0]=s->elem[i]; /* 保存待插入元素 */
low=i;high=i-1; /* 设置初始区间 */
while(low<=high) /* 该循环语句完成确定插入位置 */
{ mid=(low+high)/2;
if(s->elem[0].key>s->elem[mid].key)
low=mid+1; /* 插入位置在高半区中 */
else high=mid-1; /* 插入位置在低半区中 */
}/* while */
for(j=i-1;j>=high+1;j--) /* high+1 为插入位置 */
s->elem[j+1]=s->elem[j]; /* 后移元素,留出插入空位 */
s->elem[high+1]=s->elem[0]; /* 将元素插入 */
}/* for */
}/* InsertSort */
【时间效率】
确定插入位置所进行的折半查找,关键码的比较次数至多为 ,次,移动记录的次数和直接插入排序相同,故时间复杂
度仍为 O(n2)。是一个稳定的排序方法。
10.2.3 表插入排序
直接插入排序、折半插入排序均要大量移动记录,时间开销大。若要不移动记录完成排序,需要改变存储结构,进行
表插入排序。所谓表插入排序,就是通过链接指针,按关键码的大小,实现从小到大的链接过程,为此需增设一个指
针项。操作方法与直接插入排序类似,所不同的是直接插入排序要移动记录,而表插入排序是修改链接指针。用静态
链表来说明。
#define SIZE 200
typedef struct{
ElemType elem; /*元素类型*/
int next; /*指针项*/
}NodeType; /*表结点类型*/
typedef struct{
NodeType r[SIZE]; /*静态链表*/
int length; /*表长度*/
}L_TBL; /*静态链表类型*/
假设数据元素已存储在链表中,且 0 号单元作为头结点,不移动记录而只是改变链指针域,将记录按关键码建为一个
有序链表。首先,设置空的循环链表,即头结点指针域置 0,并在头结点数据域中存放比所有记录关键码都大的整数。
接下来,逐个结点向链表中插入即可。
【例 10.2】表插入排序示例
MAXINT 49 38 65 97 76 13 27 49
0 - - - - - - - -
MAXINT 49 38 65 97 76 13 27 49
1 0 - - - - - - -
MAXINT 49 38 65 97 76 13 27 49
2 0 1 - - - - - -
MAXINT 49 38 65 97 76 13 27 49
2 3 1 0 - - - - -
MAXINT 49 38 65 97 76 13 27 49
剩余17页未读,继续阅读
chen13826445456
- 粉丝: 0
- 资源: 1
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- Screenshot_20240427_031602.jpg
- 网页PDF_2024年04月26日 23-46-14_QQ浏览器网页保存_QQ浏览器转格式(6).docx
- 直接插入排序,冒泡排序,直接选择排序.zip
- 在排序2的基础上,再次对快排进行优化,其次增加快排非递归,归并排序,归并排序非递归版.zip
- 实现了7种排序算法.三种复杂度排序.三种nlogn复杂度排序(堆排序,归并排序,快速排序)一种线性复杂度的排序.zip
- 冒泡排序 直接选择排序 直接插入排序 随机快速排序 归并排序 堆排序.zip
- 课设-内部排序算法比较 包括冒泡排序、直接插入排序、简单选择排序、快速排序、希尔排序、归并排序和堆排序.zip
- Python排序算法.zip
- C语言实现直接插入排序、希尔排序、选择排序、冒泡排序、堆排序、快速排序、归并排序、计数排序,并带图详解.zip
- 常用工具集参考用于图像等数据处理
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0