MOOC数据结构
mooc摘记
第一讲
1.捕捉程序的运行时间
2.解决问题的方法与效率
①数据的组织方式
②空间的利用效率
③算法的巧妙程度
第二讲
第九讲 排序上
1.冒泡排序
void Bubble_Sort(long long *x,long long n){//冒泡排序 long long temp; for(int i=n-1;i>0;--i){ for(int j=0;j<i;++j){ if(x[j]>x[j+1]){ temp=x[j]; x[j]=x[j+1]; x[j+1]=temp; } } } return ; }
2.插入排序
void Insertion_Sort(long long *x,long long n){//插入排序 long long temp,j; for(int i=1;i<n;++i){ temp=a[i]; for(j=i;j>0;--j){ if(temp<a[j-1]){ a[j]=a[j-1]; }else break; } a[j]=temp; } return ; }
插排例题1
对一组包含10个元素的非递减有序序列,采用插入排序排成非递增序列,其可能的比较次数和移动次数分别是:
A. 45,44 B. 54,63 C.100,54 D. 100,100
个人觉得,对于十个元素的非递减序列,插排成非递增序列,那么比较次数最多也就是1+2+3+4+5+6+7+8+9=45次,移动次数也为45次。当出现相同元素时,比较次数会减少。所以A选项比较合理。
定理:任何仅以交换相邻两元素来排序的算法,其平均时间复杂度为
3.归并排序
这里的函数传参遇到大数值时比较慢,此时推荐全局变量
void Merge(int r[], int r1[], int s, int m, int t){//合并两个升序数组为一个升序数组 int i = s, j = m + 1, k = s; while(i <= m && j <= t){ if(r[i] <= r[j]) r1[k ++] = r[i ++]; else r1[k ++] = r[j ++]; } while(i <= m) r1[k ++] = r[i ++]; while(j <= t) r1[k ++] = r[j ++]; return ; } void Merge_Sort(int r[], int s, int t){//归并排序 if(s != t){//可以划分 int m = (s + t) / 2, r1[maxm]; Merge_Sort(r, s, m);//求解子问题1 Merge_Sort(r, m + 1, t);//求解子问题2 Merge(r, r1, s, m, t);//合并两个序列 for(int i = s; i <= t; ++ i)//结果复制到r数组中 r[i] = r1[i]; } return ; }
4.快速排序
int Partition(int r[], int begin, int end){// 划分 int i = begin, j = end; while(i < j){ while(i < j && r[i] <= r[j]) -- j;// 右侧扫描 if(i < j){// 将小元素放在前面 int temp = r[i]; r[i] = r[j]; r[j] = temp; ++ i; } while(i < j && r[i] <= r[j]) ++ i;// 左侧扫描 if(i < j){// 将大元素放在后面 int temp = r[i]; r[i] = r[j]; r[j] = temp; -- j; } } return i; } void Quick_Sort(int r[], int begin, int end){// 快速排序 int pos; if(begin < end){ pos = Partition(r, begin, end); Quick_Sort(r, begin, pos - 1); Quick_Sort(r, pos + 1, end); } return ; }
PTA练习摘记
01-复杂度1 最大子列和问题
最大子列和问题,mooc一共给出了四种解法。推荐第四种做法。
解法一:
遍历子列的左右端点,循环求和,思路简单,但时间复杂度高
解法二:
遍历子列的左端点,循环右端点求和,思路依旧简单,但时间复杂度低了一个档次
解法三:
分治法,先考虑左半边的最大子列和,再考虑右半边的最大子列和,最后考虑跨越中间分界线的最大子列和,那么当前想求的最大子列和即为三数中的最大值,之后递归求解整个数组。
代码:
int Max3( int A, int B, int C ) { /* 返回3个整数中的最大值 */ return A > B ? A > C ? A : C : B > C ? B : C; } int DivideAndConquer( int List[], int left, int right ) { /* 分治法求List[left]到List[right]的最大子列和 */ int MaxLeftSum, MaxRightSum; /* 存放左右子问题的解 */ int MaxLeftBorderSum, MaxRightBorderSum; /*存放跨分界线的结果*/ int LeftBorderSum, RightBorderSum; int center, i; if( left == right ) { /* 递归的终止条件,子列只有1个数字 */ if( List[left] > 0 ) return List[left]; else return 0; } /* 下面是"分"的过程 */ center = ( left + right ) / 2; /* 找到中分点 */ /* 递归求得两边子列的最大和 */ MaxLeftSum = DivideAndConquer( List, left, center ); MaxRightSum = DivideAndConquer( List, center+1, right ); /* 下面求跨分界线的最大子列和 */ MaxLeftBorderSum = 0; LeftBorderSum = 0; for( i=center; i>=left; i-- ) { /* 从中线向左扫描 */ LeftBorderSum += List[i]; if( LeftBorderSum > MaxLeftBorderSum ) MaxLeftBorderSum = LeftBorderSum; } /* 左边扫描结束 */ MaxRightBorderSum = 0; RightBorderSum = 0; for( i=center+1; i<=right; i++ ) { /* 从中线向右扫描 */ RightBorderSum += List[i]; if( RightBorderSum > MaxRightBorderSum ) MaxRightBorderSum = RightBorderSum; } /* 右边扫描结束 */ /* 下面返回"治"的结果 */ return Max3( MaxLeftSum, MaxRightSum, MaxLeftBorderSum + MaxRightBorderSum ); } int MaxSubseqSum3( int List[], int N ) { /* 保持与前2种算法相同的函数接口 */ return DivideAndConquer( List, 0, N-1 ); }
ll n, a[maxm]; ll calc(int l, int r){ if(l == r) return a[l]; int m = l + r >> 1; ll max1 = calc(l, m), max2 = calc(m + 1, r), max3; ll maxl = 0, maxr = 0, t; t = 0; for(int i = m; i >= l; -- i){ t += a[i]; maxl = max(maxl, t); } t = 0; for(int i = m + 1; i <= r; ++ i){ t += a[i]; maxr = max(maxr, t); } max3 = maxl + maxr; return max(max1, max(max2, max3)); } void solve(){ cin >> n; for(int i = 1; i <= n; ++ i) cin >> a[i]; cout << calc(1, n); return ; }
第四种:在线处理
怎么说,就是遍历数组,累计和并统计最大和,当累计和小于0时,其不能对后面的子列最大和起到正向作用,所以直接将累计和置0。
期中考试摘记
单选题
1.已知一棵完全二叉树的第6层(设根为第1层)有8个叶结点,则该完全二叉树的结点个数最多是:
A.119 B.111 C.39 D.52
解:首先回顾完全二叉树的特点——叶结点仅出现在最后的两层。
当第六层有8个叶结点时
第一种情况:树的深度为6,那么树的结点数为;
第二种情况:树的深度为7,那么树的结点数为
故最大的结点个数为111
期末考试摘记
前记:做题的时候忘记滑动了,提交了之后才发现最后一个编程题没有写,呜呜呜
判断题
具有相同的增长速度。
应当是对的?
选择题
- 在拓扑排序算法中用堆栈和用队列产生的结果会不同吗?
A.以上全不对 B.有可能会不同 C.肯定是相同的 D.是的肯定不同
B.有可能不同,使用堆栈最后得到的就是从栈顶到栈底就是逆拓扑的有序序列,而使用队列就是正拓扑的有序序列。
考虑极端情况链式图,两者的结果就相同
- 若数据元素序列{ 11,12,13,7,8,9,23,4,5 }是采用下列排序方法之一得到的第二趟排序后的结果,则该排序算法只能是:
A.插入排序 B.归并排序 C.选择排序 D.冒泡排序
再复习一下归并排序哈!这里我们其实可以清楚的知道,二躺排序后,选择排序和冒泡排序可以实现至少最大或者最小2个元素有序,而题目所给的数据不支持这个结论,故只能是插入排序,实现前2个元素有序
- 给定一有向图的邻接表如下。从顶点V1出发按深度优先搜索法进行遍历,则得到的一种顶点序列为:
A.V1,V2,V4,V5,V3
B.V1,V2,V3,V5,V4
C.V1,V3,V4,V5,V2
D.V1,V4,V3,V5,V2
喂喂喂,深度优先!仔细点想想什么是深度优先搜索算法。可能的序列应该是C
编程题
呜呜呜,没做上
下面是原题:
R7-1 根据后序和中序遍历输出先序遍历
本题要求根据给定的一棵二叉树的后序遍历和中序遍历结果,输出该树的先序遍历结果。
输入格式:
第一行给出正整数
输出格式:
在一行中输出
输入样例:
7
2 3 1 5 7 6 4
1 2 3 4 5 6 7
输出样例:
Preorder: 4 1 3 2 6 5 7
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
本文来自博客园,作者:Qiansui,转载请注明原文链接:https://www.cnblogs.com/Qiansui/p/17204890.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现