线性表
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<
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