自引用结构,包含三个指针(称为左,右和父)
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;
};
如果你仍然卡住了,那么为了帮助你找到正确的方向,你正在处理的数据结构将非常类似于二叉树。赠品是left
和right
指针,它们将指向树中的其他节点。你添加的唯一附加是一个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以上是关于自引用结构,包含三个指针(称为左,右和父)的主要内容,如果未能解决你的问题,请参考以下文章