自引用结构,包含三个指针(称为左,右和父)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自引用结构,包含三个指针(称为左,右和父)相关的知识,希望对你有一定的参考价值。

我在我的任务中提出了这个问题,并且如果有人能帮我解决这个问题,我就不知道了

我需要创建一个自引用结构,包含三个指针(称为left,right和parent)到同一结构的其他实例,以及指向1d数组的指针,其类型可以更改。

    struct node { 
        int* left; 
        int* right;
        int* parent;
        struct node* link; 
    }; 

    int main() 
    { 
        struct node ob; 
        return 0; 
    }
答案

包含三个指针(称为left,right和parent)到同一结构的其他实例,

这一要求将导致:

    struct node { 
        struct node * left; 
        struct node * right;
        struct node * parent;

以及指向1d数组的指针,其类型可以更改。

这可以使用void*完成:

        void * data;
    };
另一答案

如果你仍然卡住了,那么为了帮助你找到正确的方向,你正在处理的数据结构将非常类似于二叉树。赠品是leftright指针,它们将指向树中的其他节点。你添加的唯一附加是一个parent指针,你可能想要指向树中当前节点之上的节点 - 这将允许从树中任何路径的当前节点迭代回到树的根节点。

如果是这种情况,您需要的基本结构是:

typedef struct node { 
    struct node* left; 
    struct node* right;
    struct node* parent;
    int *data; 
} node;

