在预订(基础)中将BST转换为DLL

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在预订(基础)中将BST转换为DLL相关的知识,希望对你有一定的参考价值。

我有一个BST,我必须将它变成预订基础上的双向链表。该函数应该更改树中每个节点的指针,以便左指针指向列表中的前一个成员,右指针指向下一个成员。 (根的前一个(左)是NULL;同样最后一个节点(右)的下一个是NULL。)我应该返回创建的DLL的头来打印列表。

障碍:您不能使用辅助功能,您必须更改树本身的指针而不是创建新列表。实施在C.

      4                               
    /          
   2      6    ---------> output of DLL: 4<->2<->1<->3<->6<->5<->7.         
 /       /                          
1    3   5   7       

这是我的代码;我希望有人能在这里帮助我。

Node* converToPreOrder(Node* root)
{
    if (root == NULL) return root;

    static Node* head = NULL; 
    static Node* prev = NULL; 
    Node* temp = root;

    if (prev == NULL) 
        head = root;

    if (root->right != NULL && root->left != NULL)
        prev = root;

    else
    {
        prev->right = root;
        temp->left = prev;
    }

    converToPreOrder(root->left);
    converToPreOrder(root->right);

    return head;
}
答案

这里有一些似乎有用的代码。转换功能在概念上非常简单,但在处理细节时需要一些小心。

对于这个问题,在我看来,当您处理任何给定节点时,您需要获得三个元素:

  • 当前节点(root)
  • 左子列表(递归生成)
  • 右子的列表(也是递归生成的)

结果列表需要是:

  • 当前节点,后跟
  • 左子列表,后跟
  • 右孩子的名单。

鉴于问题中的树:

      4                               
    /          
   2      6    ---------> output of DLL: 4<->2<->1<->3<->6<->5<->7.         
 /       /                          
1    3   5   7       

最终结果是:

  • 节点4,后跟节点2的列表,后跟节点6的列表。

当然,节点2的列表是:

  • 节点2,后跟节点1的列表,后跟节点3的列表。
  • 节点1和节点3的列表很简单,结果如下: 节点2,节点1,节点3

类似地,节点6的列表是:

  • 节点6,后跟节点5的列表,后跟节点7的列表。 节点5和节点7的列表很简单,结果如下:
  • 所以6,所以5,5,所以7

因此最终的结果是:

  • 所以4,所以2,2,所以1,1,3,3,所以6,5,所以7

列表是双向链接和空终止的。这意味着在返回调用处理节点4时,左侧列表具有以下组织:

       +--------+     +--------+     +--------+
0 <----|        |<----|        |<----|        |
       | Node 2 |     | Node 1 |     | Node 3 |
       |        |---->|        |---->|        |----> 0
       +--------+     +--------+     +--------+

这些简单的案例返回一个包含null next和previous指针的列表。右侧列表按顺序具有类似于节点6,5,7的组织。组装最终结果需要将节点4的左指针设置为空,将节点4的右指针设置为左列表的头部,将左列表头部的左指针设置为节点4,找到结束列表从节点4的右指针开始,然后在此之后添加右列表,并将右列表头部的左指针设置为指向右列表的节点的右指针。

左侧列表或右侧列表或两者都可以为空;这需要一点点的照顾。

这是生成的代码,包含三个测试用例。指向遍历列表的节点技术指针的指针相当强大,值得学习。您可以找到该技术的其他SO问题,例如:

/* SO 4784-9166 */
#include <inttypes.h>
#include <stdio.h>

typedef struct Node Node;
struct Node
{
    int   number;
    Node *left;
    Node *right;
};

static Node *convertToPreOrder(Node *root)
{
    if (root == 0)
        return 0;
    Node *l_list = convertToPreOrder(root->left);
    Node *r_list = convertToPreOrder(root->right);
    root->left = 0;
    /* Add left list */
    root->right = l_list;
    if (l_list != 0)
        l_list->left = root;
    /* Find the end */
    Node **pos = &root;
    while ((*pos)->right != 0)
        pos = &(*pos)->right;
    /* Add right list */
    (*pos)->right = r_list;
    if (r_list != 0)
        r_list->left = *pos;
    return root;
}

