PTA——6-3 带头结点的链式表操作集

什么是单链表?

单链表(一种链式存储结构的线性表)

链表由一个个节点组成,每个节点包含数据域和指针域,指针域指向下一个节点,元素在内存中可以不连续存储。

这一题跟上一道题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 )

  1. w 用于指向新创建的节点

  2. 使用 malloc() 函数为新节点分配内存 空间,并将其地址赋值给指针**w**

  3. 让新节点连接到 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;
}
相关推荐
兮动人1 小时前
Windows 11 系统关键文件夹详解及安全清理指南
windows·安全
LabVIEW开发5 小时前
LabVIEW调用外部DLL
windows·labview·labview知识·labview功能·labview程序
biubiubiu07065 小时前
FFmpeg Windows安装
windows·ffmpeg
哆啦A梦——7 小时前
dll文件缺失解决方法
windows
漠效8 小时前
Duplicate cleaner pro 的使用技巧
windows·经验分享
DogDaoDao8 小时前
Windows下VScode配置FFmpeg开发环境保姆级教程
windows·vscode·ffmpeg·音视频·gcc
Rudon滨海渔村10 小时前
exe文件图标修改器 - exe图标提取器(ico、png) - 修改360文件夹的图标为windows自带的图标
windows
无名小猴10 小时前
Windows软件卸载
windows
小白爱电脑1 天前
电脑上如何查看WiFi密码
windows·电脑
xiaocao_10231 天前
支持在Windows电脑上使用的日程待办清单工具都有哪些?
windows