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),用循环链表来做,时间复杂度便降了一个维度,大大提高效率;
    该做法难点就是在找移动的节点时,容易找错;并且我这种做法做完时,是没有头结点的,输出时需要注意下;
    
  • 相关阅读:
    Java 8 Lambda 表达式
    OSGi 系列(十二)之 Http Service
    OSGi 系列(十三)之 Configuration Admin Service
    OSGi 系列(十四)之 Event Admin Service
    OSGi 系列(十六)之 JDBC Service
    OSGi 系列(十)之 Blueprint
    OSGi 系列(七)之服务的监听、跟踪、声明等
    OSGi 系列(六)之服务的使用
    OSGi 系列(三)之 bundle 事件监听
    OSGi 系列(三)之 bundle 详解
  • 原文地址:https://www.cnblogs.com/200157zy/p/12434354.html
Copyright © 2011-2022 走看看