【DS专题活动】第三期解答及第四期(10月20日~10月26日)题目

frankzch 2003-10-20 04:40:05
先说本期的题目:
1、在无头结点单链表上实现线性表基本操作
int Insert(LinkList L,int i,ElemType b)和Delete(LinkList L,int i)

2、已知线性表中元素以值递增有序排列,并以单链表做存储结构。写一算法,删除表中所有值大于mink且小于maxk的元素(若表中存在这样的元素),同时释放被删结点空间,并分析你的算法的时间复杂度。

3、同上题条件,删除表中所有值相同的多余元素,使删除后的表中元素各不相同,同时释放被删结点空间,并分析你算法的时间复杂度(这一点不能忘记,只有学会分析自己的复杂度,才能有助于你写出高效率的程序)

*********************************************
上期题目比较少难度也不大,相信是新手练级的绝佳机会,只要这些题目熟练了,就会为以后的学习打下一个牢固的基础
答案明天给出,没有做的今天可以思考一下
...全文
147 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
StepBy 2003-10-25
  • 打赏
  • 举报
回复
up 一下
frankzch 2003-10-23
  • 打赏
  • 举报
回复
1
xiaoyige886 2003-10-23
  • 打赏
  • 举报
回复
up
tuxw 2003-10-22
  • 打赏
  • 举报
回复
请问题目中的在第i个位置插入或删除,这个i是从0还是从1计记呀
frankzch 2003-10-22
  • 打赏
  • 举报
回复
是不是大家觉得没有难度所有不做?我的组竟然没有一个人给我发来答案的,难道就把我写的贴出来?郁闷,就贴我的吧
注意:EQ(),LT()等是比较函数,由于elemtype类型不一定是数字或字符,所以用EQ(),LT()比较适应面更广些,至于具体实现则根据具体数据类型确定,我们不必深究

第一题:
LNode* Locate(LinkList L,ElemType e)
{//在带头结点的单链表结构上实现线性表元素的定位
LNode *p=L;
while(p&&!EQ(p->data,e))p=p->next;
return(p);
}//Locate

int Lengh(LinkList L)
{//在带头结点的单链表结构上实现求线性表元素的长度
int i=0;
LNode p=L->next;
for(;p;i++);
return(i);
}//Lengh

第二题:
void List_Concat(LinkList ha,LinkList hb,LinkList &hc)
{//将两个链表ha、hb连接在一起,用指针hc返回连接后的链表的头结点
LinkList pa=ha;
while(pa->next)pa=pa->next;
pa->next=hb->next;
free(hb);
hc=ha;
}//List_ConCat

第三题:
书上都有答案,我就不献丑了;关键是:没有头结点的链表对首元结点要特殊处理
短歌如风 2003-10-21
  • 打赏
  • 举报
回复
带头节点的链表必须有一个头节点,对是否为空的判断是Head->next == NULL。
不带头节点的链表才是Head == NULL。

头节点不需要动态分配时可以在定义变量时初始化:
LNode Head = {0, NULL};
如果是动态分配的,要记得在分配成功后加一句pHead -> next = NULL。
kevin_pan 2003-10-21
  • 打赏
  • 举报
回复
我想可能是我一直都习惯于声明变量的时候都习惯直接声明一个实体,而不是一个指针,对于链表头结点看来还是声明一个指针比较好,然后马上把它副职NULL;初始化的时候分配头结点的内存(好象越走越歪了啊)

这样就可以实现判断了,不知道这个方法好不好,太烦琐了吧,这个是适用于带头接点的链表
对于不需要头接点的就好办多了。

kevin_pan 2003-10-21
  • 打赏
  • 举报
回复
node == NULL? 是判断表头的指针值么,我看上面的人都这么做的,可是,当我声明一个变量的时候他的值不是NULL,如果我们声明后马上对它开始操作(非初始化),不也是很严重的错误么。
ZhangYv 2003-10-21
  • 打赏
  • 举报
回复
直接用if (node == NULL)判断可以吧?
kevin_pan 2003-10-21
  • 打赏
  • 举报
回复
请问大家,如何区分一个链式存储结构的表——“空集”和“非法表”

typedef struct LNode{
ElemType data;
LNode* next;
}*Link,LNode;

typedef struct{
Link head,tail;
int length;
}LinkList;

我理解的初始化表的操作一定要分配内存,这样会带来非常多的麻烦,可是从另一个角度来说链表的特点就是应该根据元素来动态分配内存,这样想,初始化的时候又不应该分配内存,而只是把表头的相应元素初始化为NULL,NULL,0。但是这样一来,问题又出现了,如何区分空表和非法表呢,总不能不允许对空表进行操作吧。

