ds第八章学习记录
Posted drgnibasaw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ds第八章学习记录相关的知识,希望对你有一定的参考价值。
一.知识梳理
- 若整个排序过程不需要访问外存便能完成,则称此类排序问题为内部排序 --- 逐步扩大记录的有序序列长度的过程
外部排序
- 插入 交换 选择归并 分配
- 排序算法效率的评价指标:时间效率 空间效率 稳定性 (--- A和B的关键字相等,排序后A、B的先后次序保持不变)
♦直接插入排序(基于顺序查找)
从R[i-1]起向前进行顺序查找 监视哨设置在R[0]
R[0] = R[i]; // 设置“哨兵”
for (j=i-1; R[0].key<R[j].key; --j) // 从后往前找
两个操作 → 比较 → 移动
♦折半插入排序(基于折半查找)
void Binsert Sort(SqList &L) {//对顺序表L做折半插入排序 for (i=2; i < =L. length; ++i) { L.r[O)=L.r[i); //将待插入的记录暂存到监视哨中 low=l;high=i-1; //初值 while(low<=high) { m=(low+high)/2; if(L.r[O) .key<L.r[m) .key) high=m-1; //前一子表 else low=m+l; //后一子表 } for (j=i-l;j>=high+l; --j) L.r[j+l]=L.r(j]; //记录后移 L.r[high+l]=L.r[O]; } }
减少了比较次数,但没有减少移动次数
♦希尔排序(基于逐趟缩小增量)
步骤
- 宏观调整 ---- 跳跃式的插入排序
- 微观调整
如何选择最佳d序列,目前尚未解决
最后一个增量值必须为1,无除1以外的公因子
不宜在链式存储结构上实现
♦冒泡排序(结合上学期书本)
每趟不断将记录两两比较 挤出一个最大值到最后面位置 并按“前小后大” 规则交换
♦快速排序
取一个元素为中心 所有比它小的元素放前面 比它大的元素放后面 形成左右两个子表
对各子表重新选择中心元素并依此规则调整 直到每个子表的元素只剩一个
int Partition ( SqList &L,int low, int high) { L.r[0] = L.r[low]; pivotkey = L.r[low].key; while (low < high) { while(low<high && L.r[high].key>=pivotkey) --high; L.r[low] = L.r[high]; while(low<high && L.r[low].key<=pivotkey ) ++low; L.r[high] = L.r[low]; } L.r[low]=L.r[0]; return low; }
每趟确定的元素呈指数增加 不稳定 --- 可选任一元素为支点
♦选择排序
每一趟在后面 n-i+1个中选出关键码最小的对象, 作为有序序列的第i个记录。
void SelectSort(SqList &L) { for (i=1; i<L.length; ++i) { k=i; for( j=i+1; j<=L.length ; j++) if ( L.r[j].key <L.r[k].key) k=j; if(k!=i) L.r[i]←→L.r[k]; } }
♦堆排序
利用树的结构特征来描述堆 但是!树只是作为堆的描述工具 堆实际还是存放在线性空间中的
大根堆 小根堆
- 将无序序列建成一个堆
- 输出堆顶的最小(大)值
- 使剩余的n-1个元素又调整成一个堆,则可得到n个元素的次小值
- 重复执行,得到一个有序序列
- 输出堆顶元素后,以堆中最后一个元素替代
- 将根结点与左、右子树根结点比较,并与大者(大根堆)交换
- 重复直至叶子结点,得到新的堆
♦归并排序
将两个或两个以上的有序子序列“归并”为一个有序序列 --- 辅助数组
二.作业整理
- 外排序的瓶颈在于将记录从输入缓冲区归并入输出缓冲区。
- 就排序算法所用的辅助空间而言 堆排序 < 快速排序 < 归并排序
-
下列排序算法中,在每一趟都能选出一个元素放到其最终位置上,并且其时间性能受数据初始特性影响的是(A)。
-
A.
快速排序
B.直接插入排序
C.直接选择排序
D.堆排序
-
实践一
计算机程序设计能力考试(Programming Ability Test,简称PAT)旨在通过统一组织的在线考试及自动评测方法客观地评判考生的算法设计与程序设计实现能力,科学的评价计算机程序设计人才,为企业选拔人才提供参考标准(网址http://www.patest.cn)。
每次考试会在若干个不同的考点同时举行,每个考点用局域网,产生本考点的成绩。考试结束后,各个考点的成绩将即刻汇总成一张总的排名表。
现在就请你写一个程序自动归并各个考点的成绩并生成总排名表。
提交时间 状态 分数 题目 编译器 耗时 2020/07/12 14:20:27 答案正确30 7-1 C++ (g++) 146 ms
测试点 结果 耗时 内存 0 答案正确5 ms 1664 KB 1 答案正确5 ms 1664 KB 2 答案正确5 ms 1764 KB 3 答案正确146 ms 2600 KB
#include<iostream> #include<algorithm> #include<cstdio> using namespace std; #define MAX 30010 typedef struct { string num;//考号 int total;//最终排名 int score;//分数 int place;//考点编号 int rank;//考点排名 }Stu; Stu stdu[MAX]; bool fun(Stu s,Stu t) { if(s.score>t.score) return 1; else if(s.score==t.score) if(s.num<t.num) return 1; else return 0; // return s.score>t.score; // else return s.num<t.num; } int main() { int n,m=0,a; cin>>n; for(int i=0;i<n;i++) { cin>>a; for(int j=m;j<m+a;j++) { cin>>stdu[j].num>>stdu[j].score; stdu[j].place=i+1; } sort(stdu+m,stdu+m+a,fun); //排序 每一个考场的 int flag=1; for(int j=m;j<m+a;j++) { if(j==m) stdu[j].rank=flag; else { if(stdu[j].score==stdu[j-1].score) //!相同分数 stdu[j].rank=stdu[j-1].rank; else stdu[j].rank=flag; } flag++; } m+=a; } sort(stdu,stdu+m,fun); int flag=1; for(int j=0;j<m;j++) { if(j==0) stdu[j].total=flag; else { if(stdu[j].score==stdu[j-1].score) stdu[j].total=stdu[j-1].total; else stdu[j].total=flag; } flag++; } cout<<m<<endl; for(int i=0;i<m;i++) { cout<<stdu[i].num<<" "<<stdu[i].total<<" "<<stdu[i].place<<" "<<stdu[i].rank<<endl; } return 0; }
注意点
- 我给stu取变量名的时候用了std 但是std是关键字啊! 不行不行的!
- 有时候数组的实例化,要思考一下到底在主函数内还是主函数外
- 不停调用sort 来实现排序
- 注意重分的情况
准备期末考了,很多我感觉有些知识还只是浮在表面的理解,要加深理解呀!加油冲冲冲!
以上是关于ds第八章学习记录的主要内容,如果未能解决你的问题,请参考以下文章