【问题标题】:a nested struct with pointers带有指针的嵌套结构
【发布时间】:2016-02-13 19:03:51
【问题描述】:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct node *tree_ptr;
typedef struct table * Table;
struct node
{
    char* element;
    tree_ptr left, right;
};

typedef struct table
{
    tree_ptr head;
    int tree_h;
}table;
char* key = NULL;
Table insert(char* insert_key,Table t)
{
    int height = 0;
    //tree_ptr ptr = t->head;
    tree_ptr *ptr = &(t->head);
    key = strdup(insert_key);

    tree_ptr new_node = malloc(sizeof(struct node));
    new_node->element = key;
    new_node->left = NULL;
    new_node->right = NULL;

    if ( t->head==NULL ){
        *ptr = new_node;
        t->tree_h = 0;
        printf("head:%s\n",t->head->element);
        return t;
    }

    while(1){
        if ( strcmp(insert_key, (*ptr)->element)<0 ){
            if ( (*ptr)->left ==NULL ){
                (*ptr)->left = new_node;
                height++;
                if ( height > t->tree_h)
                    t->tree_h = height;
                break;
            }
            else{
                (*ptr) = (*ptr)->left;
                height++;
            }
        }
        else if ( strcmp(insert_key, (*ptr)->element)>0 ){
            if ( (*ptr)->right ==NULL ){
                (*ptr)->right = new_node;
                height++;
                if ( height > t->tree_h)
                    t->tree_h = height;
                break;
            }
            else{
                (*ptr) = (*ptr)->right;
                height++;
            }
        }
        else break;
    }

    return t;

}

int main() {
    Table t = malloc(sizeof(table));
    t->head = NULL;

    t = insert("one", t);
    t = insert("two", t);
    t = insert("three", t);

    printf("%s\n",t->head->element);
   return 0;
}

上面是一个简化的程序,给出了一些定义代码,所以我不能改变基本的结构,比如table,Table,node,tree_ptr,而其他的可以改变。 我要实现的是拼写检查,该表存储了树的头部和树的一些其他属性(这里省略),树实现为有序二叉树。

我发现,在 (*ptr) = (*ptr)->right; 之后,insert() 最多可以工作两次。 t->head 也发生了变化。所以用了两次之后,树头就丢了。

如何修改我的 insert()?

【问题讨论】:

  • 我们需要一个专门用于链接列表的网站。我认为每个数据结构类都必须给链表赋值是有规律的。 :)
  • 对不起,你是什么意思?
  • 我只是在评论这个网站上弹出的链接列表问题的数量。无意冒犯。
  • 数据结构是迄今为止我最喜欢的comp sci类。

标签: c struct pointer-to-pointer


【解决方案1】:

要将节点插入树中,您首先必须搜索空叶子。除此之外,您无需修改​​t,因此无需通过返回值将其写回:

void insert( char* insert_key, Table t )
{
    // serach empty leaf, where to insert the new node
    tree_ptr *ptr = &(t->head);     // start at head
    while ( *ptr != NULL )          // end if empty leaf is found
    {
        int cmpRes = strcmp( insert_key, (*ptr)->element );
        if ( cmpRes == 0 )
            return;                 // insert_key already is member of tree 
        if ( cmpRes < 0 )
            ptr = &((*ptr)->left);  // step down to left child
        else
            ptr = &((*ptr)->right); // step down to right child
    }

    // create new node
    tree_ptr new_node = malloc( sizeof(struct node) );
    new_node->element = strdup( insert_key );
    new_node->left = NULL;
    new_node->right = NULL;

    // place new node at empty leaf
    *ptr = new_node;
}

使用这个递归函数,您可以打印您的树:

void printTree( tree_ptr ptr )
{
    if ( ptr == NULL )
        return;
    printTree( ptr->left );
    printf( "%s\n", ptr->element );
    printTree( ptr->right );
}

printTree( t->head );

有了这个,你可以free你树的所有节点:

void deleteTree( tree_ptr ptr )
{
    if ( ptr == NULL )
        return;
    deleteTree( ptr->left );
    deleteTree( ptr->right );
    free( ptr );
}

deleteTree( t->head );
t->head = NULL;

【讨论】:

  • if ( cmpRes == 0 ) return; 替换为if ( cmpRes == 0 ) break; 即可。
【解决方案2】:

问题是ptr是指向一个struct node的指针的地址,而不是直接指向一个struct node:

tree_ptr *ptr = &(t->head);

那么当在while循环中迭代时,你并没有改变指针ptr,而是指针it指向的就是t-&gt;head

 (*ptr) = (*ptr)->left;

这会在每次迭代时覆盖指针t-&gt;head,从而有效地擦除指针指向的节点,并泄漏内存。

改为使用指向结构节点的普通指针:

struct node* iter = t->head;
...
if ( strcmp(insert_key, iter->element)<0 ){
...
}
else{
       iter = iter->left;
....

我强烈建议删除那些隐藏指针的 typedef,因为它们使代码难以阅读和混淆类型,这在这种情况下是不可取的:

typedef struct node *tree_ptr;
typedef struct table * Table;

还要注意,如果循环发现重复,分配的节点不会被释放,内存泄漏。

【讨论】:

  • 解决办法是什么?我已经尝试过“tree_ptr ptr = t->head”,但是树无法保持更新。
  • @NUO 我的回答中哪一部分令人困惑?
  • 只是说我没有记下你的答案,虽然你的答案对我没有太大帮助。
  • @NUO 好的。太糟糕了。我不支持懒惰,所以我不会为答案提供完整的解决方案,但正如我已经说过的,如果您发现任何令人困惑的地方,请随时询问。
猜你喜欢
  • 2023-03-10
  • 2021-02-13
  • 1970-01-01
  • 2012-09-23
  • 2010-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多