(注意:添加了typedef以允许使用node作为一种类型,而不是总是必须键入struct node

您对结构所做的工作取决于您,但从逻辑上讲,它将类似于二叉树使用,唯一的补充是将树中前一级别的节点指定为每个叶子中的parent节点。创建每个节点的基本功能(只有最小的错误报告)可以是:

void *create_node (int *data)
{
    node *p = malloc (sizeof *p);

    if (!p) {
        perror ("malloc-create_node");
        return NULL;
    }

    p->data = data ? data : NULL;
    p->left = NULL;
    p->right = NULL;
    p->parent = NULL;

    return p;
}

(注意:data可以是整数数组或NULL的地址,其中任何一个都将分配给节点的data指针)

用于添加节点的插入函数将是普通的btree插入,其中添加了将parent节点指针分配给树中紧邻其上方的节点的地址,例如,

void insert (node *tree, int *data)
{
    if (!tree->data)
        tree->data = data;
    else if (data && *data <= *tree->data) {
        if (!tree->left) {
            tree->left = create_node (data);
            tree->left->parent = tree->left;
        }
        else
            insert (tree->left, data);
    }
    else if (data && *data > *tree->data) {
        if (!tree->right) {
            tree->right = create_node (data);
            tree->right->parent = tree->right;
        }
        else
            insert (tree->right, data);
    }
}

添加预订,inorder和postorder遍历,以及释放分配给树的内存的函数,以及输出每个节点的指针地址的简短示例程序可以是:

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

typedef struct node { 
    struct node* left; 
    struct node* right;
    struct node* parent;
    int *data; 
} node;

void *create_node (int *data)
{
    node *p = malloc (sizeof *p);

    if (!p) {
        perror ("malloc-create_node");
        return NULL;
    }

    p->data = data ? data : NULL;
    p->left = NULL;
    p->right = NULL;
    p->parent = NULL;

    return p;
}

void insert (node *tree, int *data)
{
    if (!tree->data)
        tree->data = data;
    else if (data && *data <= *tree->data) {
        if (!tree->left) {
            tree->left = create_node (data);
            tree->left->parent = tree->left;
        }
        else
            insert (tree->left, data);
    }
    else if (data && *data > *tree->data) {
        if (!tree->right) {
            tree->right = create_node (data);
            tree->right->parent = tree->right;
        }
        else
            insert (tree->right, data);
    }
}

void preorder (node *tree)
{
    if (tree) {
        printf ("%10p  %10p  %10p  ->  %p   {%d, %d}
", 
                (void*)tree->left, (void*)tree->parent, (void*)tree->right,
                (void*)tree->data, tree->data[0], tree->data[1]);
        preorder (tree->left);
        preorder (tree->right);
    }
}

void inorder (node *tree)
{
    if (tree) {
        inorder (tree->left);
        printf ("%10p  %10p  %10p  ->  %p   {%d, %d}
", 
                (void*)tree->left, (void*)tree->parent, (void*)tree->right,
                (void*)tree->data, tree->data[0], tree->data[1]);
        inorder (tree->right);
    }
}

void postorder (node *tree)
{
    if (tree) {
        postorder (tree->left);
        postorder (tree->right);
        printf ("%10p  %10p  %10p  ->  %p   {%d, %d}
", 
                (void*)tree->left, (void*)tree->parent, (void*)tree->right,
                (void*)tree->data, tree->data[0], tree->data[1]);
    }
}

void freetree (node *tree)
{
    if (tree) {
        if (tree->left)
            freetree (tree->left);
        if (tree->right)
            freetree (tree->right);
        free (tree);
    }
}

int main(void) {

    int array[][2] = {{1, 2}, {3, 4}, {5, 6}, {2, 4}, {4, 5}},
        n = sizeof array / sizeof *array;
    struct node *ob = create_node (NULL);

    for (int i = 0; i < n; i++)
        insert (ob, array[i]);

    puts ("
    left       parent       right          data
"
          "---------------------------------------------------------------
"
          "preorder:
");
    preorder (ob);
    puts ("
inorder:
");
    inorder (ob);
    puts ("
postorder:
");
    postorder (ob);

    freetree (ob);
}

示例使用/输出

$ ./bin/treelrp

    left       parent       right          data
---------------------------------------------------------------
preorder:

     (nil)       (nil)    0xad2040  ->  0x7ffc0dbd68a0   {1, 2}
  0xad20a0    0xad2040    0xad2070  ->  0x7ffc0dbd68a8   {3, 4}
     (nil)    0xad20a0       (nil)  ->  0x7ffc0dbd68b8   {2, 4}
  0xad20d0    0xad2070       (nil)  ->  0x7ffc0dbd68b0   {5, 6}
     (nil)    0xad20d0       (nil)  ->  0x7ffc0dbd68c0   {4, 5}

inorder:

     (nil)       (nil)    0xad2040  ->  0x7ffc0dbd68a0   {1, 2}
     (nil)    0xad20a0       (nil)  ->  0x7ffc0dbd68b8   {2, 4}
  0xad20a0    0xad2040    0xad2070  ->  0x7ffc0dbd68a8   {3, 4}
     (nil)    0xad20d0       (nil)  ->  0x7ffc0dbd68c0   {4, 5}
  0xad20d0    0xad2070       (nil)  ->  0x7ffc0dbd68b0   {5, 6}

postorder:

     (nil)    0xad20a0       (nil)  ->  0x7ffc0dbd68b8   {2, 4}
     (nil)    0xad20d0       (nil)  ->  0x7ffc0dbd68c0   {4, 5}
  0xad20d0    0xad2070       (nil)  ->  0x7ffc0dbd68b0   {5, 6}
  0xad20a0    0xad2040    0xad2070  ->  0x7ffc0dbd68a8   {3, 4}
     (nil)       (nil)    0xad2040  ->  0x7ffc0dbd68a0   {1, 2}

内存使用/错误检查

在您编写的任何动态分配内存的代码中,您对分配的任何内存块都有2个职责:(1)始终保留指向内存块起始地址的指针,因此,(2)当它为no时可以释放它需要更久。

您必须使用内存错误检查程序,以确保您不会尝试访问内存或写入超出/超出已分配块的范围,尝试读取或基于未初始化值的条件跳转,最后,确认你释放了你分配的所有内存。

对于Linux,valgrind是正常的选择。每个平台都有类似的记忆检查器。它们都很简单易用,只需通过它运行程序即可。

$ valgrind ./bin/treelrp
==24386== Memcheck, a memory error detector
==24386== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==24386== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==24386== Command: ./bin/treelrp
==24386==

    left       parent       right          data
---------------------------------------------------------------
preorder:

     (nil)       (nil)   0x51db0a0  ->  0xffefffc00   {1, 2}
 0x51db160   0x51db0a0   0x51db100  ->  0xffefffc08   {3, 4}
     (nil)   0x51db160       (nil)  ->  0xffefffc18   {2, 4}
 0x51db1c0   0x51db100       (nil)  ->  0xffefffc10   {5, 6}
     (nil)   0x51db1c0       (nil)  ->  0xffefffc20   {4, 5}

inorder:

     (nil)       (nil)   0x51db0a0  ->  0xffefffc00   {1, 2}
     (nil)   0x51db160       (nil)  ->  0xffefffc18   {2, 4}
 0x51db160   0x51db0a0   0x51db100  ->  0xffefffc08   {3, 4}
     (nil)   0x51db1c0       (nil)  ->  0xffefffc20   {4, 5}
 0x51db1c0   0x51db100       (nil)  ->  0xffefffc10   {5, 6}

postorder:

     (nil)   0x51db160       (nil)  ->  0xffefffc18   {2, 4}
     (nil)   0x51db1c0       (nil)  ->  0xffefffc20   {4, 5}
 0x51db1c0   0x51db100       (nil)  ->  0xffefffc10   {5, 6}
 0x51db160   0x51db0a0   0x51db100  ->  0xffefffc08   {3, 4}
     (nil)       (nil)   0x51db0a0  ->  0xffefffc00   {1, 2}
==24386==
==24386== HEAP SUMMARY:
==24386==     in use at exit: 0 byte

以上是关于自引用结构,包含三个指针(称为左,右和父)的主要内容,如果未能解决你的问题,请参考以下文章

从左到右和从右到左移动标签

C++ 介绍——自定义数据类型

数据结构C++实验题 程序代码?

访问片段的子视图时出现空指针异常

如何定位具有相同边距的 div 左、右和上

用内容复制 UILabel 并滑出一个右和一个左