Yester07 2022-06-29 21:10 采纳率: 48.5%
浏览 55
已结题

树的邻接表求结点到结点的指定路径

问题:
从文本文件中提取出树的邻接表,求指定结点到指定结点的路径。
需求:
我已经完成从文本文件中提取出树的邻接表,但是不知道指定结点到指定结点的如何求解。
请求代码!(堆栈实现)
比如b2到g3无路径,a1到g3的路径为a1-》d2-》g3
以下是文本文件的内容:

img

以下是我目前已经完成的代码:

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#define MAXSIZE 3
#define MAXNODESIZE 10

//ADT
typedef struct Branch
{
    int index;
    struct Branch* next;
}branch;

typedef struct Tnode
{
    char data[MAXSIZE];
    branch* first;
}tnode;

void create(tnode tree[], char str[], int cnt)  //创建邻接表
{
    int j = 0, t = 0;
    for (int i = 0; i < cnt; i++)
    {
        j = 0;
        while (str[t] != '/')  //遇到/就开始找换行符\n,并跳转到下一行,录入下一行头节点
        {
            tree[i].data[j] = str[t];
            j++;
            t++;
        }
        tree[i].data[j] = '\0';  //为tree[i].data加入终止符
        tree[i].first = NULL;
        while (str[t] != '\n' && str[t] != EOF)  //跳转至下一行,准备录下一行的头节点
            t++;
        t++;
    }
    //头节点初始化完成,接下来将子节点连接到头结点
    t = 0;
    int size = strlen(str);
    for (int i = 0; i < cnt && t < size; i++)  //这里需要做两个限制:1.遍历字符串的指针t不能超过字符串长度 2.头结点个数有限制
    {
        while (t < size && str[t] != '/')  //先跳过头节点
            t++;
        t++;
        while (t < size && str[t] != '\n' && str[t] != '\0') // 这里是bug1: t是数字, 也要可能是空了
        {
            j = 0;
            char string[MAXSIZE];
            while (t < size && str[t] != '/' && str[t] != '\n')//将字符串截取出来 bug2:不能处理换行符
            {
                string[j] = str[t];
                j++;
                t++;
            }
            string[j] = '\0';  //为该截取出来的字符串添加终止符
            int target = -1;
            for (int n = 0; n < cnt; n++)
            {
                if (!strcmp(tree[n].data, string)) {
                    target = n;
                    break;
                }
            }
            branch* p = tree[i].first;
            //bug3:插入方式不正确,应该后插入
            if (p == NULL) //如果是第一次将子节点插入头结点,应该特殊处理,这里用尾插法
            {
                p = (branch*)malloc(sizeof(branch));
                p->index = target;
                p->next = NULL;
                tree[i].first = p;
            }
            else
            {
                while (p->next != NULL)  //用p定位到最后一个结点
                {
                    p = p->next;
                }
                p->next = (branch*)malloc(sizeof(branch));  //插入新的结点
                p->next->index = target;
                p->next->next = NULL;
            }
            if (t >= size || str[t] == '\n')
                break;
            t++;  //使t指向下一个单词开头 
        }
        //此时t指向\n
        t++;  //将t指向下一行第一个字符
    }
}
void FillInText(char str[], FILE* fp)  //将文件中内容传入str中
{
    char ch;
    int length = 0;
    ch = fgetc(fp);
    while (ch != EOF)
    {
        str[length] = ch;
        ch = fgetc(fp);
        length++;
    }
    str[length] = '\0';
}

int getCount(char str[])  //获取邻接表头节点个数
{
    int cnt = 0;
    for (int i = 0; i < strlen(str); i++)
    {
        if (str[i] == '\n')
            cnt++;
    }
    return cnt + 1;
}

int main()
{
    FILE* fp;
    tnode tree[MAXNODESIZE];
    for (int i = 0; i < MAXNODESIZE; i++)  //对头节点全部赋\0
    {
        for (int t = 0; t < MAXSIZE; t++)
        {
            tree[i].data[t] = '\0';
        }
    }
    char str[100];
    fp = fopen("Tree.txt", "r");
    if (fp == NULL)
    {
        printf("文件打开失败\n");
        exit(0);
    }
    FillInText(str, fp);
    fclose(fp);
    printf("");
    puts(str);
    create(tree, str, getCount(str));
    return 0;
}
  • 写回答

