1.本周学习总结
1.1思维导图
1.2.对线性表的认识及学习体会
可能上学期末没有把链表的基础打好吧,这学期学习链表的进一步操作有些吃力,特别是单链表逆转这一类的题目,如果没有看网上的代码,即使知道解题的思路,也不一定能打出来,不过庆幸的时,通过敲pta也对链表的结构有了一点的熟悉,也学到了一些时间复杂度低的一些算法,比如关于一些排序的问题,在上学期,我们学了冒泡排序和选择排序等几种简单的排序方法,但时间复杂度为O(n2),运行起来效率较低,但这学期学的二路归并算法,一边排序一边重构,比起以前学的效率高了不少。
虽然链表有点难,但是顺序表还是比较容易理解的,可能归功于上学期学的数组和结构体比较简单,操作起来比较顺手,而且有些方法是老师在上学期讲过,比如pta中的顺序表删除重复元素这道题,就可以用哈希算法来写,时间复杂度低,效率高。所有以前学的都可以运用到顺序表中,打好基础是关键啊。
2.PTA实验作业
2.1.题目1:6.3 顺序表删除重复元素
2.1.1设计思路(伪代码)
void CreateSqList(List &L,int a[],int n)
{
动态申请内存;
将数组a[n]赋入线性表中;
}
void DelSameNode(List &L)
{
动态申请一个静态数组flag用来记录数据是否重复;
将顺序表中的数据赋入data数组;
//找出数组中相同的两个数数,并把后一个 数所对应的flag标记改为1;
for i=0 to L->length
for j=i+1 to L->length
if data[i]=data[j] then
flag[j]=1;
end for
end for
//重构数组
for i=0 to L->length
if flag[i]==0 then
L->data[k++]=data[i];
end for
L->length=k;
}
void DispSqList(List L)
{
输出链表;
}
2.1.2代码截图
2.1.3本题PTA提交列表说明。
- 在第一次时没有注意到数据长度,两个循环条件都是i小于length,导致顺序表发生越界;
- 修改了循环条件之后,我没有考虑到全部都是重复的数据该怎么删,我只在循环里面记录改减去的数组长度,却没想到如果都是一样的数据,会把顺序表删没掉,后来用了一个k,既能用于重构,也能记录重构完的长度。
- 后来老师又讲了一种做法,哈希算法,时间复杂度只为O(n),比我这种方法好太多了。
2.2.题目2:6.9有序链表合并
2.2.1设计思路(伪代码)
void MergeList(LinkList &L1,LinkList L2)
{
如果L1和L2两条链为空,跳出函数;
定义 节点p1=L1->next,节点p2=L2->next;
定义 节点r=L1;
while p1!=NULL&&p2!=NULL do
//如果p1节点里的数据大于p2节点的数据,同尾插法将p1插入r链中
if p1->data<p2->data then
s->data=p1->data;
r->next=s;
r=s;
p1=p1->next;//指针后移
//如果p2节点里的数据大于p1节点的数据,同尾插法将p2插入r链中
if p1->data>p2->data then
s->data=p2->data;
r->next=s;
r=s;
p2=p2->next;//指针后移
//如果p2节点里的数据等于p1节点的数据,将非空链指针后移
if p1->data=p2->data then
if p1!==NULL then p1=p1->next;
else p2=p2->next;
end while
//如果p1链长于p2链,将p1链多于插入r链中
while p1!=NULL then
s->data=p1->data;
r->next=s;
r=s;
p1=p1->next;//指针后移
end while
//如果p2链长于p1链,将p2链多于插入r链中
while p2!=NULL then
s->data=p2->data;
r->next=s;
r=s;
p2=p2->next;//指针后移
end while
}
2.2.2代码截图
2.2.3本题PTA提交列表说明。
- 前几次都是运行超时,没有考虑到如果两个链表内有相同数据该怎么办,后来使用了很多方法,都没有完全删干净,最后将数据相同的两个节点之一后移就行了;
- 还有一些段错误之类的小错误,都是由于自己的粗心犯下的,后面慢慢调试都出来了。
2.3.题目3:6.7单链表逆置
2.3.1设计思路(伪代码)
void ReverseList(LinkList &L)
{
定义两个节点p和q;
p指向L链的首节点;
把L链的首节点置为空;//在进行下面的循环后,这个节点就变成了尾节点
while p!=NULL then
q=p; //将p节点赋给q节点
p=p->next;//p节点后移
q->next=L->next;
L->next=q; //用头插法将L链转置
end while;
}
2.3.2代码截图
2.3.3本题PTA提交列表说明。
- 没有将L链后的一个节点置为空,导致会无限循环下去;
- 没有将p节点指向L的后继节点,导致答案会发生错误;
3、阅读代码
3.1 题目
单链表实现约瑟夫环(JosephCircle)
约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。通常解决这类问题时我们把编号从0~n-1,最后结果+1即为原问题的解。
3.2 解题思路
我们在环中定义指针cur,每次指针走k次后删除当前指针所指位置的结点,然后继续向后走k次,接着删除当前所指结点,执行循环,直到环中只剩下一个结点(即cur->next == cur),那么最后的这个结点就是我们要找的结点,返回它的地址
3.3 代码截图
3.4 学习体会
- 通过这道单链表的题,我又学习到单链表的一种新的结构--环,环跟循环链表有点类型,可以说环包括了循环链表,题目要求在循环链表内隔几个节点删一个节点,且求出删除后的链表所剩的最后一个节点,如果我来写,我肯定写不出来,给出的解法有点微妙,只向计算机申请了两个的内存空间,空间复杂度较低,且只用了两个循环,时间复杂度也较低。代码也只有寥寥几行,可读性较高,也许是敲了pta吧,感觉自己的代码写得过于冗长,没有网上代码来的简练。