算法11——patA1032寻找公共节点(静态链表的使用、静态链表解题步骤总结)

一、算法

题目描述:
要存储英语单词,一种方法是使用链表,一个字母一个字母地存储一个单词。为了节省一些空间,如果单词共享相同的后缀,可以让它们共享相同的子列表。例如,加载和正在加载的存储方式如图1所示。您应该找到公共后缀的起始位置(例如,图1中i的位置)。
在这里插入图片描述

输入格式:
每个输入文件包含一个测试用例。对于每种情况,第一行包含两个节点地址和一个正整数N(≤10^5),其中两个地址是这两个单词的第一个节点的地址,N是节点总数。节点地址为5位正整数,NULL用−1表示。接下来N行,每一行描述一个节点,格式如下:

Address Data Next

其中,Address为节点位置,Data为该节点所包含的字母从{a-z, a-z}中选取的英文字母,Next为下一个节点的位置。

输出格式:
对于每种情况,只需输出公共后缀起始位置。如果这两个单词没有共同的后缀,则输出-1。

样例输入1:

11111 22222 9
67890 i 00002
00010 a 12345
00003 g -1
12345 D 67890
00002 n 00003
22222 B 23456
11111 L 00001
23456 e 67890
00001 o 00010

样例输出1:

67890

样例输入2:

00001 00002 4
00001 a 10001
10001 s -1
00002 a 10002
10002 t -1

样例输出2:

-1

思路:

  1. 由于地址范围很小,所以可以直接使用静态链表。根据题意,可以在结构体中再定义一个bool型标量用来标识是否在第一条链表中出现,是则为true,不是则为false
  2. 遍历第一个链表,将所有的flag设置为false
  3. 枚举第二条链表,当出现第一个flag值的节点,就说明是两条表的公共节点(因为这个节点的next确定,下个节点的next也确定,因此只要遇到一个相同节点,说明后面的节点都相同)

代码:

#include<cstdio>
#include<cstring>
const int maxn = 100010;
struct NODE{
    char data;
    int next;//指针域
    bool flag;
}node[maxn];

int main(){
    for(int i = 0 ; i < maxn ; i++)
        node[i].flag = false;
    int s1,s2,n;
    scanf("%d%d%d",&s1,&s2,&n);
    int address,next;//当前节点地址和后续地址
    char data;
    for(int i = 0 ; i < n ; i++){
        scanf("%d %c %d",&address,&data,&next);
        node[address].data = data;
        node[address].next = next;
    }

    int p;
    for(p = s1 ; p != -1 ; p = node[p].next){
        node[p].flag = true;
    }
    for(p = s2 ; p != -1 ; p = node[p].next){
        if(node[p].flag == true)
            break;
    }
    if(p != -1){
        printf("%05d\n",p);
    }else{
        printf("-1\n");
    }
    return 0;
}

在这里插入图片描述

二、静态链表解题步骤

1、定义静态链表:

struct Node{
    int address;//节点地址
    typename data;//数据域
    int next;//指针域
    XXX;//节点的性质,根据不同题目的信息进行设置
};

2、在程序的开始,对静态链表进行初始化。一般来说,要对定义中的XXX进行初始化,将其定义为一般情况下达不到的数字。例如对结点是否在表上这个性质来说可以初始化为0表示不在表上:

for(int i = 0 ; i < maxn ; i++){
    node[i].XXX = 0;
}

3、题目一般会给出一条链表首结点的地址,那么就可以从这个地址开始遍历链表。需要注意的是,这一步也是为XXX进行标记和计数的一步:

int p = begin , count = 0;
while(p != -1){
    XXX = 1;
    count++;
    p = node[p]->next;
}

4、由于使用静态链表时,结点实际存储位置可能是不连续的,在某些情况下,需要将有效结点全部移动到数组的左侧。我们可以用之前定义的XXX来帮忙。比如说两个参数有无效节点时按照XXX从大到小排序,如果都是有效结点则按照链表中的位置从小到大排序:


bool cmp(Node a , Node b){
    if(a.XXX == -1 || b.XXX == -1){
        return a.XXX > b.XXX;
    }else{
        //二级排序
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_46025531/article/details/122847432