1条回答 默认 最新

  • 广大菜鸟 2022-06-29 22:27
    关注
    
    #define _CRT_SECURE_NO_WARNINGS
    #include "stdio.h"
    #include "stdlib.h"
    #include "string.h"
    #define MAXSIZE 3
    #define MAXNODESIZE 10
    
    //ADT
    typedef struct Branch
    {
        int index;
        struct Branch* next;
    }branch;
    
    typedef struct Tnode
    {
        char data[MAXSIZE];
        branch* first;
    }tnode;
    
    void create(tnode tree[], char str[], int cnt)  //创建邻接表
    {
        int j = 0, t = 0;
        for (int i = 0; i < cnt; i++)
        {
            j = 0;
            while (str[t] != '/')  //遇到/就开始找换行符\n,并跳转到下一行,录入下一行头节点
            {
                tree[i].data[j] = str[t];
                j++;
                t++;
            }
            tree[i].data[j] = '\0';  //为tree[i].data加入终止符
            tree[i].first = NULL;
            while (str[t] != '\n' && str[t] != EOF)  //跳转至下一行,准备录下一行的头节点
                t++;
            t++;
        }
        //头节点初始化完成,接下来将子节点连接到头结点
        t = 0;
        int size = strlen(str);
        for (int i = 0; i < cnt && t < size; i++)  //这里需要做两个限制:1.遍历字符串的指针t不能超过字符串长度 2.头结点个数有限制
        {
            while (t < size && str[t] != '/')  //先跳过头节点
                t++;
            t++;
            while (t < size && str[t] != '\n' && str[t] != '\0') // 这里是bug1: t是数字, 也要可能是空了
            {
                j = 0;
                char string[MAXSIZE];
                while (t < size && str[t] != '/' && str[t] != '\n')//将字符串截取出来 bug2:不能处理换行符
                {
                    string[j] = str[t];
                    j++;
                    t++;
                }
                string[j] = '\0';  //为该截取出来的字符串添加终止符
                int target = -1;
                for (int n = 0; n < cnt; n++)
                {
                    if (!strcmp(tree[n].data, string)) {
                        target = n;
                        break;
                    }
                }
                branch* p = tree[i].first;
                //bug3:插入方式不正确,应该后插入
                if (p == NULL) //如果是第一次将子节点插入头结点,应该特殊处理,这里用尾插法
                {
                    p = (branch*)malloc(sizeof(branch));
                    p->index = target;
                    p->next = NULL;
                    tree[i].first = p;
                }
                else
                {
                    while (p->next != NULL)  //用p定位到最后一个结点
                    {
                        p = p->next;
                    }
                    p->next = (branch*)malloc(sizeof(branch));  //插入新的结点
                    p->next->index = target;
                    p->next->next = NULL;
                }
                if (t >= size || str[t] == '\n')
                    break;
                t++;  //使t指向下一个单词开头 
            }
            //此时t指向\n
            t++;  //将t指向下一行第一个字符
        }
    }
    void FillInText(char str[], FILE* fp)  //将文件中内容传入str中
    {
        char ch;
        int length = 0;
        ch = fgetc(fp);
        while (ch != EOF)
        {
            str[length] = ch;
            ch = fgetc(fp);
            length++;
        }
        str[length] = '\0';
    }
    
    int getCount(char str[])  //获取邻接表头节点个数
    {
        int cnt = 0;
        for (int i = 0; i < strlen(str); i++)
        {
            if (str[i] == '\n')
                cnt++;
        }
        return cnt + 1;
    }
    
    char* getPath(tnode tree[], int cnt, const char*p1 , const char*p2) {
         
        int s1=-1, s2=-1;
        char result[2048] = "\0";
        for (int i = 0; i < cnt; i++) {
            if (!strcmp(tree[i].data, p1)) {
                s1 = i;
            }
            if (!strcmp(tree[i].data, p2)) {
                s2 = i;
            }
        }
        if (s1 == -1 || s2 == -1) {
            printf("字符串匹配异常");
            memcpy(result, "NULL", 5);
            return result;
        }
        int path[MAXNODESIZE];
        memset(path, -1, sizeof(int) * MAXNODESIZE);
    
        int visited[MAXNODESIZE];
        memset(visited, 0, sizeof(int) * MAXNODESIZE);
    
        //深度优先:用栈
        int stack[MAXNODESIZE];
        int top = -1;
        stack[++top] = s1;
        int pathIndex = -1; 
        visited[s1] = 1;
        //栈非空
        while (top >= 0) {
            //出栈
            int pre = stack[top--];
            path[++pathIndex] = pre;
            if (pre == s2) { break; }
            for (branch* w = tree[pre].first; w != NULL; w = w->next) {
                if (!visited[w->index]) {
                    //没有访问过,入栈
                    stack[++top] = w->index; 
                }
            }
        }
      
        if (path[pathIndex] != s2) {
            memcpy(result, "NULL", 5);
            return result;
        }
        else {
            strcat(result, tree[path[0]].data);
            for (int i = 1; i <= pathIndex; i++) {
                strcat(result, "->");
                strcat(result, tree[path[i]].data);
            }  
            return result;
        }
    }
    
    
    int main()
    {
        FILE* fp;
        tnode tree[MAXNODESIZE];
        for (int i = 0; i < MAXNODESIZE; i++)  //对头节点全部赋\0
        {
            for (int t = 0; t < MAXSIZE; t++)
            {
                tree[i].data[t] = '\0';
            }
        }
        char str[100];
        fp = fopen("C:\\Users\\Lenovo\\Desktop\\Tree.txt", "r");
        if (fp == NULL)
        {
            printf("文件打开失败\n");
            exit(0);
        }
        FillInText(str, fp);
        fclose(fp);
      
        puts(str);
        create(tree, str, getCount(str));
        int cnt = getCount(str);
     
        char*path = getPath(tree,cnt, "b2", "g3");
        printf("%s", path);
        return 0;
    }
    
    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 6月29日
  • 创建了问题 6月29日

悬赏问题

  • ¥15 HFSS 中的 H 场图与 MATLAB 中绘制的 B1 场 部分对应不上
  • ¥15 如何在scanpy上做差异基因和通路富集?
  • ¥20 关于#硬件工程#的问题,请各位专家解答!
  • ¥15 关于#matlab#的问题:期望的系统闭环传递函数为G(s)=wn^2/s^2+2¢wn+wn^2阻尼系数¢=0.707,使系统具有较小的超调量
  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 截图中的mathematics程序转换成matlab
  • ¥15 动力学代码报错,维度不匹配
  • ¥15 Power query添加列问题
  • ¥50 Kubernetes&Fission&Eleasticsearch
  • ¥15 報錯:Person is not mapped,如何解決?