任务描述
本关任务:实现链表的查找功能。
相关知识
为了完成本关任务,你需要掌握:1. 链接存储,2.链表涉及的主要操作。
链接存储
线性表的存储也可以采用链接存储方式来实现。链接存储方式包括单链表、双链表和循环链表等形式。
下面描述了一种基于单链表的线性表实现方案:
为了讨论简单,假设数据元素的类型为整数:
typedef int ElemType;
在链表中,每个数据元素为一个链表结点,结点的具体定义为:
typedef struct LNode{
ElemType data; //数据域
struct LNode *next; //指针域
}LNode,*LinkList; // LinkList为指向结构体LNode的指针类型
若定义:LinkList L
; 结合上面单链表的示意图,可知:L
指向了一个单链表。我们把L
称为头指针,L
所指结点称为头结点,L->next
所指结点为第一个元素结点。通过头指针L
就可以对单链表进行操作。
链表涉及的主要操作
主要操作如下:
链表的初始化:构造一个带头结点的空的单链表。具体操作函数定义如下:
void LL_Initiate(LinkList &L)
释放链表:释放链表中各个结点。具体操作函数定义如下:
void LL_Free(LinkList &L)
判断链表是否为空: 若为空表,则返回true
,否则返回false
。具体操作函数定义如下:
bool LL_IsEmpty(LinkList L)
头插法创建链表: 输入n
个数据元素,采用头插法,创建一个带头结点的单链表L
。具体操作函数定义如下:
void LL_Create_H(LinkList &L,int n)
尾插法创建链表: 输入n
个数据元素,采用尾插法,创建一个带头结点的单链表L
。具体操作函数定义如下:
void LL_Create_R(LinkList &L,int n)
输出整个链表: 具体操作函数定义如下:
void LL_Print(LinkList L)
获取链表中第i
个元素: 在带头结点的单链表L
中获取第i
个元素的值赋给e
,i
的取值范围[1,n]
。具体操作函数定义如下:
void LL_GetAt(LinkList L, int i, ElemType &e)
查找链表中第一个值为e
的元素: 在带头结点的单链表L中查找第一个值为e
的元素,找到则将该元素在链表中的位置赋给i
,并返回该结点指针,否则i
赋值为0
并返回空指针。具体操作函数定义如下:
LNode *LL_FindValue(LinkList L, ElemType e,int &i)
编程要求
在右侧编辑器中补充代码,完成LL_GetAt
和LL_FindValue
两个操作函数,以实现链表的查找功能。具体要求如下:
LL_GetAt
:在带头结点的单链表L
中获取第i
个元素的值赋给e
,i
的取值范围[1,n]
。LL_FindValue
:在带头结点的单链表L
中查找第一个值为e
的元素,找到则将该元素在链表中的位置赋给i
,并返回该结点指针,否则i
赋值为0
并返回空指针。测试说明
平台会对你编写的代码进行测试,测试文件为step1/Main.cpp
,可在右侧文件夹中进行查看:
测试输入: 6
//输入元素的个数
5 9 11 31 9 77
//输入6个数据元素,依次插入到表尾。形成单链表结点序列:5,9,11,31,9,77
1
//输入待获取元素的位置
9
//输入待查找元素的值
预期输出: 5
//输出获取的第1个元素的值
2
//输出元素9在链表中的位置
开始你的任务吧,祝你成功!
/*************************************************************
链表的实现之查找功能 实现文件
更新于2020年4月21日
**************************************************************/
#include
#include
#include "LinkList.h"
void LL_Initiate(LinkList &L)
//单链表的初始化,即:构造一个带头结点的空的单链表
{
L=(LNode *)malloc(sizeof(LNode));
L->next=NULL;
}
void LL_Free(LinkList &L)
// 释放链表中各个结点。
{
LinkList p;
while(L)
{
p=L;
L=L->next;
free(p);
}
}
bool LL_IsEmpty(LinkList L)
// 判断链表是否为空。
{
return L->next==NULL;
}
void LL_Create_H(LinkList &L,int n)
// 输入n个数据元素,采用头插法,创建一个带头结点的单链表L。
{
LNode *s; int i;
L=(LNode *)malloc(sizeof(LNode)); L->next=NULL; //建立一个带头结点的空链表
for(i=0;idata); //输入元素值
s->next=L->next; L->next=s; //插入到表头
}
}
void LL_Create_R(LinkList &L,int n)
// 输入n个数据元素,采用尾插法,创建一个带头结点的单链表L。
{
LNode *r,*s; int i;
L=(LNode *)malloc(sizeof(LNode)); L->next=NULL; //建立一个带头结点的空链表
r=L; //尾指针r指向头结点
for(i=0;idata); //输入元素值
s->next=NULL; r->next=s; //插入到表尾
r=s; //r指向新的尾结点
}
}
void LL_Print(LinkList L)
// 输出整个线性表。
{
LNode *p;
p=L->next;
while(p)
{
printf("%d ",p->data); p=p->next;
}
printf("\n");
}
void LL_GetAt(LinkList L, int i, ElemType &e)
// 在带头结点的单链表L中获取第i个元素的值赋给e,i的取值范围[1,n]
{
// 请在这里补充代码,完成本关任务
/********** Begin *********/
LNode *p;
p=L->next;
int j=1;
while(i>j&&p)
{
p=p->next;
j++;
}
e= p->data;
/********** End **********/
}
LNode *LL_FindValue(LinkList L, ElemType e,int &i)
//在带头结点的单链表L中查找第一个值为e的元素,
//找到则将该元素在链表中的位置赋给i,并返回该结点指针,否则i赋值为0并返回空指针
{
// 请在这里补充代码,完成本关任务
/********** Begin *********/
LNode *p=L->next;
i++;
while(p&&p->data!=e)
{
p=p->next;
i++;
}
if(!p)
{
i=0;
return p;
}
return p;
/********** End **********/
}
任务描述
本关任务:实现链表的插入和删除功能。
相关知识
为了完成本关任务,你需要掌握:1. 单链表的类型定义,2.链表涉及的主要操作。
单链表的类型定义
定义如下:
typedef int ElemType;//数据元素的类型为整数
typedef struct LNode{
ElemType data; //数据域
struct LNode *next; //指针域
}LNode,*LinkList; // LinkList为指向结构体LNode的指针类型
链表涉及的主要操作
主要操作如下:
链表的初始化
void LL_Initiate(LinkList &L)
释放链表
void LL_Free(LinkList &L)
判断链表是否为空
bool LL_IsEmpty(LinkList L)
头插法创建链表
void LL_Create_H(LinkList &L,int n)
尾插法创建链表
void LL_Create_R(LinkList &L,int n)
输出整个链表
void LL_Print(LinkList L)
获取链表中第i
个元素
void LL_GetAt(LinkList L, int i, ElemType &e)
查找链表中第一个值为e
的元素
LNode *LL_FindValue(LinkList L, ElemType e,int &i)
在链表第i
个位置插入数据元素e
: 在带头结点的单链表L中第i个位置插入值为e
的新元素,i
的取值范围[1,n+1]
。该操作函数具体定义如下:
void LL_InsAt(LinkList L,int i,ElemType e)
删除链表的第i
个数据元素:在带头结点的单链表L
中,删除第i
个元素,i
的取值范围[1,n]
。该操作函数具体定义如下:
void LL_DelAt(LinkList L,int i)
删除链表中第一个值为e
的数据元素: 删除第一个值为e
的数据元素。该操作函数具体定义如下:
void LL_DelValue(LinkList L, ElemType e)
编程要求
在右侧编辑器中补充代码,完成LL_InsAt
、LL_DelAt
和LL_DelValue
三个操作函数,以实现链表的插入和删除功能。具体要求如下:
LL_InsAt
:在带头结点的单链表L
中第i
个位置插入值为e
的新元素,i
的取值范围[1,n+1]
。LL_DelAt
:在带头结点的单链表L
中,删除第i
个元素,i
的取值范围[1,n]
。LL_DelValue
:删除第一个值为e
的数据元素。测试说明
平台会对你编写的代码进行测试,测试文件为step2/Main.cpp
,可在右侧文件夹中进行查看:
测试输入: 6
//输入元素的个数
5 9 11 31 11 88
//输入6个数据元素,依次插入到表尾。形成单链表结点序列:5,9,11,31,11,88
2 10
//输入待插入的位置和待插入元素的值,表示在第2个位置插入元素10
7
//输入待删除元素的位置,表示删除第7个元素
11
//输入待删除元素的值,表示删除值为11的元素
预期输出: 5 10 9 31 11
//输出当前表中的数据元素
开始你的任务吧,祝你成功!
/*************************************************************
链表的实现之增删功能 实现文件
更新于2020年4月21日
**************************************************************/
#include
#include
#include "LinkList.h"
void LL_Initiate(LinkList &L)
//单链表的初始化,即:构造一个带头结点的空的单链表
{
L=(LNode *)malloc(sizeof(LNode));
L->next=NULL;
}
void LL_Free(LinkList &L)
// 释放链表中各个结点。
{
LinkList p;
while(L)
{
p=L;
L=L->next;
free(p);
}
}
bool LL_IsEmpty(LinkList L)
// 判断链表是否为空。
{
return L->next==NULL;
}
void LL_Create_H(LinkList &L,int n)
// 输入n个数据元素,采用头插法,创建一个带头结点的单链表L。
{
LNode *s; int i;
L=(LNode *)malloc(sizeof(LNode)); L->next=NULL; //建立一个带头结点的空链表
for(i=0;idata); //输入元素值
s->next=L->next; L->next=s; //插入到表头
}
}
void LL_Create_R(LinkList &L,int n)
// 输入n个数据元素,采用尾插法,创建一个带头结点的单链表L。
{
LNode *r,*s; int i;
L=(LNode *)malloc(sizeof(LNode)); L->next=NULL; //建立一个带头结点的空链表
r=L; //尾指针r指向头结点
for(i=0;idata); //输入元素值
s->next=NULL; r->next=s; //插入到表尾
r=s; //r指向新的尾结点
}
}
void LL_Print(LinkList L)
// 输出整个线性表。
{
LNode *p;
p=L->next;
while(p)
{
printf("%d ",p->data); p=p->next;
}
printf("\n");
}
void LL_InsAt(LinkList L,int i,ElemType e)
// 在带头结点的单链表L中第i个位置插入值为e的新元素,i的取值范围[1,n+1]
{
// 请在这里补充代码,完成本关任务
/********** Begin *********/
LNode*p,*in;
p=L;
int j=0;
while(p&&jnext;
j++;
}
in = (LNode*)malloc(sizeof(LNode));
in ->data=e;
in ->next=p->next;
p->next=in;
/********** End **********/
}
void LL_DelAt(LinkList L,int i)
// 在带头结点的单链表L中,删除第i个元素,i的取值范围[1,n]
{
// 请在这里补充代码,完成本关任务
/********** Begin *********/
int j=0;
LNode*p,*q;
p=L;
q=p;
while(p&&jnext;
j++;
}
if(p)
{
q->next=p->next;
free(p);
}
/********** End **********/
}
void LL_DelValue(LinkList L, ElemType e)
// 删除第一个值为e的数据元素
{
// 请在这里补充代码,完成本关任务
/********** Begin *********/
LNode*p;
p=L->next;
int pos = 1;
while(p)
{
if(p->data==e)
{
LL_DelAt(L,pos);
break;
}
p=p->next;
pos++;
}
/********** End **********/
}
任务描述
本关任务:已知两个单链表A和B,数据元素按值非递减有序排列,现将A和B归并成一个新的单链表C,使C中的数据元素仍按值非递减有序排列。 例如: 设 A=(3,5,8,11) B=(2,6,9,15,20) 则 C=(2,3,5,6,8,9,11,15,20)
相关知识
为了完成本关任务,你需要掌握:1. 单链表的类型定义,2.单链表涉及的主要操作。
单链表的类型定义
定义如下:
typedef int ElemType;//数据元素的类型为整数
typedef struct LNode{
ElemType data; //数据域
struct LNode *next; //指针域
}LNode,*LinkList; // LinkList为指向结构体LNode的指针类型
单链表涉及的主要操作
主要操作如下:
链表的初始化:构造一个带头结点的空的单链表。具体操作函数定义如下:
void LL_Initiate(LinkList &L)
释放链表:释放链表中各个结点。具体操作函数定义如下:
void LL_Free(LinkList &L)
判断链表是否为空: 若为空表,则返回true
,否则返回false
。具体操作函数定义如下:
bool LL_IsEmpty(LinkList L)
头插法创建链表: 输入n
个数据元素,采用头插法,创建一个带头结点的单链表L
。具体操作函数定义如下:
void LL_Create_H(LinkList &L,int n)
尾插法创建链表: 输入n
个数据元素,采用尾插法,创建一个带头结点的单链表L
。具体操作函数定义如下:
void LL_Create_R(LinkList &L,int n)
输出整个链表: 具体操作函数定义如下:
void LL_Print(LinkList L)
链表的合并: 已知单链表LA
和LB
的元素按值非递减排列,归并LA
和LB
得到新的单链表LC
,LC
的元素也按值非递减排列。该操作函数具体定义如下:
void MergeList_L(LinkList LA,LinkList LB,LinkList &LC)
编程要求
根据提示,在右侧编辑器中补充代码,完成MergeList_L
操作函数,以实现链表的合并。具体要求如下:
MergeList_L
:已知单链表LA
和LB
的元素按值非递减排列,归并LA
和LB
得到新的单链表LC
,LC
的元素也按值非递减排列。
提示:已知单链表 A
和 B
中的数据元素按值非递减有序排列,现要求将 A
和 B
归并为一个新的单链表 C
,且 C
中的数据元素仍按值非递减有序排列。
例如:
A=(1,7,8)
B=(2,4,6,8,10,11)
则合并后的C=(1,2,4,6,7,8,8,10,11)
测试说明
平台会对你编写的代码进行评测,测试文件为step3/Main.cpp
,可在右侧文件夹中进行查看:
测试输入: 4
//输入A表的元素个数
3 5 8 11
//输入4个数据元素,创建A表
7
//输入B表的元素个数
2 6 8 9 11 15 20
//输入7个数据元素,创建B表
预期输出: 2 3 5 6 8 8 9 11 11 15 20
//输出合并后的C表
开始你的任务吧,祝你成功!
/*************************************************************
链表的合并 实现文件
更新于2020年4月21日
**************************************************************/
#include
#include
#include "LinkList.h"
void LL_Initiate(LinkList &L)
//单链表的初始化,即:构造一个带头结点的空的单链表
{
L=(LNode *)malloc(sizeof(LNode));
L->next=NULL;
}
void LL_Free(LinkList &L)
// 释放链表中各个结点。
{
LinkList p;
while(L)
{
p=L;
L=L->next;
free(p);
}
}
bool LL_IsEmpty(LinkList L)
// 判断链表是否为空。
{
return L->next==NULL;
}
void LL_Create_H(LinkList &L,int n)
// 输入n个数据元素,采用头插法,创建一个带头结点的单链表L。
{
LNode *s; int i;
L=(LNode *)malloc(sizeof(LNode)); L->next=NULL; //建立一个带头结点的空链表
for(i=0;idata); //输入元素值
s->next=L->next; L->next=s; //插入到表头
}
}
void LL_Create_R(LinkList &L,int n)
// 输入n个数据元素,采用尾插法,创建一个带头结点的单链表L。
{
LNode *r,*s; int i;
L=(LNode *)malloc(sizeof(LNode)); L->next=NULL; //建立一个带头结点的空链表
r=L; //尾指针r指向头结点
for(i=0;idata); //输入元素值
s->next=NULL; r->next=s; //插入到表尾
r=s; //r指向新的尾结点
}
}
void LL_Print(LinkList L)
// 输出整个链表。
{
LNode *p;
p=L->next;
while(p)
{
printf("%d ",p->data); p=p->next;
}
printf("\n");
}
void MergeList_L(LinkList LA,LinkList LB,LinkList &LC)
//已知单链表LA和LB的元素按值非递减排列
//归并LA和LB得到新的单链表LC,LC的元素也按值非递减排列。
{
// 请在这里补充代码,完成本关任务
/********** Begin *********/
LL_Initiate(LC);//初始化LC
LNode* p, * q, *m, *in;
p = LA->next;
q = LB->next;
m = LC;
in = (LNode*)malloc(sizeof(LNode));
while (p && q)//使用尾插法
{
in = (LNode*)malloc(sizeof(LNode));//建立一个临时节点存数据
if (p->data >= q->data)
{
in->data = q->data;//将LB现在所在节点的数据=>in这个节点
in->next = NULL;//指向NULL,不要让这个节点变成野指针,以免造成不必要的麻烦
m->next = in;/*m的指针指向这个临时节点,
此时可以看成in在m这个链表中*/
m = in;//更新位置
q = q->next;//q指针更新位置
}
else {
in->data = p->data;
in->next = NULL;
m->next = in;
m = in;
p = p->next;
}
}
while (p)
{
in = (LNode*)malloc(sizeof(LNode));
in->data = p->data;
in->next = NULL;
m->next = in;
m = in;
p = p->next;
}
while (q)
{
in = (LNode*)malloc(sizeof(LNode));
in->data = q->data;
in->next = NULL;
m->next = in;
m = in;
q = q->next;
}
/********** End **********/
}