1.本周学习总结
1.1思维导图
1.2.对线性表的认识及学习体会
个人感觉线性表是一种用基础语言构造出来的一种常用算法,并不是来源于语言自身所带的。也就感觉是新学了一种算法。对于线性表的顺序储存结构的编程倒是没什么问题,但对于链式储存结构——链表编程题,虽然能够理解每个语句的意思以及它的逻辑结构,但是编程时不断的出现编程错误,接着就是段错误,而且函数的缺失,使代码无法在编译器内运行,很难找出错误,可谓是困难重重,个人认为还需要一段时间来加深对链表的理解。
2.PTA实验作业
2.1.题目1:
从顺序表中删除重复的元素,并使剩余元素间的相对次序保存不变。
输入格式:
第一行输入顺序表长度。 第二行输入顺序表数据元素。中间空格隔开。
输出格式:
数据之间空格隔开,最后一项尾部不带空格。
2.1.1设计思路
CreateSqList建立顺序表
定义i
顺序表L申请空间
L的长度置为n
for i=0 to n
L->data[i]=a[i] 顺序表置赋值
//此函数申请顺序表空间,将数组a[i]的值放入顺序表中
DelSameNode 删除重复数据
定义 i,j
定义 k=0
定义 len=0 新表的长度
定义 b[10]={0,0,0,0,0,0,0,0,0,0} 新表的赋值数组
for i=0 to L->length
b[L->data[i]]++ 将相应元素值放入数组b[i]中
for j=0 to 10
if b[j] 大于 0 如果b[j]>0,则将其下标的值放入新表中
{
L->data[k]=j 下标的值
k++
len++
}
L->length=len 将长度置为len
//主要是将每个数值当作新数组的下标,并对这个下标代表的值++,再对这个数组b[j]扫描,凡是大于0的则放入新表中,重构数组和顺序表,免去了复杂的数组a[i]删除操作
DispSqList 顺序表的输出
定义 i
for i=0 to L->length 循环输出顺序表
if i 等于 L->length-1
输出 L->data[L->length-1]
else
输出 L->data[i] 空格
//利用循环结构输出顺序表,在最后一个输出时控制一下空格问题
2.1.2代码截图
2.1.3本题PTA提交列表说明。
-
Q1:出现编译错误
-
A1:L=new SqList;语句出现问题,导致一开始顺序表L的申请就出错了
-
Q2:部分正确
-
A2:原因在定义的数组b[j]没有进行初始化为0,导致结果出现错误,反映了我对于未初始化的数组的掌握并不完全
2.2.题目2:
已知一个带有表头节点的单链表,查找链表中倒数第m个位置上的节点。
输入格式
先输入链表结点个数,再输入链表数据,再输入m表示倒数第m个位置。
输出格式
若能找到则输出相应位置,要是输入无效位置,则输出-1。
2.2.1设计思路
Finding 寻找导数m个数
LinkList p 定义一个结构体指针
定义 i k=0
p=L
while (L!=NULL) 得出整个链表的元素的个数
L=L->next
k++ 用k来计数
if k > m 能找到的情况下
{
for i=0 to k-m 直接找到倒数第m个数
p=p->next
if p不为空
return p->data
else
return -1
}
else
return -1
2.2.2代码截图
2.2.3本题PTA提交列表说明。
- Q1:答案部分正确
- A1:第一步的调整并无加入判断条件,编程时想着能先把大结构写出来再进行调试
- A2:因为第一步没有加入if语句的判断,自然没有else返回值,则答案还是部分正确
- A3:再进行修改,发现是for循环内的结点取值错误,会取到后面一个去了,进行修改至
2.3.题目3:
已知两个递增链表序列L1与L2,2个链表都是带头结点链表。设计函数实现L1,L2的合并,合并的链表仍然递增有序,头结点为L1的头结点。 合并后需要去除重复元素。
输入格式
输入分两行,先输入数据项个数,再输入数据项,数字用空格间隔。
输出格式
在一行中输出合并后新的递增链表,数字间用空格分开,结尾不能有多余空格。
2.3.1设计思路
MergeList 归并函数
{
定义结构体指针 pa=L1->next pb=L2->next r s;
r=L1 r指向L1
while(pa!=NULL&&pb!=NULL) 两个指针指向都不为空的时候
{
if (pa->data==pb->data) 两元素值都相等的时候,进行重复数据的判断
{
if (pa->next!=NULL) 判断哪个不是空的,不空的那个指针就往下移
指针 pa 往下移
else
指针 pb 往下移
}
if (pa->data<pb->data)
{
s申请空间
s->data=pa->data pa赋值给s
r->next=s 和r连接起来
r=s 将指针往下传递
pa指针往下移
}
else
{
s申请空间
s->data=pb->data;
r->next=s 指针间的连接
r=s;
pb指针往下移
}
}
接着扫描剩下的的长度
while(pa!=NULL)
{
s申请空间
s->data=pa->data;
r->next=s;
r=s;
pa指针往下移
}
while(pb!=NULL)
{
s=new LNode;
s->data=pb->data;
r->next=s;
r=s;
pb=pb->next;
}
r的后续置为NULL
}
2.3.2代码截图
2.3.3本题PTA提交列表说明。
-
Q1:编译错误
-
A1:在判断重复数据的时候,把if条件放入判断不重复的数据的分支内
-
Q2:部分正确
-
A2:,当其出现重复数据的时候,若只将pa指针往后移,则会出现空的状况,加入一个else语句使pb也能往后移
3、阅读代码
3.1 题目
一个长度为L(L>=1)的升序序列S,处在第[L/2]个位置的数称为S的中位数。例如,若序列S1=(11,13,15,17,19),则S1的中位数是15。两个序列的中位数是含它们所有元素的升序序列的中位数。例如,若S2=(2,4,6,8,20),则S1和S2的中位数是11。现有两个等长的升序序列A和B,试设计一个在时间和空间两方面都尽可能高效的算法,找出两个序列A和B的中位数。要求:
(1)给出算法的基本设计思想。
(2)根据设计思想,采用C或C++或Java语言描述算法,关键之处给出注释。
(3)说明你所设计计算法的时间复杂度和空间复杂度。
3.2 解题思路
此题思路主要是对于S1和S2两个序列的中位数的比较
(1)如果v1.data[mid1]==v2.data[mid2],则直接返回,它们的中位数相等。
(2)如果v1.data[mid1]<v2.data[mid2],则舍弃S1中比mid还要小的数(因为它们必不可能是中位数)。若序列数元素个数为偶数,则舍弃中位数前的元素;若序列元素个数是奇数,则舍弃包括中位数前的元 素以及中位数。同理,这时也要舍弃S2中较大的一半。
(3)如果v1.data[mid1]>v2.data[mid2],则舍弃S1中比mid大的数,同时也要舍弃S2中较小的一半,若序列元素个数为奇数则舍弃S2中位数的元素,若为偶数则舍弃包括中位数在内的元素。
3.3 代码截图
3.4 学习体会
此题为考研题,这个题目是找两个序列的中位数。可以说,这道题难度大倒是不大,但是算法的效率有大有小;我的第一直觉就是,先将两个序列合并,再用冒泡排序法排序,最后找出中位数。显而易见,这种算法效率不是最高的。而答案中的算法可以说是直接跳过两个序列合并,而且直接将中位数比较后的序列切去一半或者直接输出,大大提高算法效率;可以说,考研题的算法的确有种让人豁然开朗的感觉,一个思路的转变,就能够大大简化代码,只能说,算法之路,路漫漫其修远兮,吾将上下而求索。