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;
}
相关推荐
Python之栈36 分钟前
Python 隐藏法宝:双下划线 _ _Dunder_ _
数据库·windows·microsoft
BillKu2 小时前
Windows Server部署Vue3+Spring Boot项目
windows·spring boot·后端
love530love11 小时前
Windows 下部署 SUNA 项目:虚拟环境尝试与最终方案
前端·人工智能·windows·后端·docker·rust·开源
BIBI204913 小时前
Windows 下彻底删除 VsCode
windows·vscode
小垣13 小时前
Windows版PostgreSQL 安装 vector 扩展
windows·postgresql·pgvector·spring.ai·vectorstore
杰哥技术分享13 小时前
Windows清理之后,资源管理器卡顿-解决方法
windows
扛枪的书生14 小时前
AD 横向移动-哈希传递攻击
windows·渗透·kali·域渗透
刘俊辉个人博客14 小时前
简单配置RHEL9.X
linux·运维·windows·经验分享·centos·github·vim
小菜刀刀15 小时前
WAF绕过,网络层面后门分析,Windows/linux/数据库提权实验
数据库·windows
IoT小趴菜16 小时前
研华工控机安装Windows10系统,适用UEFI(GPT)格式安装
windows·microsoft·电脑