此题解仅供参考!倘若你有更好的方法,请积极在评论区分享并@我。(,,´•ω•)ノ"(´っω•`。)
题目来源入标题相同,主要的考察是单双链表的排序,本内容只针对后两道题。
第3关:循环单链表输出非递减序列
任务描述
本关任务:设有一个带头结点的循环单链表,其结点值均为正整数。设计一个算法,反复找出单链表中结点值最小的结点并输出,然后将该节点从中删除,直到单链表空为止,再删除表头节点。
相关知识
为了完成本关任务,你需要掌握:1.如何创建循环链表,2.如何遍历链表。
编程要求
根据提示,在右侧编辑器Begin和End之间补充代码。
输入输出说明
输入包含两行,第一行为元素个数
n
,第二行为相应的链表元素。 输出包含一行,为输出的非递减链表元素测试说明
平台会对你编写的代码进行测试:
测试输入: 5
5 2 1 3 4
预期输出: 1 2 3 4 5
开始你的任务吧,祝你成功!
分析
做这个题,主要思路就是用排序,我用的是冒泡排序。 其中还有一些小坑,在接下来的代码中我们来看一下。
挖坑代码如下:
Status Init(LinkList &L)
{
L = new LNode;
if(!L) return ERROR;
L->next = L;//此题的坑就在这里,可以看到我们的届就是它不等于NULL而等于L;
return OK;
}
冒泡排序的代码如下:
主要思想就是在冒泡排序中我们只需要改变data就行,而指针的位置不用改变。!!最后的循环截止范围是NULL!!
while(p)
{
q=p->next;
while(q)
{
if(p->data>q->data)
{
swap(p->data,q->data);//用swap函数或者用中间量temp也可以
}
q=q->next;
}
p=p->next;
}
总代码
void Del_All(LinkList &L)
{
/********************Begin*****************/
LinkList p,q;
p=L->next;
while(p!=L)//注意!
{
q=p->next;
while(q!=L)
{
if(p->data>q->data)
{
swap(p->data,q->data);
}
q=q->next;
}
p=p->next;
}
p=L->next;
while(p != L)
{
cout << p->data << ' ';
p = p->next;
}
/*********************End*******************/
}
第4关:非循环双向链表的访问
任务描述
本关任务:设头指针为L的带有表头节点的非循环双向链表,其每个结点中除有pre(前驱指针),data(数据),next(后继指针)外,还有一个访问频度域freq,在链表被启用前,其均值初始化为0。每当链表中进行一次Locate(L,x)运算时,令元素值为x的结点中的freq域增1,并使链表中的结点保持访问频度非增(递减)的顺序排列,同时最近访问的结点排在频度相同的结点的前面,以便使频繁访问的结点总是靠近表头。试编写符合上述要求的Locate(L,x)运算的算法,该运算为函数过程。
相关知识
为了完成本关任务,你需要掌握:1.如何创建双向链表,2.如何遍历链表。
编程要求
根据提示,在右侧编辑器Begin和End之间补充代码。
输入输出说明
输入:第一行为元素个数
n
,第二行为相应的链表元素,第三行为Locate的操作次数w
,最后一行为w
个x
值。 输出包含n
行,2列,第一列为freq非增的元素,第二列为访问次数freq。测试说明
平台会对你编写的代码进行测试:
测试输入: 5
5 2 1 3 4
3
2 2 4
预期输出: 2 2 4 1 5 0 1 0 3 0
——————————————
开始你的任务吧,祝你成功!
分析
这个题的做法很多,我用了两种,但大体上思路都是先改变freq的值,然后再进行调换。
(1)方法一:插入排序
先找到与x相同的节点,然后freq加1,再把它从链表中删除,最后再插入链表(排序)。
void Locate(DLinkList &L, int x)
{
/***************Begin********************/
DLinkList p,t;
p=L->next;
//从链表删除x
while(p)
{
if(p->data==x)
{
p->freq=p->freq+1;
t=p;
if(p->next!=NULL)//如果x在尾部,则不要这一步骤
p->next->pre=p->pre;
p->pre->next=p->next;
break;
}
p=p->next;
}
//把t插入链表
p=L->next;
while(p)
{
if(t->freq>=p->freq)
{
t->pre=p->pre;
p->pre->next=t;
t->next=p;
p->pre=t;
break;
}
p=p->next;
}
/***************End**********************/
}
(2)方法二:冒泡排序
void Locate(DLinkList &L, int x)
{
/***************Begin********************/
DLinkList p,q;
p=L->next;
//改变freq的值
while(p)
{
if(p->data==x)
{
p->freq=p->freq+1;
break;
}
p=p->next;
}
//冒泡排序
p=L->next;
while(p)
{
q=p->next;
while(q)
{
if(p->freq<=q->freq)
{
swap(p->freq,q->freq);
swap(p->data,q->data);
}
q=q->next;
}
p=p->next;
}
/***************End**********************/
}
在本题中只能用方法一,因为我们的测试集就是按照插入排序来产生答案的。
如果能够帮助你,就点个赞吧O(∩_∩)O哈哈~