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

    0.PTA总分

    • 线性表

    1.本周学习总结

    1.1 总结线性表内容

    顺序表

    • 顺序表结构体定义
      顺序表包括元素跟顺序表的长度,元素用数组存放
    typedef struct 
    {	
        int data[Size];      //存放顺序表元素
        int length ;         //存放顺序表的长度
    } List;	
    typedef List *SqList;    //指针
    
    • 顺序表插入
      由于元素仍用数组储存,所有插入数据时移动数组时必不可免的,但仍需注意的时每次插入完,顺序表长度(lenth)需加1
    for (i = 0; i < L->length; i++)                     //遍历顺序表
    {
        if (L->data[i] >= x)                            //找到要插入的位置
        {
            for (k = L->length; k > i; k--)
            {
                L->data[k] = L->data[k - 1];            //将该位置往后所有元素右移一位
            }
            L->data[i] = x;                             //插入元素
            break;
        }
        else if (x >= L->data[L->length])               //如果在顺序表尾,则直接添加,无需移动
        {
            L->data[L->length] = x;
        }
    }
    L->length += 1;                                     //注意每次插入顺序表长度加1
    
    • 顺序表的删除
      在删除时,其本质跟插入差不了多少,只不过一个右移一个左移,注意顺序表长度减1
    for (i = 0; i < L->length; i++)                     //遍历顺序表
    {
        if (L->data[i] == x)                            //找到要删除的位置
        {
            for (k = i; k <L->length; k++)
            {
                L->data[k] = L->data[k + 1];            //将该位置往后所有元素左移一位,覆盖原位置元素
            }
            L->length -= 1;                             //顺序表长度减1
        }
    }
    

    链表

    • 链表结构体定义
      链表结构体包括所储存的元素以及指向下一结点的指针
    typedef struct LNode  		        //定义单链表结点类型
    {
    	ElemType data;                    
    	struct LNode *next;		//指向后继结点
    } LNode,*LinkList;
    
    • 链表 头插法
      每次插入的数据均在头结点下一位,这样使得输入跟输出的顺序截然相反。
    void CreateListF(LinkList& L, int n)//头插法建链表,L表示带头结点链表,n表示数据元素个数
    {
    	L = new LNode;
    	L->next = NULL;                //开辟头结点
    
    	LinkList head, p, pre;
    
    	head = L;
    
    	int i;
    
    	for (i = 0; i < n; i++)
    	{
    		p = new LNode;
    		cin >> p->data;
    		p->next = head->next;
    		head->next = p;
    	}
    }
    

    • 链表 插入、删除
      链表中插入输出操作相对于数组而言简单不少,无需任何的移动,仅需改变链的关系即可。

      插入

    while (pre->next)                    //由于插入时需要知道插入位置的前驱,所有采用pre—>next为循环变量。
    {
    	if (pre->next->data >= e)
    	{
    		p->next = pre->next;        //改变链的关系
    		pre->next = p;
    		break;
    	}
    	pre = pre->next;
    }
    

    删除

    while (pre->next)                //删除时需要知道删除位置的前驱,采用pre—>next为循环变量。
    {
    	if (pre->next->data == e)
    	{
    	        p = pre->next;        //保留删除节点
    	        pre->next = p->next;    //改变链的关系
    	        free(p);                //释放所要删除节点
                    break;    
    	}
    	pre = pre->next;
    }
    

    有序表

    • 有序单链表数据插入、删除
      其操作的思路及核心代码跟普通链表的插入删除没有区别,只不过需判断特殊情况
      插入
    while (pre->next)
    {
    	if (pre->next->data >= e)
    	{
    		p->next = pre->next;
    		pre->next = p;
    		flag = 0;                //标记状态 说明已经找到位置并完成插入
    		break;
    	}
    	pre = pre->next;
    }
    if (flag == 1)pre->next = p;            //若还没找到插入位置 说明插入位置在链尾,做单独处理
    

    删除

    while (pre->next)
    {
    	if (pre->next->data == e)
    	{
    		p = pre->next;
    		pre->next = p->next;
                    free(p);
    		flag = 0;                //标记状态 说明找到删除位置
                    break;    
    	}
    	head = head->next;
    }
    if (flag == 1)cout << e << "找不到!" << endl;  //若没找到 输出相应提示
    

    • 有序单链表表合并
      同时遍历两链表,并比较数据大小,将较小的采用头插法插入另一条链。
    while (L1->next&&L2->next)
    {
    	if (L1->next->data > L2->next->data)        //当L2数据小于L1时,采用头插法插入
    	{
    		p = new LNode;
    		p->data = L2->next->data;
    		p->next = L1->next;
    		L1->next = p;
    		L2 = L2->next;
    	}
            else if(L1->next->data == L2->next->data)L2 = L2->next;        //如果两数据相等则跳过
    	L1 = L1->next;
    }
    if (L1->next == NULL)L1->next = L2->next;            //当L1遍历完,将L1尾部接上L2剩下的数据。
    

    • 循环单链表
      类似于一个圈,任意一个节点均能访问整条链
    //带头结点为L
    while(pre->next!=L)
    //不带头节点
    while(p!=L)
    
    • 双链表
      即有两个方向的两边,一个节点既有前驱指针,也有后驱指针

    定义

    typedef struct node
    {
        int data;
        struct node* pre;        //指向前一节点的指针
        struct node* next;       //指向后一节点的指针
    }DLNode, *DLinkList;
    
    • 循环双链表
      即在双链表的基础上围成一个圈
      (就不画图了)

    1.2 线性表的认识及学习体会。

    由于线性表内容中大部分知识点在上学期C的学习中已经接触了不少,所以对于线性表的学习即操作中并没有较大的障碍。刚接触时一些较新的知识点,会出现一脸懵的状态,比如头插法,单链表逆置等,还是花了一定的时间去理解消化并准备活用。总而我觉得线性表比较灵活,需要较好的掌握它。


    2.PTA实验作业

    2.1 6-2 jmu-ds-有序表插入数据

    2.1.1 代码截图

    2.1.2本题PTA提交列表说明


    1.部分正确:考虑过于简单,只写了插入数据位于两数之间的代码,情况并没有考虑,导致较多错误。随后补上了插入在头和在尾的代码。
    2.部分正确:忘记考虑表空情况。加上了判空代码,也就相对完整了。
    3.全部正确。


    2.2 6-9 jmu-ds-有序链表合并

    2.2.1 代码截图

    2.2.2本题PTA提交列表说明


    1.部分正确:代码思路有问题,我采用每次判断一对数字,插入玩均往下走。导致会出现输入1 1 ,2 2 输出1 2 1 2的情况。后来更改为一旦L2数据小于L1就采用头插法插入L1。
    2.部分正确:由于细节问题,L2插入完忘记往下走。随后补上代码。
    3.部分正确:没有看清题目具体要求,即:“合并后需要去除重复元素”。加上若两数相等,则L2继续下走。
    4.全部正确。


    2.3 6-10 jmu-ds-有序链表的插入删除

    2.3.1 代码截图

    2.3.2本题PTA提交列表说明


    1.大部分段错误:为了找到错误具体在哪一部分而提交的。
    2.运行超时:同上。
    3.段错误:删除函数中,进行一次删除后我仍使指针后移并且在外层仍有一个指针后移代码,这导致一次移动2个位置,出现段错误。后在插入代码中加入break。
    4.答案错误:修正段错误代码后忘记添上删除部分代码,直接提交导致错误。
    5.部分正确:链表全删时,输出重复。因为链表为空时进不了循环就没注意,然而函数中仍会输出“找不到”。随后加上链表为空直接返回的代码。
    6.全部正确。


    3.1 1.6判断一个单链表中是否有环

    3.1.1 该题的设计思路

    3.1.2 该题的伪代码

    定义两个快,慢指针fast,slow;
    while(fast != NULL && fast->next != NULL)
    {
        slow每次后移一位;
        fast每次后移2位;
        if (fast==slow)//说明两者相遇
        return true;
    }
    end while
    return false;
    //当fast或fast->next移动到NULL时,或链表为空或只有一个元素时。不符合,返回false。
    

    本题时间复杂度O(n);空间复杂度O(1)

    3.1.3 运行结果

    先简单的通过手动改代码实现带环

    3.1.4分析该题目解题优势及难点。

    • 采用快慢指针操作,觉得比较新颖,所以摘抄此题目为例题。其类似借鉴于数学中的追及相遇问题,速度不同两者绕环跑时必然会相遇。借此编写代码十分巧妙
    • 循环条件不能遗漏'fast->next != NULL',否则可能会出现访问非法内存错误。我觉得这是一个注意点。

    3.2 相交链表(LeetCode160题)


    3.2.1 该题的设计思路

    3.2.2 该题的伪代码

    定义两条链L1,L2
    
    while (L1) 
    {
            计算L1长度lenthA;
    }end while
    while (L2) 
    {
    	计算L2长度lenthB;
    }end while
    计算长度差size=fabs(lenthA-lenthB);
    长的链先走size个节点;
    while(L1&&L2)//同时同速遍历两链表
    {
        if 两链中节点相同
            return 相同元素节点
    }end while
    return NULL;
    

    本题时间复杂度O(1)空间复杂度O(n)

    3.2.3 运行结果

    其中我自建一个链表,分别加在L1,L2的尾部使它们有公共节点。输入的为L1,L2,输出为第一个相同节点的数据。

    3.2.4分析该题目解题优势及难点。

    • 先做长度处理,使其类似进行尾部对齐,从较短链开始同时同速遍历,无需嵌套循环。
    • 比较时,注意比较的是节点,而不是数据。这是两个截然不同的东西。
  • 相关阅读:
    单例模式
    Java多线程小例子(三个窗口卖火车票)
    HashMap和HashTable的区别
    javascript操作对象的方法
    javascript基本语法
    其他标签
    头标签
    label标签
    表单标签
    IO流-LineNumberReader
  • 原文地址:https://www.cnblogs.com/gdlkblue/p/12383199.html
Copyright © 2011-2022 走看看