static void print_node(Node *node)
{
    if (node != 0)
        printf("Node = 0x%.12" PRIXPTR " - Number = %d - "
               "Left = 0x%.12" PRIXPTR " - Right = 0x%.12" PRIXPTR "
",
               (uintptr_t)node, node->number, (uintptr_t)node->left, (uintptr_t)node->right);
}

static void print_BST_preorder(Node *root)
{
    if (root == 0)
        return;
    print_node(root);
    print_BST_preorder(root->left);
    print_BST_preorder(root->right);
}

static void print_list(Node *list)
{
    while (list != 0)
    {
        print_node(list);
        list = list->right;
    }
}

static Node *add_bst_node(Node *root, Node *node)
{
    if (root == 0)
        return node;
    if (node->number >= root->number)
        root->right = add_bst_node(root->right, node);
    else
        root->left = add_bst_node(root->left, node);
    return root;
}

static void test_bst_to_list(size_t n_nodes, Node nodes[])
{
    Node *root = 0;
    for (size_t i = 0; i < n_nodes; i++)
        root = add_bst_node(root, &nodes[i]);
    printf("Print BST in pre-order:
");
    print_BST_preorder(root);
    printf("Convert to list
");
    Node *list = convertToPreOrder(root);
    printf("Print list:
");
    print_list(list);
    putchar('
');
}

int main(void)
{
    Node array1[] =
    {
        { 4, 0, 0 },
        { 2, 0, 0 },
        { 1, 0, 0 },
        { 3, 0, 0 },
        { 6, 0, 0 },
        { 5, 0, 0 },
        { 7, 0, 0 },
    };
    enum { ARRAY1_SIZE = sizeof(array1) / sizeof(array1[0]) };
    test_bst_to_list(ARRAY1_SIZE, array1);

    Node array2[] =
    {
        { 19, 0, 0 },
        { 21, 0, 0 },
        { 20, 0, 0 },
        { 18, 0, 0 },
        { 22, 0, 0 },
        { 24, 0, 0 },
        { 17, 0, 0 },
        { 16, 0, 0 },
        { 23, 0, 0 },
        { 27, 0, 0 },
        { 26, 0, 0 },
        { 25, 0, 0 },
    };
    enum { ARRAY2_SIZE = sizeof(array2) / sizeof(array2[0]) };
    test_bst_to_list(ARRAY2_SIZE, array2);

    Node array3[] =
    {
        { 16, 0, 0 },
        { 11, 0, 0 },
        { 21, 0, 0 },
        { 10, 0, 0 },
        { 22, 0, 0 },
        { 22, 0, 0 },
        { 21, 0, 0 },
        { 27, 0, 0 },
        { 27, 0, 0 },
        { 20, 0, 0 },
        { 22, 0, 0 },
        { 17, 0, 0 },
        { 12, 0, 0 },
    };
    enum { ARRAY3_SIZE = sizeof(array3) / sizeof(array3[0]) };
    test_bst_to_list(ARRAY3_SIZE, array3);

    return 0;
}

print_node()函数被调整为在Mac上运行(64位),其中内存地址通常在前4个nybbles中具有前导零,因此12个十六进制数字足以打印它们。

样本输出:

Print BST in pre-order:
Node = 0x7FFEE6F5B180 - Number = 4 - Left = 0x7FFEE6F5B198 - Right = 0x7FFEE6F5B1E0
Node = 0x7FFEE6F5B198 - Number = 2 - Left = 0x7FFEE6F5B1B0 - Right = 0x7FFEE6F5B1C8
Node = 0x7FFEE6F5B1B0 - Number = 1 - Left = 0x000000000000 - Right = 0x000000000000
Node = 0x7FFEE6F5B1C8 - Number = 3 - Left = 0x000000000000 - Right = 0x000000000000
Node = 0x7FFEE6F5B1E0 - Number = 6 - Left = 0x7FFEE6F5B1F8 - Right = 0x7FFEE6F5B210
Node = 0x7FFEE6F5B1F8 - Number = 5 - Left = 0x000000000000 - Right = 0x000000000000
Node = 0x7FFEE6F5B210 - Number = 7 - Left = 0x000000000000 - Right = 0x000000000000
Convert to list
Print list:
Node = 0x7FFEE6F5B180 - Number = 4 - Left = 0x000000000000 - Right = 0x7FFEE6F5B198
Node = 0x7FFEE6F5B198 - Number = 2 - Left = 0x7FFEE6F5B180 - Right = 0x7FFEE6F5B1B0
Node = 0x7FFEE6F5B1B0 - Number = 1 - Left = 0x7FFEE6F5B198 - Right = 0x7FFEE6F5B1C8
Node = 0x7FFEE6F5B1C8 - Number = 3 - Left = 0x7FFEE6F5B1B0 - Right = 0x7FFEE6F5B1E0
Node = 0x7FFEE6F5B1E0 - Number = 6 - Left = 0x7FFEE6F5B1C8 - Right = 0x7FFEE6F5B1F8
Node = 0x7FFEE6F5B1F8 - Number = 5 - Left = 0x7FFEE6F5B1E0 - Right = 0x7FFEE6F5B210
Node = 0x7FFEE6F5B210 - Number = 7 - Left = 0x7FFEE6F5B1F8 - Right = 0x000000000000

Print BST in pre-order:
Node = 0x7FFEE6F5B230 - Number = 19 - Left = 0x7FFEE6F5B278 - Right = 0x7FFEE6F5B248
Node = 0x7FFEE6F5B278 - Number = 18 - Left = 0x7FFEE6F5B2C0 - Right = 0x000000000000
Node = 0x7FFEE6F5B2C0 - Number = 17 - Left = 0x7FFEE6F5B2D8 - Right = 0x000000000000
Node = 0x7FFEE6F5B2D8 - Number = 16 - Left = 0x000000000000 - Right = 0x000000000000
Node = 0x7FFEE6F5B248 - Number = 21 - Left = 0x7FFEE6F5B260 - Right = 0x7FFEE6F5B290
Node = 0x7FFEE6F5B260 - Number = 20 - Left = 0x000000000000 - Right = 0x000000000000
Node = 0x7FFEE6F5B290 - Number = 22 - Left = 0x000000000000 - Right = 0x7FFEE6F5B2A8
Node = 0x7FFEE6F5B2A8 - Number = 24 - Left = 0x7FFEE6F5B2F0 - Right = 0x7FFEE6F5B308
Node = 0x7FFEE6F5B2F0 - Number = 23 - Left = 0x000000000000 - Right = 0x000000000000
Node = 0x7FFEE6F5B308 - Number = 27 - Left = 0x7FFEE6F5B320 - Right = 0x000000000000
Node = 0x7FFEE6F5B320 - Number = 26 - Left = 0x7FFEE6F5B338 - Right = 0x000000000000
Node = 0x7FFEE6F5B338 - Number = 25 - Left = 0x000000000000 - Right = 0x000000000000
Convert to list
Print list:
Node = 0x7FFEE6F5B230 - Number = 19 - Left = 0x000000000000 - Right = 0x7FFEE6F5B278
Node = 0x7FFEE6F5B278 - Number = 18 - Left = 0x7FFEE6F5B230 - Right = 0x7FFEE6F5B2C0
Node = 0x7FFEE6F5B2C0 - Number = 17 - Left = 0x7FFEE6F5B278 - Right = 0x7FFEE6F5B2D8
Node = 0x7FFEE6F5B2D8 - Number = 16 - Left = 0x7FFEE6F5B2C0 - Right = 0x7FFEE6F5B248
Node = 0x7FFEE6F5B248 - Number = 21 - Left = 0x7FFEE6F5B2D8 - Right = 0x7FFEE6F5

以上是关于在预订(基础)中将BST转换为DLL的主要内容,如果未能解决你的问题,请参考以下文章

在 MS VC 2013 Express 中将 C++ dll 从 32 位转换为 64 位

在 Groovy 中将字符串 XML 片段转换为文档节点

在Visual Studio 2010中将Native / C ++ DLL链接到托管C ++ / CLI包装器

HTTP转换为null什么意思?

如何在 ASP.NET MVC 视图中将主键转换为实际名称/描述符字段

在 AsyncTask 中将新的 TextView 设置为片段