MOOC数据结构

mooc摘记

第一讲

1.捕捉程序的运行时间

image

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选项比较合理。

定理:任何仅以交换相邻两元素来排序的算法,其平均时间复杂度为O(n2)

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一共给出了四种解法。推荐第四种做法。
解法一:
遍历子列的左右端点,循环求和,思路简单,但时间复杂度高
image
解法二:
遍历子列的左端点,循环右端点求和,思路依旧简单,但时间复杂度低了一个档次
image
解法三:
分治法,先考虑左半边的最大子列和,再考虑右半边的最大子列和,最后考虑跨越中间分界线的最大子列和,那么当前想求的最大子列和即为三数中的最大值,之后递归求解整个数组。
image
代码:

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。
image

期中考试摘记

单选题

1.已知一棵完全二叉树的第6层(设根为第1层)有8个叶结点,则该完全二叉树的结点个数最多是:
A.119 B.111 C.39 D.52

解:首先回顾完全二叉树的特点——叶结点仅出现在最后的两层。
当第六层有8个叶结点时
第一种情况:树的深度为6,那么树的结点数为251+8=39;
第二种情况:树的深度为7,那么树的结点数为261+(258)2=111
故最大的结点个数为111

期末考试摘记

前记:做题的时候忘记滑动了,提交了之后才发现最后一个编程题没有写,呜呜呜

判断题

  1. NlogN2NlogN具有相同的增长速度。

应当是对的?NlogN2=2NlogN

选择题

  1. 在拓扑排序算法中用堆栈和用队列产生的结果会不同吗?
    A.以上全不对 B.有可能会不同 C.肯定是相同的 D.是的肯定不同

B.有可能不同,使用堆栈最后得到的就是从栈顶到栈底就是逆拓扑的有序序列,而使用队列就是正拓扑的有序序列。
考虑极端情况链式图,两者的结果就相同

  1. 若数据元素序列{ 11,12,13,7,8,9,23,4,5 }是采用下列排序方法之一得到的第二趟排序后的结果,则该排序算法只能是:
    A.插入排序 B.归并排序 C.选择排序 D.冒泡排序

再复习一下归并排序哈!这里我们其实可以清楚的知道,二躺排序后,选择排序和冒泡排序可以实现至少最大或者最小2个元素有序,而题目所给的数据不支持这个结论,故只能是插入排序,实现前2个元素有序

  1. 给定一有向图的邻接表如下。从顶点V1出发按深度优先搜索法进行遍历,则得到的一种顶点序列为:
    image
    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 根据后序和中序遍历输出先序遍历
本题要求根据给定的一棵二叉树的后序遍历和中序遍历结果,输出该树的先序遍历结果。
输入格式:
第一行给出正整数N(30),是树中结点的个数。随后两行,每行给出N个整数,分别对应后序遍历和中序遍历结果,数字间以空格分隔。题目保证输入正确对应一棵二叉树。
输出格式:
在一行中输出Preorder:以及该树的先序遍历结果。数字间有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

posted on   Qiansui  阅读(68)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示