这个问题一直捆饶我很久了,一直不敢提出来,怕被笑话:),在树或者别的链式存储结构的时候都会遇到这个问题,请大家帮助我理解一下。
短歌如风 2003-10-21
  • 打赏
  • 举报
回复
“指向指针的指针”可能不太好理解,我再给出一个一般的实现:

int LinkList_Move(LinkList *la, LinkList *lb, int i, int j,int len)
{
LinkList First, Last, InsertPos, Temp;
LinkList PreFirst = NULL, PreLast = NULL, PreInsert = NULL;
int n;
assert(i > 0 && j > 0 && len > 0);
assert(la != NULL && lb != NULL);

//找到要删除的第一个节点
First = *la;
while (i > 1 && First != NULL)
{
--i;
PreFirst = First;
First = First -> next;
}

//找到要删除的最后一个节点的下一个节点
Last = First;
n = len;
while (n > 0 && Last != NULL)
{
--n;
PreLast = Last;
Last = Last -> next;
}

//寻找插入点
InsertPos = *lb;
while(j > 1 && InsertPos != NULL)
{
--j;
PreInsert = InsertPos;
InsertPos = InsertPos -> next);
}

//把[First, Last)从A链断开并加入到B链。
if (PreLast != NULL)//序列非空。这个判断把寻找插入点的循环包括进来也可以,不过这样清晰一些。
{
if (PreFirst == NULL)
*la = Last;
else
PreFirst -> next = Last;

PreLast -> next = InsertPos;
if (PreInsert == NULL)
*lb = First;
else
PreInsert -> next = First;
}
return len - n;
}
frankzch 2003-10-21
  • 打赏
  • 举报
回复
好,每组做好之后自己贴上来
下面是plainsong组的解答:
这一期的解答发现普遍对头节点的问题理解不够,在处理有头链表的Locate、Length时都把头节点也参与比较/计数,在连接时错误地把第二个链表的头节点也连接进来。而在处理无头链表的插入和删除时没有考虑到对首节点的处理。
第一、二题,完成者xiaoyige886(修改过)
int Length(LinkList L) //函数返回 k 值为链表长度
{
assert(L != NULL)
LinkList p = L -> next;
int k = 0;
while(p)
{
p = p-> next;
k++;
}
return k;
}

LinkList Locate(LinkList L, ElemType X)// 查找元素x
{
assert(L != NULL)
LinkList p = L -> Next;
while(p && p-> data != X)
p = p-> next;
return p; //若找到返回该指针,若找不到返回 NULL
}

/*把hb连接到ha后,形成链表hc,不过形成的hc 好象已经没有意义了,
因为ha在次之后已经和hc完全一样了 */
LinkList Union(LinkList ha, LinkList hb, LinkList hc)
{
assert(ha != NULL && hb != NULL)
hc = ha;
LinkList p = ha;
while(p-> next)//判断末尾指针是否为NULL
p = p-> next;
p-> next = hb -> next;

return hc ;

}
第三题的完成都不理想,我给出我的实现:
/******************************************************************
函数:LineList_Move
功能:把链表la的第i个元素开始的len个元素插入到链表lb的第j个元素之前
并从la中删除。
参数:
la:链表指针(指向节点指针的指针),无头节点的链表;不可为NULL。
lb:链表指针,无头节点的链表,不要为NULL
i:移动序列的首元素在la中的索引,1-Based
j:在lb中的插入点索引,1-Based
len:移动的元素个数。
返回值:移动的元素个数
其它:
当i=1时会改变la中的值;
当j=1时会改变lb中的值。
如la元素数不足i + len,则移动从第i个元素开始的所有元素。
如la元素数不足i则不发生移动。
如lb元素数不足j,则添加到末尾。

由于使用的是无头节点的链表,一般情况下在插入和删除时需要对第一个元素进行特殊处理,
为了避免这一特殊处理,使用了“指向指针的指针”进行操作。
******************************************************************/
int LinkList_Move(LinkList *la, LinkList *lb, int i, int j,int len)
{
LinkList * First, * Last, * InsertPos, Temp;
int n;
assert(i > 0 && j > 0 && len > 0);
assert(la != NULL && lb != NULL);

//找到要删除的第一个节点
First = la;
while (i > 1 && *First != NULL)
{
--i;
First = &((*First) -> next);
}

//找到要删除的最后一个节点的下一个节点
Last = First;
n = len;
while (n > 0 && *Last != NULL)
{
--n;
Last = &((*Last) -> next);
}

//寻找插入点
InsertPos = lb;
while(j > 1 && *InsertPos != NULL)
{
--j;
InsertPos = &((*InsertPos) -> next);
}

//把[First, Last)从A链断开并加入到B链。
if (Last != First)//序列非空。这个判断把寻找插入点的循环包括进来也可以,不过这样清晰一些。
{
Temp = *Last;
*Last = *InsertPos;
*InsertPos = *First;
*First = Temp;
}
return len - n;
}
短歌如风 2003-10-21
  • 打赏
  • 举报
