zoukankan      html  css  js  c++  java
  • DS博客作业02--线性表

    1.本周学习总结

    1.1思维导图

    1.2谈谈你对线性表的认识和学习体会

    学线性表这一章的时候,我感觉吧就像是在学加上了结构体可以变化长度的数组和链表 。感觉就是应该和上学期的数组和链表差不多,结果做起PTA的时候,一堆堆的错误。然后上级考的时候,一遍遍的段错误到绝望……然后就感觉自己跟上学期比起来松懈了不少,最基本的代码问题又开始
    

    2.PTA实验作业

    2.1题目1:6-3 jmu-ds- 顺序表删除重复元素

    设计一个算法,从顺序表中删除重复的元素,并使剩余元素间的相对次序保存不变。
     - 输入格式: 第一行输入顺序表长度。 第二行输入顺序表数据元素。中间空格隔开。
     - 输出格式:数据之间空格隔开,最后一项尾部不带空格。
     - 输出删除重复元素后的顺序表。
    

    2.1.1设计思路(伪代码)

    因为顺序表中的数均为正数,构造一个哈希数组赋初值为0,遍历顺序表,将L->data[i]的值作为哈希数组的下标统计顺序表中各个数出现的次数,将哈希数组值为一的数存入重构顺序表中。
    
    • 伪代码
    定义整型变量i、j=0,i为原顺序表的下标,j为重构顺序表的下标
    定义整型哈希数组hash[100],并赋初值为0
    遍历顺序表
        将L->data[i]作为哈希数组的下标,统计其出现的次数
        if L->data[i]出现的次数为一次 then
            将L->data[i]的值赋给L->data[j++]  //重构顺序表
    将j的值作为顺序表长度赋给L->length
    

    2.1.2代码截图

    • void CreateSqList(List &L,int a[],int n); //创建顺序表

    • void DispSqList(List L);//输出顺序表

    • void DelSameNode(List &L) ;//删除顺序表重复元素

    2.1.3本题PTA提交列表说明

    Q1:一开始部分正确是因为忽略了空表及全部删除后的输出,然后又认真的看了一下题目,在输出的函数部分用if语句分出空顺序表的情况;
    Q2:后来两个间隔长时间的答案正确的提交改进了算法,将时间复杂度为O(n3)改进成了O(n);
    A2:一开始做这道题的时候用的是笨办法,用两层for循环查找重复元素,找到后再来一层循环将顺序表往前挪,虽然做法简单易懂,但是时间复杂度特别高,当时抱着做出结果就好的心态,做完就没去管它了。隔了两周多吧,老师上课提到这道题,经过这两周的学习,我又想到了只用两层循环的重构做法,然后老师说可以用哈希数组来做,只要一层循环就能搞定,当时在课上我就自己试着做了一遍。
    

    2.2题目2:6-8 jmu-ds-链表倒数第m个数

    已知一个带有表头节点的单链表,查找链表中倒数第m个位置上的节点。
     - 输入要求:先输入链表结点个数,再输入链表数据,再输入m表示倒数第m个位置。
     - 输出要求,若能找到则输出相应位置,要是输入无效位置,则输出-1。
    

    2.2.1设计思路(伪代码)

    利用两个LinkList型指针p,ptr,将p移到第m个位置,让ptr从指向头结点的位置与p同时往下指,当p指向尾结点时,ptr的位置即为倒数第m个数的位置。
    
    • 伪代码
    定义LinkList型指针p,ptr,两个指针均指向头结点,ptr表示指向倒数第m个位置的指针
    if 头结点为空 或者 m取小等于0的无效位置 then
        返回 -1
    while 指针p不为空 且 m的值不为0 do
        指针p往下移
    if m的值大于0 then //即L的长度小于m 
        返回 -1
    else
        while 指针p不为空 do
            指针p与指针ptr同时向下移动
        返回 ptr->data的值
    end if
    

    2.2.2代码截图

    2.2.3本题PTA提交列表说明

    Q1:当时做的时候,是在帮同学改过这题代码的情况下做的,所以无效位置条件的测试点都过了,但是我没想到的是有效位置上出了错
    A1:我当时看了一遍又一遍,觉得自己的代码没什么毛病啊,(当时因为题目的各种函数细节不表,懒得自己打出来去dev调试),后面又静下心来慢慢看那,发现我else里头while语句的条件写错了,写成了p->next,这样一来ptr所指向的位置就变成了倒数第m+1个
    Q2:当时做这道题的时候不仅是在帮同学改完代码的基础上,更是在老师上课讲完了相关例题之后写的,总觉得没有了自己的思考,下回PTA的作业还是不要拖着了(哭唧唧)
    

    2.3题目3:6-10 jmu-ds-有序链表的插入删除

    链表L是一个有序的带头结点链表,实现有序链表插入删除操作。
    

    2.3.1设计思路(伪代码)

    插入函数:找到比输入数据大的结点,将数据插入该结点的前面
    删除函数:找到所输入的数据,并将该结点释放删除,若找不到则输出X找不到!
    
    • 伪代码
    插入函数:
        定义LinkList型的变量p、ptr,为p申请空间,将e赋值给p->data,令ptr等于L
        while ptr->next不为空 then  //保存前驱结点,方便插入操作
            if ptr->next->data的值大于e then
                将指针p插入在ptr指针后
                返回空值
            end if
            ptr指针往后移
        end while
        将指针p插入在ptr指针后
    
    删除函数:
        定义LinkList类型的指针 ptr、q,令ptr等于L保存前结点
        if 头结点为空 then
            return
        while ptr->next 不为空 do
            if ptr->next->data的值与e相等 then
                利用指针q删除该结点,释放q
                return
            end if
        ptr指针往后移
        end while
        输出X找不到!  //当输入数据找不到时才会执行该语句
    

    2.3.2代码截图

    • void ListInsert(LinkList &L,ElemType e);//有序链表插入元素e

    • void ListDelete(LinkList &L,ElemType e);//链表删除元素e

    2.3.3本题PTA提交列表说明

    Q1:这题做完后再看,真的是超简单,但是吧当时不知道在想什么,信心满满的做完,结果编译错误……看了眼PTA的错误提醒,好吧,把指针跟数据进行比较,我也是没谁了
    Q2:改完想着好了这题做完了,结果来了个运行超时……(吐血)
    A2:检查了两遍,没毛病啊,再提交一下,运行超时……然后问了下同学,一语惊醒梦中人:你指针都没移动。好的吧我的错,继续改。
    Q3:改完以后想着这回总该对了吧,结果如上图所见,答案错误
    A3:如同上一题一样的原因,没用dev调试,看了n边的代码,始终找不出错误,最后认命的手动补充细节不表的函数,过程中又出现了问题,因为建链的时候忘记让尾结点等于NULL,结果输出的时候陷入了死循环。改完后,在调试过程中发现插入函数在尾部插入的情况不能实现,再瞅了眼代码,好吧,还真没考虑到在末尾插入的情况,终于,答案正确了。
     - 写这题呢不是因为难,不会做,而是发现自己又开始犯起了基本的错误,指针跟数据都能比较起来,不知道为啥做这道题的时候,逻辑思维乱乱的,各种出错。当然还有,不要因为题目给的代码细节不表懒得自己写,就不去用dev调试,你以为不表的函数你都会,但是可能也会有不懂的地方。
    

    3.阅读代码

    3.1题目:链表的中间结点

    给定一个带有头结点 head 的非空单链表,返回链表的中间结点。
    如果有两个中间结点,则返回第二个中间结点。
    
    • 示例1:
    输入:[1,2,3,4,5]
    输出:此列表中的结点 3 (序列化形式:[3,4,5])
    返回的结点值为 3 。 (测评系统对该结点序列化表述是 [3,4,5])。
    注意,我们返回了一个 ListNode 类型的对象 ans,这样:
    ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, 以及 ans.next.next.next = NULL.
    
    • 示例2:
    输入:[1,2,3,4,5,6]
    输出:此列表中的结点 4 (序列化形式:[4,5,6])
    由于该列表有两个中间结点,值分别为 3 和 4,我们返回第二个结点。
    

    提示: 给定链表的结点数介于 1 和 100 之间。

    3.2解题思路

    解法一:输出到数组

    • 解题思路
    按顺序将每个结点放入数组 A 中。然后中间结点就是 A[A.Length/2],因为我们可以通过索引检索每个结点。
    时间复杂度:O(N),其中 N 是给定列表中的结点数目。
    空间复杂度:O(N),A 用去的空间
    
    • 伪代码
    1.定义一个数组A
    2.利用while遍历链表并将链表赋值给数组
    3.返回数组A[n/2]的值
    

    解法二:快慢指针法

    • 解题思路
    当用慢指针 slow 遍历列表时,让另一个指针 fast 的速度是它的两倍。当 fast 到达列表的末尾时,slow 必然位于中间。
    时间复杂度:O(N),其中 N 是给定列表的结点数目
    空间复杂度:O(1),slow 和 fast 用去的空间。
    
    • 伪代码
    定义两个ListNode类型的指针变量slow、fast,且两个指针变量均指向head
    while fast指针不为空 且 fast->next指针不为空 do
       slow指针往下移一位
       fast指针往下移两位
    end while
    返回slow指针的值
    

    3.3代码截图

    • 解法一
    • 解法二

    3.4学习体会

    这道题其实超级简单,选择这道题的原因是这套题配的解题思路。
    看到这道题的时候,我的想法就是:遍历一边链表,然后记下链表的长度,再用一个循环来使指针指向中间的位置。虽然跟上述两种做法的时间复杂度一样,都是O(n),但是,却用了两次循环,而且感觉自己的做法特别的笨。然后看到解法一的解题思路时,我在想为什么还要用数组,跟我的想法不是差不多,却还要在定义新的临时变量,结果看完代码…好吧,是我的思路不对,存进数组后直接输出就好了,根本不用再次遍历。然后看到解法二的时候,心里的想法:真的是妙啊,连新的临时变量都用不上了,然后就想到了链表倒数第k个数的那道题,有异曲同工之妙。
    所以记下这道题,一是给自己一个新的逻辑思维跟解题思路,更是提醒自己举一反三,不要新的思路解法学了,却运用不到其他类似的题目上。
    
  • 相关阅读:
    prepareStatement的用法和解释
    java socket报文通信(一) socket的建立
    java多线程小结
    Java_XML操作
    socket实例2
    socket实例1
    Socket小结
    从源码角度理解android动画Interpolator类的使用
    android使用属性动画代替补间动画
    OKHttp的简单使用
  • 原文地址:https://www.cnblogs.com/Lay-549/p/10629623.html
Copyright © 2011-2022 走看看