什么是单链表?
单链表(一种链式存储结构的线性表)
链表由一个个节点组成,每个节点包含数据域和指针域,指针域指向下一个节点,元素在内存中可以不连续存储。
这一题跟上一道题PTA------6-2 顺序表操作集,非常的像,所以主要记忆上一道题的不同点
1.typedef struct LNode *PtrToLNode;新别名
2.存储的数据结构不一样了
顺序表:用数组**Data[MAXSIZE]**存储
通常用整数来表示元素的位置,也就是数组的下标
Last
表示顺序表中最后一个元素的位置当顺序表为空 时,
Last
通常为**-1**链式表(离散的):
用ElementType Data 存储(可以将Data 理解为存储的一个具体的东西)
位置通常用节点的指针来表示
当顺序表为空 时, L->Next=NULL;
3.参数 L不同:
顺序表:
L
是指向顺序表结构体的指针链式表:
L
是指向单链表头节点的指针
一、题目
函数接口定义:
List MakeEmpty();
Position Find( List L, ElementType X );
bool Insert( List L, ElementType X, Position P );
bool Delete( List L, Position P );
其中List
结构定义如下:
typedef struct LNode *PtrToLNode;
struct LNode {ElementType Data; //
ElementType
是自定义的数据类型,它代表节点中存储的数据PtrToLNode Next; //
Next
是一个指向struct LNode
结构体的指针,它用于指向下一个节点};
typedef PtrToLNode Position; //这里把
PtrToLNode
类型重命名为Position
typedef PtrToLNode List; //同样是把
PtrToLNode
类型重命名为List
typedef
属于 C 语言的关键字,其作用是为已有的数据类型创建新的别名。struct LNode
是一个结构体类型,不过此时还未对其具体内容进行定义。struct LNode *
代表指向struct LNode
结构体的指针类型。PtrToLNode
就是为struct LNode *
这个指针类型所定义的新别名。之后就可以用PtrToLNode
来声明指向struct LNode
结构体的指针了。
各个操作函数的定义为:
List MakeEmpty()
:创建并返回一个空的线性表;
Position Find( List L, ElementType X )
:返回线性表中X的位置。若找不到则返回ERROR;
bool Insert( List L, ElementType X, Position P )
:将X插入在位置P指向的结点之前,返回true。如果参数P指向非法位置,则打印"Wrong Position for Insertion",返回false;
bool Delete( List L, Position P )
:将位置P的元素删除并返回true。若参数P指向非法位置,则打印"Wrong Position for Deletion"并返回false。
裁判测试程序样例:
#include <stdio.h>
#include <stdlib.h>
#define ERROR NULL
typedef enum {false, true} bool;
typedef int ElementType;
typedef struct LNode *PtrToLNode;
struct LNode {
ElementType Data;
PtrToLNode Next;
};
typedef PtrToLNode Position;
typedef PtrToLNode List;
List MakeEmpty();
Position Find( List L, ElementType X );
bool Insert( List L, ElementType X, Position P );
bool Delete( List L, Position P );
int main()
{
List L;
ElementType X;
Position P;
int N;
bool flag;
L = MakeEmpty();
scanf("%d", &N);
while ( N-- ) {
scanf("%d", &X);
flag = Insert(L, X, L->Next);
if ( flag==false ) printf("Wrong Answer\n");
}
scanf("%d", &N);
while ( N-- ) {
scanf("%d", &X);
P = Find(L, X);
if ( P == ERROR )
printf("Finding Error: %d is not in.\n", X);
else {
flag = Delete(L, P);
printf("%d is found and deleted.\n", X);
if ( flag==false )
printf("Wrong Answer.\n");
}
}
flag = Insert(L, X, NULL);
if ( flag==false ) printf("Wrong Answer\n");
else
printf("%d is inserted as the last element.\n", X);
P = (Position)malloc(sizeof(struct LNode));
flag = Insert(L, X, P);
if ( flag==true ) printf("Wrong Answer\n");
flag = Delete(L, P);
if ( flag==true ) printf("Wrong Answer\n");
for ( P=L->Next; P; P = P->Next ) printf("%d ", P->Data);
return 0;
}
/* 你的代码将被嵌在这里 */
输入样例:
6
12 2 4 87 10 2
4
2 12 87 5
输出样例:
2 is found and deleted.
12 is found and deleted.
87 is found and deleted.
Finding Error: 5 is not in.
5 is inserted as the last element.
Wrong Position for Insertion
Wrong Position for Deletion
10 4 2 5
二、题解
List MakeEmpty()
List MakeEmpty(){
List L;
L=(PtrToLNode)malloc(sizeof(struct LNode)); //PtrToLNode:指针类型的名字,看题目所给的定义
L->Next=NULL; //这里的 Next 为指针了
return L;
}
Position Find( List L, ElementType X )
1.借助指针遍历链表,从链表的第一个 数据节点(
L->Next
)开始2.利用while 循环遍历,查找 X 即 p->Data==X
注意:p=p->Next;
Position Find( List L, ElementType X ){PtrToLNode p=L->Next; //将指针
p
初始化 为指向链表的第一个数据节点 (假设L
是头节点,头节点本身可能不存储实际数据 ,L->Next
指向第一个真正存储数据的节点 )while(p){
if(p->Data==X){
return p; //返回本次指针
}
p=p->Next; //通过
p = p->Next
移动指针; Next是指向下一个指针的指针}
return ERROR;
}
bool Insert( List L, ElementType X, Position P )
w
用于指向新创建的节点使用
malloc()
函数为新节点分配内存 空间,并将其地址赋值给指针**w
**让新节点连接到
P
节点之前,即 w->Next=P;
思路:

bool Insert( List L, ElementType X, Position P ){
PtrToLNode p=L,w;
while(p){
if(p->Next==P){
w=(PtrToLNode)malloc(sizeof(struct LNode)); //使用
malloc
函数为新节点分配内存空间,并将其地址赋值给指针w
。w->Data=X;
w->Next=P; //将新节点的
Next
指针指向指定位置P
,即让新节点连接到P
节点之前p->Next=w;
return true;
}
p=p->Next; //遍历,指向下一个节点用的(查找 )
}
printf("Wrong Position for Insertion\n");
return false;
}
bool Delete( List L, Position P )
1.跳过P指针 ,即 p->Next=P->Next
2.free(P); //使用
free
函数释放P
节点所占用的内存
bool Delete( List L, Position P ){PtrToLNode p=L;
while(p){
if(p->Next==P&&P!=NULL){ // 检查当前节点
p
的下一个节点是否为要删除的节点P
,并且P
不为NULL
p->Next=P->Next; //直接跳过P指针就可以了
free(P); //使用
free
函数释放P
节点所占用的内存return true;
}
p=p->Next;
}
printf("Wrong Position for Deletion\n");
return false;
}
三、答案
cpp
List MakeEmpty(){
List L;
L=(PtrToLNode)malloc(sizeof(struct LNode));
L->Next=NULL;
return L;
}
Position Find( List L, ElementType X ){
PtrToLNode p=L->Next;
while(p){
if(p->Data==X){
return p;
}
p=p->Next;
}
return ERROR;
}
bool Insert( List L, ElementType X, Position P ){
PtrToLNode p=L,w;
while(p){
if(p->Next==P){
w=(PtrToLNode)malloc(sizeof(struct LNode));
w->Data=X;
w->Next=P;p->Next=w;
return true;
}
p=p->Next;
}
printf("Wrong Position for Insertion\n");
return false;
}
bool Delete( List L, Position P ){
PtrToLNode p=L;
while(p){
if(p->Next==P&&P!=NULL){
p->Next=P->Next;
free(P);
return true;
}
p=p->Next;
}
printf("Wrong Position for Deletion\n");
return false;
}