回复
B组的答案我发给frankzch了,是在E-Mail中直接写的,自己没留备份,只有麻烦frankzch贴上来了。

是不是以后都要把每一组的答案都贴出来?如果这样,以后我就不用发给frankzch了。
ZhangYv 2003-10-20
  • 打赏
  • 举报
回复
plainsong(短歌) 说得对,确实有错误。但是目前我组才上交这一份,我自己还没有写就先贴上来了。明天我会写自己一份完整的。
短歌如风 2003-10-20
  • 打赏
  • 举报
回复
关于ZhangYv组的答案,我觉得:
1:Locate中的L是头节点,它的data不应参与比较。
2:MergeList中的hb也是头节点,hb->next才是第一个元素的节点,应该连接进来的是它。
3:DeleInse中虽然说不进行错误检测,但我觉得i或j为1不应该认为是错误,而这时是不存在第i-1和第j-1个节点的(两个链表都是无头节点的),应该作特殊处理。
frankzch 2003-10-20
  • 打赏
  • 举报
回复
请大家写程序的时候使用我们给出的类的标准定义:
#define LIST_INIT_SIZE 100
#define LISTINCREMENT 10
typedef struct {//顺序表
ElemType *elem;
int length;
int listsize;
} SqList;


typedef struct LNode {//链表
ElemType data;
struct LNode *next;
} LNode,*LinkList;

ZhangYv:刚才我突然发现我的题目出错了,赶紧把它删了,你的回复也被我删了,不好意思!
现在我重新发了一遍!
frankzch 2003-10-20
  • 打赏
  • 举报
回复
ZhangYv组的解答:
给一份偶组里的程序,我自己还没有写 :<
#define ElemType int
#define Status int
#define NULL 0
#define FALSE 0
#define TRUE 1

typedef struct LNode {
ElemType data;
struct LNode *next;
} LNode, *LinkList;


/*第一题:在带头结点的单链表结构上实现线性表的基本操作LOCATE(L,X)和LENGTH(L).
(L为线性表,X为表内元素) */

LinkList LOCATE(LinkList L,ElemType X)
{
LinkList p;
if(L==NULL) return FALSE;
else
for(p=L; p->data != X; p=p->next)
if(!p) return FALSE;
return p;
}

int LENGTH(LinkList L)
{
int length;
for(length=0; L->next; length++)
L=L->next;
return length;
}


/*第二题:已知指针ha和hb分别指向两个单链表的头结点,并且已知两个链表的长度分别
为m和n。写一算法将两个链表连接在一起,用指针hc返回连接后的链表的头结点 */

void MergeList(LinkList ha,LinkList hb,LinkList hc)
{
hc=ha;
while(ha->next)
ha=ha->next;
ha->next=hb; //将b接在a后面
}


/*第三题:已知指针la和lb分别指向两个无头结点单链表中的首元结点。编写算法从表la
中删除自第i个元素起共len个元素后,将他们插入到表lb中第j个元素之前(la、lb、i、j、
len均由函数参数表传入) */

