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),我发现很多经典算法都是利用了两个或多个指针对链表操作,取得了可观的时间复杂度。
原文地址:https://www.cnblogs.com/codedawn/p/10568257.html