【问题标题】:Getting a path by traversing backward a linkedlist tree structure通过向后遍历链表树结构获取路径
【发布时间】:2015-09-23 08:04:23
【问题描述】:

我有一个像下面这样的树结构

-> grandma
    -> dad
        -> me
        -> sister
            -> niece
        -> brother
    -> uncle
        -> cousin

我有一个结构如下

struct Node{
Node *parent;
Node *next;
Node *child;
Node *prev;
}

如果我有 niece 节点,我想回到根节点,并将该路径保存在 c 字符串中,我也不知道如何将遍历的路径保存在字符串中。如果我有侄女,它应该将路径保存为,grandma/data/me/sister/niece

如果我也有表哥,想回到原路,应该是奶奶/叔叔/表哥,怎么知道那个叔叔父母是奶奶并在完整遍历的路径中连接它吗?

【问题讨论】:

  • 如何获取节点的名称,例如像uncleniece 这样的字符串?
  • 是的,我把它作为一个字符串,考虑我有节点的字符串

标签: c algorithm


【解决方案1】:

要执行此操作,您可以使用递归函数调用自身来查找根,然后将 nodesnames 附加到某个缓冲区。

例子:

void buildPath(Node* node, char* buffer)
{
    if (node->parent != NULL)
        buildPath(node->parent, buffer);
    else
        strcpy("", buffer);

    strcat(buffer, node->name);
}

笑话迭代示例(不要这样做!):

void buildPath(Node* node, char* buffer)
{
    strcpy("", buffer);

    do {
        strrev(node->name);
        strcat(node->name, buffer);
        strrev(node->name);

        node = node->parent;
    } while (node != NULL);

    strrev(buffer);
}

简单的栈迭代示例:

void buildPath(Node* node, char* buffer)
{
    const size_t MAX_STACK_SIZE = 1024;
    char* stack[MAX_STACK_SIZE];
    char** top = stack;

    do {
        *top++ = node->name; // Stack overflow can occurs here!!!
        node = node->parent;
    } while (node != NULL);

    strcpy("", buffer);

    do {
        strcat(buffer, *top--);
    } while (top > stack);
}

【讨论】:

  • 你能提供一个迭代解决方案吗?感谢您的递归解决方案
  • @AhmedSaleh,开个玩笑,是的,我可以。说真的,我不能让这个函数在堆栈等数据结构中收集路径的节点。
  • @AhmedSaleh 这种方法可以工作,但在这种情况下,结果不是很明显。该算法在每次迭代中反转每个名称并将它们收集在反转缓冲区中。最后,它反转这个缓冲区以获得正确的路径。
  • 对于迭代版本,另一种可能性,给定缓冲区及其长度作为参数,将像堆栈一样从末尾填充缓冲区;最后,要么返回一个指向其中实际字符串开头的指针,要么将内容与memmove 重新对齐。我已经将前者用于一些itoa-esque 功能。
  • @Medinoc,感谢您的评论。我不知道 Ahmed 使用什么策略来管理内存,所以我只展示了方法,并没有展示任何策略。该函数可以分配内存,或者它可以检查溢出,或者它可以返回所需内存的大小——所有这些策略都是可能的。
【解决方案2】:

由于@Ahmed Saleh 的要求,我为带有缓冲区和长度的迭代制作了一个完整的示例。但是,它没有注释。

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

struct node { struct node *parent; char const * name; };

char* PushString(char* buffer, char* currentPosition, char const *toAdd)
{
    if(buffer == NULL || currentPosition == NULL)
        return NULL;
    if(toAdd == NULL)
        return currentPosition;

    {
        size_t freeSpace = currentPosition - buffer;
        size_t length = strlen(toAdd);
        if(length > freeSpace)
            return NULL;
        currentPosition -= length;
        //Note: I'm using a sizeof here, to avoid bad surprises
        //when this code is someday converted to use wchar_t instead of char
        memcpy(currentPosition, toAdd, length * sizeof(*toAdd));
        return currentPosition;
    }
}

char* BuildPath(struct node const* theNode, char *buffer, size_t bufferSize)
{
    char * currentPosition = buffer + bufferSize;
    if(buffer==NULL || bufferSize==0)
        return NULL;

    *(--currentPosition) = '\0';

    while(theNode != NULL)
    {
        currentPosition = PushString(buffer, currentPosition, theNode->name);
        if(currentPosition == NULL)
            return NULL;
        currentPosition = PushString(buffer, currentPosition, "/");
        if(currentPosition == NULL)
            return NULL;
        theNode = theNode->parent;
    }
    return currentPosition;
}

int main(void)
{
    struct node node1 = { NULL, "root" };
    struct node node2 = { &node1, "child" };
    struct node node3 = { &node2, "grandchild" };
    char buffer[80];
    char* ret = BuildPath(&node3, buffer, sizeof buffer / sizeof(*buffer));
    if(ret == NULL)
    {
        puts("Failed.");
        return EXIT_FAILURE;
    }
    printf("Result: %s\n", ret);
    return EXIT_SUCCESS;
}

【讨论】:

    猜你喜欢
    • 2012-01-07
    • 1970-01-01
    • 1970-01-01
    • 2014-12-12
    • 1970-01-01
    • 1970-01-01
    • 2017-09-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多