http://hncu.acmclub.com/index.php?app=problem_title&id=111&problem_id=1326
题目描述
链表是数据结构中一种最基本的数据结构,它是用链式存储结构实现的线性表。它较顺序表而言在插入和删除时不必移动其后的元素。现在给你一些整数,然后会频繁地插入和删除其中的某些元素,会在其中某些时候让你查找某个元素或者输出当前链表中所有的元素。
下面给你基本的算法描述:
图1:链表类型的定义以及获得链表元素的算法描述
图2:链表的插入算法描述
图3:链表的删除算法描述
图4:链表的创建算法描述
输入格式
输入数据只有一组,第一行有n+1个整数,第一个整数是这行余下的整数数目n,后面是n个整数。这一行整数是用来初始化列表的,并且输入的顺序与列表中的顺序相反,也就是说如果列表中是1、2、3那么输入的顺序是3、2、1。
第二行有一个整数m,代表下面还有m行。每行有一个字符串,字符串是“get”,“insert”,“delete”,“show”中的一种。如果是“get”或者“delete”,则其后跟着一个整数a,代表获得或者删除第a个元素;如果是“insert”,则其后跟着两个整数a和e,代表在第a个位置前面插入e;“show”之后没有整数。
输出
如果获取成功,则输出该元素;如果删除成功则输出“delete OK”;如果获取失败或者删除失败,则输出“get fail”以及“delete fail”。如果插入成功则输出“insert OK”,否则输出“insert fail”。如果是“show”则输出列表中的所有元素,如果列表是空的,则输出“Link list is empty”。注:所有的双引号均不输出。
样例输入
3 3 2 1
21
show
delete 1
show
delete 2
show
delete 1
show
delete 2
insert 2 5
show
insert 1 5
show
insert 1 7
show
insert 2 5
show
insert 3 6
show
insert 1 8
show
get 2
样例输出
1 2 3
delete OK
2 3
delete OK
2
delete OK
Link list is empty
delete fail
insert fail
Link list is empty
insert OK
5
insert OK
7 5
insert OK
7 5 5
insert OK
7 5 6 5
insert OK
8 7 5 6 5
7
#include<string.h>
#include<malloc.h> /* malloc()等 */
#include<stdio.h> /* EOF(=^Z或F6),NULL */
#include<stdlib.h> /* atoi() */
#include<math.h> /* floor(),ceil(),abs() */
/* 函数结果状态代码 */
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
/* #define OVERFLOW -2 因为在math.h中已定义OVERFLOW的值为3,故去掉此行 */
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef int Boolean; /* Boolean是布尔类型,其值是TRUE或FALSE */
typedef int ElemType; // 定义元素的类型为整型
struct LNode
{
ElemType data;
struct LNode *next;
};
typedef struct LNode *LinkList; /* 另一种定义LinkList的方法 */
Status GetElem(LinkList L,int i,ElemType *e) /* 算法2.8 */
{
/* L为带头结点的单链表的头指针。当第i个元素存在时,其值赋给e并返回OK,否则返回ERROR */
int j=1; /* j为计数器 */
LinkList p=L->next; /* p指向第一个结点 */
while(p&&j<i) /* 顺指针向后查找,直到p指向第i个元素或p为空 */
{
p=p->next;
j++;
}
if(!p||j>i) /* 第i个元素不存在 */
return ERROR;
*e=p->data; /* 取第i个元素 */
return OK;
}
Status ListInsert(LinkList L,int i,ElemType e) /* 算法2.9。不改变L */
{
/* 在带头结点的单链线性表L中第i个位置之前插入元素e */
int j=0;
LinkList p=L,s;
while(p&&j<i-1) /* 寻找第i-1个结点 */
{
p=p->next;
j++;
}
if(!p||j>i-1) /* i小于1或者大于表长 */
return ERROR;
s=(LinkList)malloc(sizeof(struct LNode)); /* 生成新结点 */
s->data=e; /* 插入L中 */
s->next=p->next;
p->next=s;
return OK;
}
Status ListDelete(LinkList L,int i,ElemType *e) /* 算法2.10。不改变L */
{
/* 在带头结点的单链线性表L中,删除第i个元素,并由e返回其值 */
int j=0;
LinkList p=L,q;
while(p->next&&j<i-1) /* 寻找第i个结点,并令p指向其前趋 */
{
p=p->next;
j++;
}
if(!p->next||j>i-1) /* 删除位置不合理 */
return ERROR;
q=p->next; /* 删除并释放结点 */
p->next=q->next;
*e=q->data;
free(q);
return OK;
}
void CreateList(LinkList *L,int n)
{
/* 逆位序(插在表头)输入n个元素的值,建立带表头结构的单链线性表L */
int i;
LinkList p;
*L=(LinkList)malloc(sizeof(struct LNode));
(*L)->next=NULL; /* 先建立一个带头结点的单链表 */
for(i=n; i>0; --i)
{
p=(LinkList)malloc(sizeof(struct LNode)); /* 生成新结点 */
scanf("%d",&p->data); /* 输入元素值 */
p->next=(*L)->next; /* 插入到表头 */
(*L)->next=p;
}
}
int ShowList(LinkList L)
{
// 显示链表中的元素,返回值为链表元素的数目
int numOfList = 0; // 记录链表中元素的数目
LinkList p = L->next; // 用来遍历链表元素的指针
while(p) // 如果该结点不为空
{
if(numOfList) // 如果该元素不是列表中的第一个元素(先判断值是否为0,然后加1)
{
putchar(' ');
}
numOfList++; // 元素的数目加1
printf("%d",p->data); // 输出元素
p = p->next; // 指针向后移动
}
if(numOfList == 0) // 如果链表中的元素数目为0,说明是空链表
{
return 0;
}
else
{
putchar('\n'); // 注意换行
return numOfList; // 返回链表中元素的数目
}
}
int main()
{
int n; // 初始时元素的数目
int m; // 指令的数目
char strInst[30]; // 存储指令:instruction
int a; // 存储位置数据
LinkList L; // 链表
int e; // 定义节点,用来存储获取的节点或者删除的节点
scanf("%d", &n); // 读入元素的数目
CreateList(&L, n); // 创建链表
scanf("%d", &m); // 读取指令的数目
while(m--) // 做 m 次循环
{
scanf("%s", strInst); // 读取指令
if(strcmp(strInst, "get") == 0) // 如果是需要获取某个元素
{
scanf("%d", &a); // 读取元素的位置
if(GetElem(L, a, &e) == OK) // 如果获取元素成功
{
printf("%d\n", e); // 输出元素的值
}
else // 如果获取元素失败
{
puts("get fail"); // 输出获取元素的出错信息
}
}
else if(strcmp(strInst, "insert") == 0) // 如果是插入某个元素
{
scanf("%d%d", &a, &e); // 获取待插入的位置以及待插入的值
if(ListInsert(L, a, e) == OK) // 如果插入元素成功
{
puts("insert OK"); // 输出插入成功的信息
}
else
{
puts("insert fail"); // 否则输出插入失败的信息
}
}
else if(strcmp(strInst, "delete") == 0) // 如果是删除某个元素
{
scanf("%d",&a); // 获得待删除元素的位置
if(ListDelete(L, a, &e) == OK) // 如果删除成功
{
puts("delete OK"); // 输出删除成功的信息
}
else
{
puts("delete fail"); // 否则输出删除失败的信息
}
}
else if(strcmp(strInst, "show") == 0) // 如果是显示链表
{
if(ShowList(L) == 0) // 如果链表为空
{
puts("Link list is empty"); //显示量表为空的信息
}
}
}
return 0;
}