DS博客作业02--线性表
1.本周学习总结
1.1思维导图
1.2.谈谈你对线性表的认识及学习体会。
(1) 首先链表我上学期已有一定的基础,所以学起来没有太大的困难,但是解决问题时不够老道,
没有写出的代码时间复杂度不是太好,和老师举例的算法有明显差距,这方面还需多积累。
(2) 其次链表操作会涉及到指针,指针的用法又可以相当巧妙,让本来复杂的问题变简单,
但是用不好可能会留下各种小bug,难以查找,甚至崩溃。所以要多多领悟总结。
2.PTA实验作业
2.1.题目1:6-2 jmu-ds-有序表插入数据
实现在顺序表中删除某个区间数据。需要实现下述的三个函数完成该功能。
实现函数:
CreateSqList:创建有序表,连续输入n个正数存入有序表中。L表示顺序表指针,n表示输入数据个数。
InsertSq(SqList *&L,int x):顺序表L中插入数据x。
DispSqList:输出顺序表L中所有数据。数据间空格隔开,尾部不能有空格。
2.1.1设计思路
- void CreateSqList(SqList &L, int n)创建有序表
用new分配内存给L
L->length赋值为n,n为输入数据长度
if (n小于等于最大值50) then
{
输出“大于数组长度”
}
end if
if (n等于0) then
{
输出 "error"
并且退出
}
else if (n大于0) then
{
for (i 从0开始循环到 L->length-1)
{
输入数据到 L->data[i]中
}
}
else 如果n<0为不合法
{
输出 "小于0 error"
}
end if
- void InsertSq(SqList &L, int x)顺序表L中插入数据x
遍历找到插入点然后后面元素后移
定义变量flag记录插入位置
for (i 从 1 循环到 L->length=1 )
{
if (L->data[0] 大于 x) then //插入头
{
把标记flag = 0意为插入头
退出循环
}
else if ( L->data[L->length - 1] 小于 x) 说明要插入尾
{
把标记flag = L->length - 1意为插入尾
退出循环
}
else if L->data[i] 大于x并且L->data[i - 1] 小于x then
{
找到中间插入点赋给flag
flag = i
}
end if
}
end for
if (flag 等于 L->length - 1) then
{
L->data[L->length] = x //在尾部插入x
}
else
{
for (i = L->length to flag)
{
L->data[i] = L->data[i - 1] //后移
}
end for
L->data[flag] = x //插入x
}
end if
长度L->length加1
- void DispSqList(SqList L)输出顺序表L中所有数据。数据间空格隔开,尾部不能有空格
for (从i = 0 循环到 L->length)
{
输出 L->data[i]
if i 小于 L->length - 1 then //结尾无空格
{
输出空格
}
}
2.1.2代码截图
2.1.3本题PTA提交列表说明
- Q1:代码考虑不周全,插入结尾时会插入到前一个
- A1;对插入结尾单独判断
2.2.题目2:6-4 顺序表操作集
本题要求实现顺序表的操作集。
2.1.1设计思路(伪代码)
(1) List MakeEmpty():创建并返回一个空的线性表;
List MakeEmpty()
{
声明结构体指针q,用malloc分配内存;
给q->Last 赋值为 -1表示为空
返回 q;
}
(2) Position Find( List L, ElementType X ):返回线性表中X的位置。若找不到则返回ERROR;
for循环遍历顺序表查找X的位置,找不到返回ERROR
Position Find(List L, ElementType X)
{
for (从0开始循环到顺序表最后L->Last)
{
if (如果L->Data[i] 等于 X)
{
返回位置i;
}
}
如果找不到返回 ERROR;
}
(3)bool Insert( List L, ElementType X, Position P ):将X插入在位置P并返回true。若空间已满,则打印“FULL”并返回false;如果参数P指向非法位置,则打印“ILLEGAL POSITION”并返回false;
先判断是否合法,然后for循环查找插入位置,然后把插入位置之后的元素后移,把元素插入
bool Insert(List L, ElementType X, Position P)
{
if (如果最后元素位置L->Last 等于最大位置MAXSIZE-1)
{
输出( "FULL")
返回 false
}
if (如果P小于0或者大于最后元素位置)
{
输出( "ILLEGAL POSITION");
返回 false;
}
if (如果P 小于等于 元素最后位置L->Last)需要移动元素
{
for (i从最后位置L->next+1的位置循环到p)
{
L->Data中的i-1位置的元素移到i位置
}
通过循环后移结束后把L->Data[P]赋值为X
L->Last最后元素位置加一
}
else 不需要移动
{
通过循环后移结束后把L->Data[P]赋值为X
L->Last最后元素位置加一
}
返回true
}
(4) bool Delete( List L, Position P ):将位置P的元素删除并返回true。若参数P指向非法位置,则打印“POSITION P EMPTY”(其中P是参数值)并返回false。
bool Delete(List L, Position P)
{
if (如果p不合法)
{
输出("POSITION %d EMPTY",P);
返回 false;
}
for (从头遍历一遍顺序表)
{
if (如果目标P 不等于当前i)
{
就把L->Data[j++]赋值为L->Data[i]重构顺序表
}
}
最后顺序表的最后元素位置L->Last减一
返回 true
}
2.1.2代码截图
2.1.3本题PTA提交列表说明
Q1:使用了new,但是题目是gcc编译
Q2:在尾部删除时没有考虑到
Q3:输出不对等小问题
2.3.题目3:7-2 一元多项式的乘法与加法运算
设计函数分别求两个一元多项式的乘积与和。
2.3.1设计思路(伪代码)
结构体定义
typedef struct equation
{
定义int类型系数 number;
定义int类型次方 power;
定义equation* 指针next;
}EQU;//equation方程
(1) 建链表(比较简单不详细介绍)
void CreateList(EQU *&head,int &count)
{
用new分配内存
用for循环不断输入
尾插法建链表
}
(2) 多项式加法
在循环中相同次方的系数相加或者不相等就把大的赋值到addresult中,直到两个链表遍历完毕
void EquationAdd(EQU* const &head1, EQU* const &head2,EQU* &addresult)
{
用new分配内存,具体细节不表
声明EQU指针q1来代替head1, q2来代替head2,temp为临时,p来代替addresult
for (如果q1或q2不为空)
{
用new为temp分配内存
if (如果q1和q2都不为空)
{
if (如果q1->power 等于 q2->power)就合并
{
把temp->power 赋值为q1->power
把temp->number 赋值为 q1->number + q2->number
q1和q2都等于下一个节点
}
else把次方大的接到结果链表
{
然后该链表指针后移一个节点
}
}
else if(q1遍历结束)
{
就把q2的赋给temp
}
else q2遍历结束
{
就把q1的赋给temp
}
每次循环结束前把temp接到结果链表
}
p->next = NULL
}
(3) 多项式乘法
用两个嵌套for把两个链表相乘,结果保存在temp,然后调用插入函数
void EquationMultiply(EQU *const &head1, EQU *const &head2, EQU *&Multiplyresult)
{
用new分配内存,具体细节不表
声明EQU指针temp作为临时指针, p指针来代替Multiplyresult
声明EQU指针q1来代替head1,q2来代替head2
if (q1或者q2为空)
{
结束函数
}
for (如果q1遍历还没结束)
{
for (从q2头循环到q2尾)
{
把q1和q2相乘的结果保存到temp
调用插入函数InterList(Multiplyresult, temp)
}
}
}
(4) 插入函数
结果链表是按次方从大到小排序,用for循环找到插入点插入,有次方等于的就合并
void InterList(EQU *&head,EQU *&temp)
{
声明EQU指针q和p来代替被插入链表,p指在q的前一个节点
for (通过q遍历链表即q不为空继续循环)
{
如果有次方相等就合并,没有就插入
}
}
(5)输出函数
遍历链表输出,链表为空等输出相应提示(相对简单,不详述)
2.3.2代码截图
2.3.3本题PTA提交列表说明。
Q1:一开始没有合并同类项
Q2:没有去除零项
Q3:一开始没有用插入函数,导致代码复杂,小问题多,就写了插入函数
3、阅读代码
3.1题目
给定一个链表,判断链表中是否有环。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
3.2解题思路
通过使用具有 不同速度 的快、慢两个指针遍历链表,慢指针每次移动一步,而快指针每次移动两步 ,如果列表中不存在环,最终快指针将会最先到达尾部,此时我们可以返回 false,如果有环快指针就一定会追上慢指针。
3.3代码截图
3.3学习体会
算法经典,时间复杂度o(n),空间复杂度o(1),我发现很多经典算法都是利用了两个或多个指针对链表操作,取得了可观的时间复杂度。