pta非零返回怎么解决_#图解 PTA「6-5 链式表操作集」

6c5de63a21ca0188b45099f84580bc76.png

PTA是浙江大学设计类实验辅助教学平台。

635806014247cd6f11c985d676b9c489.png

题目描述:

本题要求实现链式表的操作集。

函数接口定义:

Position Find( List L, ElementType X );
List Insert( List L, ElementType X, Position P );
List Delete( List L, Position P );

其中List结构定义如下:

typedef struct LNode *PtrToLNode;
struct LNode {
    ElementType Data;
    PtrToLNode Next;
};
typedef PtrToLNode Position;
typedef PtrToLNode List;

各个操作函数的定义为:

Position Find( List L, ElementType X ):返回线性表中首次出现X的位置。若找不到则返回ERROR;

List Insert( List L, ElementType X, Position P ):将X插入在位置P指向的结点之前,返回链表的表头。如果参数P指向非法位置,则打印“Wrong Position for Insertion”,返回ERROR;

List Delete( List L, Position P ):将位置P的元素删除并返回链表的表头。若参数P指向非法位置,则打印“Wrong Position for Deletion”并返回ERROR。

裁判测试程序样例:

#include <stdio.h>
#include <stdlib.h>

#define ERROR NULL
typedef int ElementType;
typedef struct LNode *PtrToLNode;
struct LNode {
    ElementType Data;
    PtrToLNode Next;
};
typedef PtrToLNode Position;
typedef PtrToLNode List;

Position Find( List L, ElementType X );
List Insert( List L, ElementType X, Position P );
List Delete( List L, Position P );

int main()
{
    List L;
    ElementType X;
    Position P, tmp;
    int N;

    L = NULL;
    scanf("%d", &N);
    while ( N-- ) {
        scanf("%d", &X);
        L = Insert(L, X, L);
        if ( L==ERROR ) printf("Wrong Answern");
    }
    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 {
            L = Delete(L, P);
            printf("%d is found and deleted.n", X);
            if ( L==ERROR )
                printf("Wrong Answer or Empty List.n");
        }
    }
    L = Insert(L, X, NULL);
    if ( L==ERROR ) printf("Wrong Answern");
    else
        printf("%d is inserted as the last element.n", X);
    P = (Position)malloc(sizeof(struct LNode));
    tmp = Insert(L, X, P);
    if ( tmp!=ERROR ) printf("Wrong Answern");
    tmp = Delete(L, P);
    if ( tmp!=ERROR ) printf("Wrong Answern");
    for ( P=L; 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

fbc5d8545bc5ab8a4d7d1bc3e8df3b2a.png

Position Find( List L, ElementType X ):返回线性表中首次出现X的位置。若找不到则返回ERROR;

解题思路:

只需要遍历链表,判断L->Data==X。

代码如下:

Position Find( List L, ElementType X ){

    while (L)
    {  
        if (L->Data==X) return L;
        L=L->Next;
    }
    
    return ERROR;

}

List Insert( List L, ElementType X, Position P ):将X插入在位置P指向的结点之前,返回链表的表头。如果参数P指向非法位置,则打印“Wrong Position for Insertion”,返回ERROR;

解题思路:

首先我们需要考虑在头结点之前插入的情况。

所以,我们需要加入以下判断。

    //头插
    if (P==L)
    {
        Node->Next=L;
        return Node;
    }

然后我们才进行,一般的节点插入操作。

  1. malloc一个新节点Node
  2. Node->Next=L->Next
  3. L->Next=Node

68186e5d0d4bff9df2be005bc896b62c.png
节点插入

你可能还有一个问题:需要考虑在尾节点插入吗?

不需要。

题目说的是:将X插入在位置P指向的结点之前。

要在尾节点之后插入,那么P就指向非法位置了。

代码如下:

List Insert( List L, ElementType X, Position P ){

    List Head=L,Node;
    Node=(List)malloc(sizeof(List));
    Node->Data=X;
    Node->Next=NULL;

    //头插
    if (P==L)
    {
        Node->Next=L;
        return Node;
    }
    
    while (L)
    {
        if (L->Next==P)
        {
            Node->Next=L->Next;
            L->Next=Node;
            return Head;
        }

        L=L->Next;
    }

    printf("Wrong Position for Insertionn");
    return ERROR;
}

List Delete( List L, Position P ):将位置P的元素删除并返回链表的表头。若参数P指向非法位置,则打印“Wrong Position for Deletion”并返回ERROR。

解题思路:

首先,我们同样要考虑删除的节点是头结点。

删除头结点,相当简单。

    // 删除头部
    if(P==L)
    {
        L=L->Next;
        return L;
    }

其余节点的删除步骤有三:

  1. 用一个节点G来暂存L->Next 用于释放该节点
  2. L=L->Next->Next
  3. free(G)

fffc133762b320a1efe276d1ac355093.png
节点删除

你可能还有顾虑:要删除尾节点怎么办?

不用担心。

我们只需要调整判断的条件L->Next==P,

所以,当我们遍历到尾节点的前一个节点,执行和一般节点的删除的同样操作。

尾节点->Next为NULL,所以L->Next=NULL。

        if (L->Next==P)
        {
            G=L->Next;
            L->Next=L->Next->Next; //尾节点->Next为NULL,所以L->
            free(G);
            return Head;
        }

如此,就删除了尾节点。

代码如下:

List Delete( List L, Position P ){

    List Head=L,G;
    // 删除头部
    if(P==L)
    {
        L=L->Next;
        return L;
    }

    while (L)
    {
        if (L->Next==P)
        {
            G=L->Next;
            L->Next=L->Next->Next;
            free(G);
            return Head;
        }

        L=L->Next;
    }

    printf("Wrong Position for Deletionn");
    return ERROR;
    
}

53693e5626c62cf8b92fa3384951ad38.png

编译器

C(gcc)

提交代码

Position Find( List L, ElementType X ){

    while (L)
    {  
        if (L->Data==X) return L;
        L=L->Next;
    }
    
    return ERROR;

}

List Insert( List L, ElementType X, Position P ){

    List Head=L,Node;
    Node=(List)malloc(sizeof(List));
    Node->Data=X;
    Node->Next=NULL;

    //头插
    if (P==L)
    {
        Node->Next=L;
        return Node;
    }
    
    while (L)
    {
        if (L->Next==P)
        {
            Node->Next=L->Next;
            L->Next=Node;
            return Head;
        }

        L=L->Next;
    }

    printf("Wrong Position for Insertionn");
    return ERROR;
}

List Delete( List L, Position P ){

    List Head=L,G;
    // 删除头部
    if(P==L)
    {
        L=L->Next;
        return L;
    }

    while (L)
    {
        if (L->Next==P)
        {
            G=L->Next;
            L->Next=L->Next->Next;
            free(G);
            return Head;
        }

        L=L->Next;
    }

    printf("Wrong Position for Deletionn");
    return ERROR;
    
}

运行截图

a71306a156adf836df4a4153368d8138.png
准确输出

提交结果

57c4827d5b615d0683fb418e359c2ee2.png
答案正确

Ncie!Nice!Ncie!

搞定!

cca91c33a25760517bad2dcaf54a96a2.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值