【问题标题】:Deleting a tree(data structure) in Python在 Python 中删除树(数据结构)
【发布时间】:2013-11-18 06:05:12
【问题描述】:

以下是在C中删除一棵树(GeeksforGeeks提供)

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

/* A binary tree node has data, pointer to left child 
   and a pointer to right child */
struct node 
{
    int data;
    struct node* left;
    struct node* right;
};

/* Helper function that allocates a new node with the
   given data and NULL left and right pointers. */
struct node* newNode(int data) 
{
    struct node* node = (struct node*)
                           malloc(sizeof(struct node));

    node->data = data;
    node->left = NULL;
    node->right = NULL;  
    return(node);
}

/*  This function traverses tree in post order to 
    to delete each and every node of the tree */
void deleteTree(struct node* node) 
{
    if (node == NULL) return;

    /* first delete both subtrees */
    deleteTree(node->left);
    deleteTree(node->right);

    /* then delete the node */
    printf("\n Deleting node: %d", node->data);
    free(node);
} 


/* Driver program to test deleteTree function*/   
int main()
{
    struct node *root = newNode(1); 
    root->left            = newNode(2);
    root->right          = newNode(3);
    root->left->left     = newNode(4);
    root->left->right   = newNode(5); 

    deleteTree(root);  
    root = NULL;

    printf("\n Tree deleted ");

    getchar();
    return 0;
}
The above deleteTree() function deletes the tree, but doesn’t change root to NULL which may cause problems if the user of deleteTree() doesn’t change root to NULL and tires to access values using root pointer. We can modify the deleteTree() function to take reference to the root node so that this problem doesn’t occur. See the following code.

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

/* A binary tree node has data, pointer to left child
   and a pointer to right child */
struct node
{
    int data;
    struct node* left;
    struct node* right;
};

/* Helper function that allocates a new node with the
   given data and NULL left and right pointers. */
struct node* newNode(int data)
{
    struct node* node = (struct node*)
                           malloc(sizeof(struct node));

    node->data = data;
    node->left = NULL;
    node->right = NULL;
    return(node);
}

可以通过free(node) 删除 C 中的节点。在 Python 中,没有这样的方法。我是否需要引用节点的父节点才能在 Python 中删除节点,而在 C 中不需要?

(即,有没有办法在 Python 中使用 delete(node) 而不是 parent.left = None

说明: 我会在 Python 中删除如下所示的树(可能存在一些错误)。

def delete_tree(root, parent):
    if not root:
        return
    if not root.left and not root.right:
        if root is parent.left:
            parent.left = None
        else:
            parent.right = None
    delete_tree(root.left, root)
    delete_tree(root.right, root)
    root = None

在提供的 C 代码中,可以通过释放为特定节点分配的内存来删除节点。但是,在 Python 中,我需要引用节点的父节点来删除节点。有没有比我的代码更简单的方法从树中删除特定节点?

【问题讨论】:

  • 不清楚你想要完成什么:Python 使用垃圾收集 - 永远不需要显式释放对象。如果你用完了一棵树,它的内存将在对树的最后一次引用消失后自动回收。
  • @TimPeters 这是真的吗?甚至实现__del__ 并且可能有循环引用?
  • 谢谢@TimPeters。你能看看更新吗?我的问题的一个更一般的版本实际上是“你如何在 Python 中删除一棵树?”但我想解决 C 从树中删除节点的方式与 Python 的方式之间的区别。
  • @MaximusS,对不起,我仍然不明白你想要完成什么。 Python 既没有malloc() 也没有free()。忘记它们的存在,你会更快乐 ;-) “你如何在 Python 中删除一棵树?”你没有。当您的程序停止引用它时,它会自行消失。您可以浪费时间;-) 如果您愿意,可以将内容设置为 None,但这不是必需的。
  • @Hyperboreus,是的__del__ 方法可以创建不朽的循环垃圾。但在下一个 Python 3 版本中它们将不再存在 :-)

标签: python tree binary-search-tree


【解决方案1】:

正如 cmets 中所解释的,在 Python 中不需要这样做。但是,如果您想要“行为类似于”C 代码的 Python 代码,那么您可以这样做:

class Node:
    # with data members .data, .left, and .right
    def __init__(self, data):
        self.data = data
        self.left = self.right = None

def deleteTree(node):
    if node is not None:
        deleteTree(node.left)
        deleteTree(node.right)
        node.left = node.right = None

在 Python 中无法拼写“释放此内存”。你所能做的——也是你需要做的——就是停止引用你不再关心的对象。

编辑:而且,我应该补充一点,你最终会认为这是一件的事情:当你知道你永远不会看到 NULL 指针解引用段错误时,生活会变得更加愉快再次 ;-) 这就是“为什么”Python 无法拼写“释放此内存”的原因。

【讨论】:

    【解决方案2】:

    我认为您对 C 和 Python 中内存管理的差异有一点误解。在 C 语言中,您需要删除之前从堆中取出的所有未使用的内存。您可以通过调用free 函数来实现。
    Python 使用garbage collection 进行自动内存管理。所以,通过parent.left = None 你告诉:对这个对象的引用将是None,没有其他人知道对这个对象的引用,我们可以收集它。垃圾收集器处理所有其他事情,因此您无需从堆中显式删除此对象。

    有没有比我的代码更简单的方法从树中删除特定节点?

    您不是从树中删除特定节点,而是删除了树本身。在 Python 中,您可以使用更简单的方法来执行此操作 - 只需将对其根的引用设置为 None,垃圾收集器就会处理这棵树。

    【讨论】:

    • 再次感谢您。我明白你在说什么,但这不是我想问的。你能看看更新吗?
    • 嘿,谢谢!现在我意识到“删除一棵树”的问题在 C 中只是不平凡的问题,而且这个问题真的不打算在 Python 中解决
    【解决方案3】:

    我猜你要找的是:

    node ##class '__main__.node'
    del(node)
    node
    Traceback (most recent call last):
    NameError: name 'node' is not defined
    

    【讨论】:

      猜你喜欢
      • 2012-03-05
      • 1970-01-01
      • 1970-01-01
      • 2020-09-06
      • 1970-01-01
      • 2019-06-26
      • 1970-01-01
      • 2020-06-20
      • 2015-11-18
      相关资源
      最近更新 更多