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

    0. PTA得分截图

    1. 本周学习总结

    1.1总结线性表内容

    1.1.1顺序表结构体定义、顺序表插入、删除的代码操作

    顺序表结构定义

    typedef struct List{
         int data[MAX];//保存线性表元素
         int Length;//保存线性表长度
    }List,*SqList;
    

    顺序表插入

    for (i = L->length - 1; i >= 0; i--)//从后面开始找插入位置,不满足元素则往后移,满足则插入
    {
    	if (x > L->data[i])
    	{
    		L->data[i + 1] = x;
    		L->length++;
    		return;
    	}
    	else
    	{
    		L->data[i + 1] = L->data[i];
    	}
    	if (i == 0)
    	{
    		L->data[i] = x;
    		L->length++;
    		return;
    	}
    }
    

    顺序表删除元素操作

    int i,j,k;
    k = 0;
    j = L->length;
    L->length = 0;//重构顺序表
    for (i = 0; i < j; i++)
    {
    	if (!(L->data[i]>=min && L->data[i]<=max))//不在删除区间内的,写入重构顺序表
    	{
    		L->data[k++] = L->data[i];
    		L->length++;
    	}
    }
    

    顺序表删除重复元素,并且顺序不变

    //一般都是用选择排序或冒泡排序来做,但学了数据结构,就要追求更高效的算法,降低时间复杂度
    int i, j,len;
    i = 0; j = 0;
    static int hash[maxsize];//新建一个哈希数组,牺牲空间来换取时间
    len = L->length;
    L->length = 0;
    for (i = 0; i < len; i++)
    {
    	hash[L->data[i]]++;
    	if (hash[L->data[i]] == 1)
    	{
    	        L->data[j++] = L->data[i];
    		L->length++;
    	}
    }
    

    1.1.2 链表结构体定义、头插法、尾插法、链表插入、删除操作

    链表结构定义

    typedef struct LNode  		//定义单链表结点类型
    {
    	ElemType data;
    	struct LNode *next;		//指向后继结点
    } LNode,*LinkList;
    

    头插法代码

    void CreateListF(LinkList& L, int n)//头插法建链表,L表示带头结点链表,n表示数据元素个数
    {
    	int i;
    	LinkList tempptr;
    	L = new LNode;
    	L->next = NULL;
    	for (i = 0; i < n; i++)
    	{
    		tempptr = new LNode;
    		cin >> tempptr->data;
    		tempptr->next = L->next;
    		L->next = tempptr;
    	}
    }//顺序与输入数据顺序相反,无需尾指针
    

    尾插法

    void CreateListR(LinkList& L, int n)//尾插法建链表,L表示带头结点链表,n表示数据元素个数
    {
    	LinkList tailptr,tempptr;
    	L = new LNode;
    	L->next = NULL;
    	tailptr = L;
    	int i;
    	for (i = 0; i < n; i++)
    	{
    		tempptr = new LNode;
    		cin >> tempptr->data;
    		tailptr->next = tempptr;
    		tailptr = tempptr;
    	}
    	tailptr->next = NULL;
    }//需要尾指针,输入顺序与输出顺序相同
    

    链表插入数据代码

    {
        s=new LNode;
        s->data=e;//插入节点
        s->next=p->next;
        p->next=s;
    }
    

    链表删除数据

    {
         q=p->next;//保存删除节点
         p->next=q->next;//将节点连向下一个节点
         delete q;//销毁删除节点
    }
    

    1.1.3 有序表,尤其有序单链表数据插入、删除,有序表合并

    有序单链表数据插入

    void ListInsert(LinkList& L, ElemType e)//有序链表插入元素e
    {
    	LinkList nodePtr,tailPtr;
    	tailPtr = new LNode;
    	tailPtr->data = e;
    	tailPtr->next = NULL;
    	nodePtr = L;
    	while (nodePtr->next&&nodePtr->next->data<e)  //找到插入的位置
    	{
    		nodePtr = nodePtr->next;
    	}
    	tailPtr->next = nodePtr->next;
    	nodePtr->next = tailPtr;
    }
    

    有序单链表数据删除

    void ListDelete(LinkList& L, ElemType e)//链表删除元素e
    {
    	LinkList DeletePtr,p;
    	DeletePtr = L;
    	while (DeletePtr->next)
    	{
    		if (DeletePtr->next->data == e)//找到删除节点,销毁节点
    		{
    			p = DeletePtr->next;
    			DeletePtr->next = DeletePtr->next->next;
    			delete p;
    			return;
    		}
    		DeletePtr = DeletePtr->next;
    	}
    	if (L->next==NULL) return;
    	cout << e << "找不到!"<<endl;
    }
    

    有序表合并

    void MergeList(LinkList& L1, LinkList L2)//合并链表
    {
         while 遍历两个链表,直到一个为空
    		if (tempLink->data > L2->data)
    		{
                            尾插法将该节点写入新链表;
    			L2 = L2->next;
    		}
    		else if (tempLink->data < L2->data)
    		{
                            尾插法将该节点写入新链表;
    			tempLink = tempLink->next;
    		}
    		else if (tempLink->data == L2->data)
    		{
    			tailptr->next = L2;
    			tailptr = L2;
    			L2 = L2->next;
    			tempLink = tempLink->next;
    		}
    	if 判断链表tempptr是否为空,不为则将剩下写入新链表
    	if 判断链表tL2是否为空,不为则将剩下写入新链表
    	tailptr->next = NULL;
    }
    

    1.1.4 循环链表、双链表结构特点

    循环链表:将表中尾节点的指针域改为指向表头节点,整个链表形成一个环。由此从表中任意节点出发,都可以找到其他节点

    双链表:每个节点中有两个指针域,一个指向后继节点,一个指向前驱结点。从任意节点出发都可以快速找到其前驱和后继
    其结构示意图如下:

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

    经过一两周的学习,从刚开始对创建链表都很费劲的我,现在对链表基本操作都可以掌握了,最主要还是要画图来看,会更加清晰。
    
    在看到第一章时,各种时间复杂度的差异,纵使在小数据量时差距不大,但在大数据量的作用下,都会使得差距很大。
    
    而在以后的工作中,面临的肯定都是大数据,所以关注其时间成本才是重中之重。以及在做PTA时,我会经常考虑它的时间复杂度,看有没有更节约时间的做法,学这本书,我觉得更重要的是学习它的算法,如何更快的节省时间,降低时间复杂度。
    
    在做PTA时,经常会遇到在保存节点后,容易把节点后的给丢失掉。后面再进行保存节点时,我得及时把节点给移到下一个节点处,这样才不会让它丢失,也可以将该节点的数据保存下来,这样也是可以的。
    
    还有就是以往有一个习惯就是不喜欢画图来做链表,经常导致链表关系丢失,画图之后,确实感觉链表关系明确了好多,丢失这种错误也很少再犯。
    

    2. PTA实验作业

    2.1 题目1: jmu-ds-链表倒数第m个数

    2.1.1 代码截图

    2.1.2 本题PTA提交列表说明

    第一次是用遍历一次链表,再重新找他的倒数第m个数的做法
    多种错误:①第二次找他的倒数m个数据时,L没有循环到下一个节点②j=n-m+1,第一次没有加一,导致读出的数据往前了一位,修改后便正确
    
    第二次用老师上课讲的做法,节约了更多时间。即新建两个指针,第一个指向正数第m个节点,第二次两个指针一起往前走,直到第一个指针结束。也是相当于做了减法,但巧妙地节约了时间
    部分正确:没有考虑无效位置的情况下,就是在输入0或者负数时的情况。在前面加上一个判断m的情况就可以了
    

    2.2 题目2: jmu-ds-有序链表合并 (20分)

    2.2.1代码截图

    2.2.2 本题PTA提交列表说明

    答案错误:考虑的是两个链表一样长时的情况,没有考虑一条走完,另一条还有的情况。解决:在后面判断两个链表是否已经到了尾部,没到则将剩下的接到新链表上;
    部分正确:第二次错误则是看错题意,题目写的是“合并后需要去除重复元素”,我理解的就是要去除重复的元素,自然就错了。后面将重复元素写一个进去就好啦,
    

    2.3 题目三:7-1 两个有序序列的中位数 (25分)

    2.3.1 代码截图

    2.3.2本题PTA提交列表说明

    在做本题时,一开始想到的是将两个链表合并在一起后,找出它的中位数。在课上老师的讲解后,有了这种做法,时间比以前节省了不少,也节省了空间
    编译错误则是PTA不能用void main导致的
    

    3.阅读代码

    3.1题目及解题代码

    链表的中间节点(leetcode 876)

    3.1.1 该题的设计思路

    时间复杂度:O(n)
    空间复杂度:O(1)
    

    3.1.2 该题的伪代码

    新建快指针fast;
    新建慢指针slow;
    while 判断快指针及快指针的下一节点是否为空   //快指针为空,慢指针则指到中间位置
           慢指针指向下一节点;
           快指针是慢指针速度的两倍;
    return 慢指针
    

    3.1.3运行结果

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

    本来的这题我以为是跟pta上找倒数第几个数的做法类似的,但却不能用一个指针先去移,因为并不知道它的中间节点在哪。
    按平常做法来的话,也可以先遍历一遍,再找出它的中间节点,但时间明显比这种做法多了一些。
    这种快慢指针的做法,只需要遍历一遍,就可以找出它的中间节点。以后再遇到这种找他的哪个位置节点呀,这种方法倒简便了不少
    

    3.1题目及解题代码

    题目:

    解题代码:

    3.1.1 该题的设计思路

    时间复杂度:O(N)
    空间复杂度:O(1)
    

    3.1.2 该题的伪代码

    void CirculationList(LinkList& L, int  m)
    {
          保存开头节点;
          while遍历L到尾部
               n++;   //保存节点个数
          L->next=head;   //将链表首尾相连,循环链表
          for 找到移动的位置
          L = head->next;
          head->next = NULL;//将链表断开
    }
    

    3.1.3运行结果

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

    上面这种做法就是以往拿数组的方法来做的,时间复杂度为O(n2),用循环链表来做,时间复杂度便降了一个维度,大大提高效率;
    该做法难点就是在找移动的节点时,容易找错;并且我这种做法做完时,是没有头结点的,输出时需要注意下;
    
  • 相关阅读:
    <NET CLR via c# 第4版>笔记 第18章 定制特性
    <NET CLR via c# 第4版>笔记 第17章 委托
    <NET CLR via c# 第4版>笔记 第16章 数组
    <NET CLR via c# 第4版>笔记 第15章 枚举类型和位标志
    <NET CLR via c# 第4版> 读书笔记--目录
    <NET CLR via c# 第4版>笔记 第14章 字符,字符串和文本处理
    <NET CLR via c# 第4版>笔记 第13章 接口
    <NET CLR via c# 第4版>笔记 第12章 泛型
    python 之实例属性和类属性
    python 之获取对象信息
  • 原文地址:https://www.cnblogs.com/200157zy/p/12434354.html
Copyright © 2011-2022 走看看