DS博客作业02--线性表
0.PTA得分截图
1.本周学习总结
1.1 总结线性表内容
- 顺序表结构体定义:把线性表中的所有元素按照顺序存储方法进行存储的结构为顺序表,即物理地址相邻
- 顺序表结构体定义代码:
typedef int ElemType;
typedef struct
{
ElemType data[MaxSize]; //存放顺序表元素
int length ; //存放顺序表的长度
} List;
typedef List *SqList;
- 顺序表插入:顺序表插入可选择指定位置插入或根据大小插入,若按大小插入且该顺序表为递增排序则可使用以下代码
- 顺序表插入代码:
for (i = 0; i < L->length ; i++)
{
if (L->data[i]>x)
{
for (j = L->length; j > i; j--)
{
L->data[j] = L->data[j - 1];
}
L->data[i] = x;
L->length++;
break;
}
}
- 顺序表删除:顺序表删除可选择删除某范围内元素或删除某位置上的元素,其中删除某范围内元素可使用以下代码
- 顺序表删除代码:
for (i = 0; i < L->length-1; i++)
{
if (L->data[i] >= min && L->data[i] <= max)
{
for (j = i; j < L->length-1; j++)
{
L->data[j] = L->data[j + 1];
}
L->length--;
i--;
}
}
- 链表结构体定义:链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
- 链表结构体定义代码:
typedef struct LNode //定义单链表结点类型
{
ElemType data;
struct LNode *next; //指向后继结点
} LNode,*LinkList;
- 头插法代码:
for (i = 0; i < n; i++)
{
q = new LNode;
cin >> q->data;
q->next = L->next;
L->next = q;
}
- 尾插法代码:
LinkList end,q;
L = new LNode;
end = new LNode;
end = L;
for (i = 0; i < n; i++)
{
q = new LNode;
cin >> q->data;
end->next = q;
end = end->next;
end->next = NULL;
}
- 链表插入代码:
LinkList p,q;
int flag = 1;
p = L;
while (p->next)
{
if (p->next->data>e)
{
q = new LNode;
q->data = e;
q->next = p->next;
p->next = q;
flag = 0;
break;
}
p = p->next;
}
if (flag)
{
q = new LNode;
q->data = e;
q->next = NULL;
p->next = q;
}
- 链表删除代码:
LinkList p = L;
while (L)
{
p = L;
L = L->next;
delete p;
}
- 有序表:元素以递增或递减顺序排序的链表。
- 有序表插入代码:
void ListInsert(LinkList &L, ElemType e)//有序链表插入元素e
{
LinkList p,q;
int flag = 1;
p = L;
while (p->next)
{
if (p->next->data>e)
{
q = new LNode;
q->data = e;
q->next = p->next;
p->next = q;
flag = 0;
break;
}
p = p->next;
}
if (flag)
{
q = new LNode;
q->data = e;
q->next = NULL;
p->next = q;
}
}
- 有序表删除代码:
while (p!=NULL&&p->next!=NULL)
{
if (p->next->data == e)
{
q = p->next;
p->next = p->next->next;
delete q;
}
p = p->next;
}
` 有序表合并代码:
void MergeList(LinkList &L1, LinkList L2)
{
LinkList p,q,end;
int flag=1;
p = L1->next;
q = L2->next;
L1 = new LNode;
end = L1;
L1->next = NULL;
while (p||q)
{
if (p == NULL)
{
end->next = q;
break;
}
if (q == NULL)
{
end->next = p;
break;
}
if (flag)
{
if (p->data > q->data)
{
end->next = q;
q = q->next;
end = end->next;
end->next = NULL;
}
else if (p->data < q->data)
{
end->next = p;
p = p->next;
end = end->next;
end->next = NULL;
}
else if (p->data == q->data)
{
q = q->next;
}
}
}
}
- 循环链表结构特点:循环链表结束并不是指向NULL而是指向头节点,使其能从任意一个节点遍历整个链表进行链表的查找等操作。
- 双链表结构特点:拥有与next指针相对应的前驱指针,它指向该节点的前一个节点,与循环链表一样能从任意一个节点遍历整个链表进行链表的查找等操作,但结束依旧指向NULL。
1.2.谈谈你对线性表的认识及学习体会。
- 对线性表的认识:与数组相比,对链表的操作对数据关系的理解要求更高,而越强的理解能使链表代码的写法更加简单,甚至比数组更方便,而且在面对不清楚数据个数的情况,使用链表更节省对空间的使用,面对复杂的数据使用链表也能减少许多不必要的循环语句的使用。
- 学习体会:线性表的建立和完全运用都需要许多的代码与思维基础,当线性表出现问题时查错会变的更加不方便,所以在编写线性表时对自己数据的关系与代码写法需要提前与缜密的构思。
2.PTA实验作业
2.1.题目1:6-10 jmu-ds-有序链表的插入删除
2.1.1代码截图
2.1.2本题PTA提交列表说明。
部分正确:用链表元素比较插入元素大小,直到链表元素大于插入元素才能进行插入,没判断若插入元素比链表内所有元素都大应插在尾部的情况。
2.2题目2:6-4 顺序表操作集
2.2.1代码截图:
2.2.2本题PTA提交列表说明。
部分正确:在一开始构建顺序表时,将一开始的最终位置设为-1.进行判断插入位置是否正确时,未将最终位置加1进行判断,导致构建顺序表进行的插入全部错误,以及输出插入错误的位置时,应该输出位置p的内容,写成了输出p字母。
2.3题目3:7-2 一元多项式的乘法与加法运算
2.3.1代码截图
2.3.2本题PTA提交列表说明。
部分正确:
- 一开始并没意识到空的多项式需要用0 0输出,反而在思考是否是出现一个算数步骤答案为0 0时需要特别打出导致错误
- number数组的最大容量MaxSize过小,考虑到两指数相乘最大指数可为2000后更改了MaxSize取消了段错误
- 对number数组的遍历寻找有无有数值的多项式时for循环i最大取值过小,一开始认为最大取值到1000即可,后调试时将两指数1000的多项式相乘时发现乘后的多项式无法被找到,后更改了for循环i最大值为2000.
3.阅读代码
3.1 题目及解题代码
题目:反转链表 II:反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。
代码:
3.1.1 该题的设计思路
时间复杂度O(n)空间复杂度O(m-n)
3.1.2 该题的伪代码
建立链表pre指向原链表L
for i=1 to m-1
pre向下遍历至m-1位置 end;
for i=m to i=n
用头插法将m-n位置上链表以pre为头节点插入 end;
将原m位置上链表指向n+1位置链表
3.1.3 运行结果
3.1.4分析该题目解题优势及难点。
该题与pta逆转链表相似,唯一的差别就是固定了被逆转的链表的范围,该代码也只使用了一次遍历做法相对简单。
3.2题目及解题代码
题目:环形链表:给定一个链表,判断链表中是否有环。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
解题代码:
3.2.1 该题的设计思路
时间复杂度:O(n)空间复杂度O(1)
3.2.2该题的伪代码
if 为空表 then
返回false
end if
while fast不为空且fast的下一结点亦不为空 then
fast向前移动两个结点
slow向前移动一个结点
if faster和slower相遇 then
返回true
end if
end while
返回false
3.2.3运行结果
3.2.4分析该题目解题优势及难点。
使用快慢双指针,至需要判断两指针会相遇与fast指针与其下一结点是否为空来判断是否为环形指针,但时间复杂度不能准确计算。