void DeleInse(LinkList la,LinkList lb,int i,int j,int len)
{
/*la中删除len个元素后,第i-1个元素指向i+len个元素;而lb中第j-1个元素指向la中
的原第i个元素,原la第i+len个元素指向lb第j个元素,本程序不检验参数的合法性 */

int ta; //循环记数
LinkList lai,laj,lbj1,lbj2; //标记断点位置
for(ta=1,lai=la,lai=la;lai->next!=NULL && ta<i;ta++)
lai=lai->next; //使lai指向la的第i-1个元素,若i=1则等于la
for(laj=lai;lai->next!=NULL && ta<i+len;ta++)
laj=laj->next; //继续上面循环,使laj指向la的第i+len-1个元素
for(ta=1,lbj1=lb;lbj1->next!=NULL && ta<j;ta++)
lbj1=lbj1->next; //使lbj1指向lb的第j-1个元素
lbj2=lbj1->next; //使lbj2指向lb的第j 个元素

lbj1->next=lai->next; //lb中第j-1个元素指向la中的原第i个元素
lai->next=laj->next; //la中第i-1个元素指向i+len个元素
laj->next=lbj2; //原la第i+len个元素指向lb第j个元素
}
课 程 设 计 任 务 书 课程设计题目 三位数电容表 功能 技术指标 设计一个电路简洁、精度高及测量范围宽的电容表,将待测电容的电容值显示到数码管,可显示 三位数字 工作量 适中 工作计划 38 查资料,分析原理 39 画原理图,列元器件表 311 购买元器件 312 安装电路 314 电路调试 319 结题验收 320 撰写说明书 325 交说明书并准备答辩 326 答辩 指导教师评语 指导教师: 2010年3 23 目录 第1章 绪论 1 1.1设计要求 1 1.2 设计功能 1 第2章 电路的方框图 2 2.1 电路的方框图 2 第3章 单元电路设计和参数计算 3 3.1 单元电路设计 3 3.1.1 双时基电路 3 3.1.2 控制电路 5 3.1.3 计数电路 5 3.1.4 译码电路 7 3.1.5 显示电路 8 3.1.6 8550型号三极管 9 3.1.7 电容的作用 9 3.2 参数计算 11 第4章 整机电路的工作原理 13 4.1 三位数字电容表原理图 13 4.2 电路工作原理 13 第5章 电路的组装与调试 15 5.1合理布局 15 5.2调试 15 结论 16 收获与体会 17 致谢 18 参考文献 19 附录1 元器件清单 20 第1章 绪论 课程设计是运用自己所学的数字电子技术、模拟电子技术知识,根据老师所给课程设计题目,自行分组(每组3-4人)来设计、搭接、调试电路,使其实现所给题目要求的功能、量化指标等参数,三周内上交电路,老师通过对电路的完成情况、出勤情况、说明书制作情况以及课程设计答辩情况对每位同学进行评分。 1.1设计要求 1.被测电容范围:1PF-10000uF; 2.测试误差<10%; 3.电容值用三位数码管显示。 1.2 设计功能 设计一个电路简洁、精度高及测量范围宽的电容表,将待测电容的电容值显示到数码管可显示三位数。 实际上就是,待测电容容量时间转换器将待测电容的容量转换成与其成正比的单稳态时间。闸门控制器的开通时间及为单稳时间。当闸门控制器开通,由基准脉冲发生器产生的标准计数脉冲被输入到计数器计数,然后再通过译码器对其译码,使BCD码转换成十进制数字笔段码,最后在共阴极数码管上直接显示测量结果。 第2章 电路的方框图 2.1 电路的方框图 三位数字电容表是由基准脉冲发生器、待测电容容量时间转换器、闸门控制器、计数器、译码器及显示器等组成,其方框图如图2-1所示。 基准脉冲发生器是用来产生标准的计数脉冲。待测电容容量时间转换器是把待测电容的容量转换成与容量成正比的单稳态时间td。闸门控制器的开通时间就是单稳态时间td。在to时间内,计数脉冲通过闸门被送往计数器计数,计数的多少直接反映出被测电容的容量。 图2-1 三位数字电容表电路结构框图 第3章 单元电路设计和参数计算 3.1 单元电路设计 3.1.1 双时基电路 双时基电路主要由NE556组成,其芯片引脚与外围电路如图3-1所示。 图3-1 NE556芯片管脚图 由于NE556是两个NE555组成。故这里只简单介绍一下NE555,见图3-2所示。 图3-2 NE555内部结构图 NE555是属于555系列的计时IC的其中的一种型号,555系列IC的接脚功能及运用都是相容的,只是型号不同的因其价格不同其稳定度、省电、可产生的振荡频率也不大相同;而555是一个用途很广且相当普遍的计时IC,只需少数的电阻和电容,便可产生数位电路所需的各种不同频率之脉冲信号。 NE555具体如下的特点: 只需简单的电阻器、电容器,即可完成特定的振荡延时作用。其延时范围极广,可由几微秒至几小时之久。 它的操作电源电压范围极大,可与TTL,CMOS等逻辑电路配合,也就是它的输出准位及输入触发准位,均能与这些逻辑系列的高、低态组合。 其输出端的供给电流大,可直接推动多种自动控制的负载。 它的计时精确度高、温度稳定度佳,且价格便宜。 NE555内部功能框图如图3-3所示。其功能说明如下: 图3-3 NE555内部功能框图 Pin 1 (接地) -地线(或共同接地) ,通常被连接到电路共同接地。 Pin 2 (触发点) -这个脚位是触发NE555使其启动它的时间周期。触发信号上缘电压须大于2/3 VCC,下缘须低于1/3 VCC 。 Pin 3 (输出) -当时间周期开始555的输出输出脚位,移至比电源电压少1.7伏的高电位。周

33,006

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