代码改变世界

线性表

2020-03-08 15:07  pluto1214  阅读(239)  评论(0编辑  收藏  举报

0.PTA得分截图

1.本周学习总结

1.1 总结线性表内容

顺序表结构体的定义
typedef struct
{
    ElemType data[max];
    int length;
}SqList;
typedef SqList *List;

顺序表插入
for(j=L->length;j>i;j--)//i为插入位置
   L->data[j]=L->data[j-1];
L->data[i]=e;
L->length++;

顺序表删除
for(j=i;j<L->length-1;j++)i为删除的位置
    L->data[j]=L->data[j+1];
L->length--;
链表结构体定义
typedef struct LNode
{
     ElemType data;//数据域
     struct LNode next;//指针域
}LinkList;
LinkList*List;

头插法建链表
while(i<n)
{
     p=new LinkList;//为节点申请内存空间
     写入数据;
     p->next=L->next;//关键句
     L->next=p;//关键句
     i++;
}

尾插法建链表
for(i=0;i<n;i++)
{
    p=new LinkList;
    cin>>p->data;
    end->next=p;//关键句
    end=p;//关键句
}
end->next=NULL;//关键句

链表的插入
先找插入的位置
while(p&&j<i-1)
{
    j++;
    p=p->next;
}
判断位置是否合法
if(p=NULL)
   return false;
最后进行插入
s=new LinkList;
s->data=e;
s->next=p->next;
p->next=s;

链表的删除
while(p&&j<i-1)
{
     j++;
     p=p->next;//找删除前的位置
}
if(p==NULL)//判断p是否为空
 return false;
q=p->next;
if(q==NULL)//判断q是否为空
 return false;
p->next=q->next;改变指针关系
delete q;
有序表数据插入
for(j=L->length;j>i;j--)//i为插入位置
   L->data[j]=L->data[j-1];
L->data[i]=e;
L->length++;

有序表数据删除
for(j=i;j<L->length-1;j++)i为删除的位置
    L->data[j]=L->data[j+1];
L->length--;

有序表合并
void MergeList(LinkList&L1,LinkList L2)
{
     LinkList end;
     LinkList p,q;

     p=L1->next;
     L1->next=NULL;
     q=L2->next;
     L2->next=NULL;
     end=L1;
    
     while(p&&q)
     { 
         若p->data大于q->data;
         将q插入,并将q指向下一个节点

         若p->data小于q->data;
         将p插入,并将p指向下一个节点
        
         若相等,插入p或q,并将p和q同时移动
     }
    将剩余的元素插入

双链表:有两个指针域,一个指向前*驱节点,一个指向后驱节点

定义:typedef struct DNode
{
ElemType data;
struct DNode *prior;
struct DNode *next;
}DLinkList;
特点:可以快速找到除头节点和尾节点的前一个和后一个节点

循环链表:将表的尾节点的指针域改为指向头节点

特点:从循环链表中的任一节点的位置都可以找到其他节点,循环条件为p->next!=L

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

1.线性表的内容多,而且比较杂,有些部分抽象难以理解,
一开始学习很难懂,许多知识都想不明白,理解也有点难
但通过编程练习之后会好很多,通过PTA的练习可以帮助自
己更好的学好线性表。
2.对链表的内容掌握得不是很好,碰到新的题目和填空题会比较难受。
3.做链表的题目虽然过程痛苦,但是自己做出来之后又会有比较大的成就感。

2.PTA实验作业

2.1.题目1:6-3 jmu-ds-链表区间删除

2.1.1代码截图



2.1.2本题PTA提交列表说明。

A1:用尾插法建链表,没看清题目,导致建链表错误
A2:原先插入建链表时用pre指针表示当前位置p的end的前一个,每次插入时与前一个进行比较,例如
题目1,2,9,4,8插入2时与1比较,插入9时与2比较...虽然结果正确1,2,4,8,9.删除后为1,8,9
但是提交始终不过,经调试和思考后发现错误,每次插入应与所有数字都进行比较。
Q2:while (pre2->next && pre2->next->data < p->data)
				{
					pre2 = pre2->next;
				}
				p->next = pre2->next;
				pre2->next = p;
				pre2 = L;
让pre2指针每次遍历插入后重新指向L;
A3:删除时只考虑到了在区间范围的元素,没理不在区间范围内的
Q3:q = p;
        p = p->next;
不在区间范围内的用以上代码保存

2.2.题目2:顺序表删除重复元素

2.2.1代码截图



2.2.2本题PTA提交列表说明。

![](https://img2020.cnblogs.com/blog/1775776/202003/1775776-20200306191539875-340961912.png)
A1:删除之后没有将顺序表的长度减一,造成输出时错误
Q1:每次删除后;L->length--;
A2:当元素全为重复元素且原顺序表元素个数大于2时,会漏删一个,原因是L->length删除后减1,但循环条件也会减1,
所以导致最后一个重复元素无法删除,实际上经过调试发现总有一些情况会漏删,比如1,2,1,1,3,由于删除后为1,2,1,3
此时j=2,但删除后j++使j变为3,L->data[j]也就变为3,会漏删1.
Q2:删除结束后,若L->data[0]=L->data[1],则L->length--;

2.3.题目3:两个有序链表的交集

2.3.1代码截图




2.3.2本题PTA提交列表说明。

A1:尾插法建链时忘记最后end->next=NULL
A2:循环条件漏了,把-1也算到交集了
Q2:循环条件有while(p1&&p2)改为
while(p1&&p1->data!=-1&&p2&&p2->data!=-1)
A3:用两层循环比较,用第一条链的每个数跟第二条链的每个数比较,相等的插入,这样在数据大的时候会超时
Q3:考虑到可以用类似于归并的方法,降低比较次数
if(p1->data>p2->data)
   移动p2;
if(p1->data<p2->data)
   移动p1;
else
   用尾插法插入
这样大大节省了时间,最后提交成功

3.阅读代码

3.1 题目及解题代码

题目:求链表的中间节点
关键代码如下

3.1.1 该题的设计思路

3.1.2 该题的伪代码

int mian()
{
List L,middle;
调用建链函数建链表;
middle=middleNode(head);//该函数用于求链表的中间节点值;
cout<data输出中间节点的值;
return 0;
}
ListNode* middleNode(ListNode* head)
{
慢指针slow=head;
快指针fast = head;
while (fast != NULL && fast->next != NULL)
{
快指针走两步;慢指针走一步;
}
return slow;
}

3.1.3 运行结果

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

优势:巧妙的运用了快慢指针,利用题目中若中间节点有两个则第二个为中间节点,用头插法和快慢指针则可以避免对链长度奇偶的讨论
难点:如何高效准确找出中间节点,若用一般方法根据链的长度来求中间节点麻烦

3.2 题目及解题代码

**题目:请在顺序表上实现运算,实现顺序表的逆置,删除表中所有元素值等于x的元素。

3.2.1 该题的设计思路

3.2.2 该题的伪代码

while(i<n)
{
头插法建链表;
输入要删除的数据;
遍历链表;
输出删除后的链表;
}

3.2.3 运行结果

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

优势:一开始我看到题目是想建多条链表来存放不同类型的数据元素,但该解法在结构体内定义了string s;来存放不同的数据元素,
string s;这样便可存放小数的元素。
难点:在于小数的链表该如何处理,不能用char而要用string