一、单选题
1、
2、
答案:D
解析:
因为h不带头结点,所以h指的就是第一个元素,在第一个元素前面插入t,所以t的下一个指向h,之后,h重新变为指向第一个元素;
头指针—头结点—首元结点
3、
单链表的插入
因为在找位置的时候,是一个个找的,因此要用一个变量不断指向线性表的下一个元素;
Status ListInsert_L(LinkList&L,int i,ElemType e)//在线性表第i个位置插入元素e//插入和创建不一样,插入是在创建的基础上进行的改动;
{
LinkList p;
p=L;//因为现在需要找的位置是插入位置的前一个,插入的位置也有可能为头结点的后面,因此以p为起点;
int j=0;//因为以p为起点,所以j的初始值为0;
while(p&&j<i-1)//这里是在寻找要插入结点位置的前一个
{
p=p->next;
j++;
}
if(!p||j>i-1) return ERROR;//p为空的话就停止;
LinkList s;
s=(LinkList)malloc(sizeof(LNode));//要为插入的地方创建新的结点;
s->data=e;//千万不要忘记在创建结点之后给新结点赋值;
s->next=p->next;
p->next=s;
return OK;
}
千万不要忘记在创建新结点之后赋值
插入的时候,先要找到前一个插入的位置,因为插入的位置也有可能为头结点的后面,因此以p为起点,所以j的初始值为0(这里还用了一个变量j是因为怕有错误的位置出现)。找到位置之后,创建新的结点,输入元素,然后再将新结点放到找到的p的位置的后面;
4、
答案:A
5、
答案:B
解析:
头指针—(头结点)(可以没有)—首元结点
(1)头结点中可以不存储任何信息,也可以存储线性表的长度的附加信息,头结点的指针域指向第一个元素结点存储的位置。头结点的设定是为了操作方便。
(2)头指针是指向链表中第一个结点的指针。若链表中有头结点,那么头指针所指结点为线性表的头结点;若链表中不设头结点,那么该头指针所指结点为该线性表的首元结点;
(3)链表增加头结点的作用如下:
一是:便于首元结点的处理。增加了头结点后,首元结点的地址保留在头结点的指针域中,则对链表的第一个数据元素的操作与其它数据元素相同,无需进行特殊处理。
二是:便于空表和非空表的统一处理。当链表不设头结点的时候,假设L为单链表的头指针,它应该指向首元结点,则当单链表为长度n为0的空表的时,L指针为空(判断空表的条件可记为L==NULL)//L为头指针,L的指针为空指针。增加头结点后,无论链表是否为空,头指针都是指向头结点的非空指针。若为非空单链表,头指针指向头结点。若为空表,则头结点的指针域为空(判定空表的条件可记为L->next==NULL)//L为头指针,L所指的下一个的指针域为空
6、
答案:A
7、
答案:C
8、
答案:D
二、函数题
1、循环单链表区间删除 (15 分)
本题要求实现带头结点的循环单链表的创建和单链表的区间删除。L是一个带头结点的循环单链表,函数ListCreate_CL用于创建一个循环单链表,函数ListDelete_CL用于删除取值大于min小于max的链表元素。
函数接口定义:
Status ListCreate_CL(LinkList &CL);
void ListDelete_CL(LinkList &CL,ElemType min,ElemType max);
裁判测试程序样例:
//库函数头文件包含
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
//函数状态码定义
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status;
typedef int ElemType; //假设线性表中的元素均为整型
typedef struct LNode
{
ElemType data;
struct LNode *next;
}LNode,*LinkList; //循环单链表类型定义与单链表定义相同,区别在尾节点next取值
Status ListCreate_CL(LinkList &CL);
void ListDelete_CL(LinkList &CL, ElemType min, ElemType max);
void ListPrint_CL(LinkList &CL)
{ //输出单链表,空表时输出Empty List。
LNode *p=CL->next; //p指向第一个元素结点
if(p==CL){
printf("Empty List");
return;
}
while(p!=CL)
{
if(p->next!=CL)
printf("%d ",p->data);
else
printf("%d",p->data);
p=p->next;
}
}
int main()
{
LinkList CL;
ElemType min,max;
if(ListCreate_CL(CL)!= OK)
{
printf("循环链表创建失败!!!\n");
return -1;
}
scanf("%d%d",&min,&max);
ListDelete_CL(CL,min,max);
ListPrint_CL(CL);
return 0;
}
/* 请在这里填写答案 */
输入格式: 第一行输入一个整数n,表示循环单链表中元素个数,接下来一行共n个整数,中间用空格隔开。第三行输入min和max。
输出格式: 输出删除后循环链表的各个元素,两个元素之间用空格隔开,最后一个元素后面没有空格。
输入样例:
6
1 2 3 4 5 6
2 5
输出样例:
1 2 5 6
答案
Status ListCreate_CL(LinkList &CL)
{
CL=(LinkList)malloc(sizeof(LNode));
if(!CL) exit(OVERFLOW);
CL->next=CL;
int n;
scanf("%d",&n);
LinkList p,r;
p=CL;
for(int i=0;i<n;i++)
{
r=(LinkList)malloc(sizeof(LNode));
if(!r) exit(OVERFLOW);
scanf("%d",&r->data);
r->next=p->next;
p->next=r;
p=r;
}
return OK;
}
void ListDelete_CL(LinkList &CL,ElemType min,ElemType max)
{
LinkList p,r;
p=CL;
while(p->next!=CL)//注意判别条件不是p,也不是p!=CL;
{
if(p->next->data>min&&p->next->data<max)//比较大小的是p->next->data,千万不要忘记了next
{
r=p->next;
p->next=r->next;
free(r);
}
//p=p->next;
else p=p->next;//这里必须是else
}
}
注意:
(1)注意判别条件不是p,也不是p!=CL;
(2)比较大小的是p->next->data,千万不要忘记了next
(3)else p=p->next;这里必须是else
插入操作中,是用head搭建起re和cu之间的桥梁,用cu创建一个新结点,创建完之后,输入数值,把cu放到链表中,re指向cu,不断这样循环完之后,因为是双向链表,所以re的下一个指向head,同时在这里,head起到桥梁的作用,CL=head;
2、 单链表元素定位 (12 分)
本题要求在链表中查找第一个数据域取值为x的节点,返回节点的位序。L是一个带头结点的单链表,函数ListLocate_L(LinkList L, ElemType x)要求在链表中查找第一个数据域取值为x的节点,返回其位序(从1开始),查找不到则返回0。例如,原单链表各个元素节点的元素依次为1,2,3,4,则ListLocate_L(L, 1)返回1,ListLocate_L(L, 3)返回3,而ListLocate_L(L, 100)返回0。
函数接口定义:
int ListLocate_L(LinkList L, ElemType x);
其中 L 是一个带头节点的单链表。 x 是一个给定的值。函数须在链表中查找第一个数据域取值为x的节点。若找到则返回其位序(从1开始),找不到则返回0。
裁判测试程序样例:
//库函数头文件包含
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
//函数状态码定义
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status;
typedef int ElemType; //假设线性表中的元素均为整型
typedef struct LNode
{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
Status ListCreate_L(LinkList &L,int n)
{
LNode *rearPtr,*curPtr; //一个尾指针,一个指向新节点的指针
L=(LNode*)malloc(sizeof (LNode));
if(!L)exit(OVERFLOW);
L->next=NULL; //先建立一个带头结点的单链表
rearPtr=L; //初始时头结点为尾节点,rearPtr指向尾巴节点
for (int i=1;i<=n;i++){ //每次循环都开辟一个新节点,并把新节点拼到尾节点后
curPtr=(LNode*)malloc(sizeof(LNode));//生成新结点
if(!curPtr)exit(OVERFLOW);
scanf("%d",&curPtr->data);//输入元素值
curPtr->next=NULL; //最后一个节点的next赋空
rearPtr->next=curPtr;
rearPtr=curPtr;
}
return OK;
}
//下面是需要实现的函数的声明
int ListLocate_L(LinkList L, ElemType x);
int main()
{
LinkList L;
int n;
int x,k;
scanf("%d",&n); //输入链表中元素个数
if(ListCreate_L(L,n)!= OK) {
printf("表创建失败!!!\n");
return -1;
}
scanf("%d",&x); //输入待查找元素
k=ListLocate_L(L,x);
printf("%d\n",k);
return 0;
}
/* 请在这里填写答案 */
输入样例:
4
1 2 3 4
1
输出样例:
1
答案
int ListLocate_L(LinkList L, ElemType x)
{
LinkList p;
p=L->next;
int i=1;
while(p)
{
if(p->data==x) return i;
else
{
i++;
p=p->next;
}
}
return 0;
}