【问题标题】:How to find the deepest UNIQUE node of a binary tree in C如何在C中找到二叉树的最深UNIQUE节点
【发布时间】:2019-04-16 14:04:17
【问题描述】:

我正在从文本文件中读取命令。示例输入是:

Create Key 2
Create Key 1
Create Key 3
Update Key 1
Delete Key 2 

我想减少我的程序执行的操作。比如创建Key2是没有用的,之后才删除。

为了尽量减少操作次数,我决定将这些操作存储在二叉搜索树中。在 Cormen、Leiserson、Rivest 和 Stein 所著的第三版“算法简介”一书中,二叉搜索树 (BST) 被明确定义为允许重复。键后面的字母代表创建、更新或删除。一个简单的例子如下:

       K2(C)
      /    \
     /      \
  K1(C)     K3(C)      <-- The deepest Key3 appears here.
     \       /   
    K1(U)   K2(D)      <-- The deepest Key1 and Key2 appear here.

正如所指出的,我希望能够提取所有唯一键的最深位置,以最大限度地减少操作次数。我在 CLRS 中找不到对此的任何引用,也许我在寻找错误的东西..

返回键的简单搜索是不够的,因为它返回找到的第一个节点,因此广度优先或深度优先搜索不起作用。

struct node* search(struct node* root, int key) 
{ 
    // Base Cases: root is null or key is present at root 
    if (root == NULL || root->key == key) 
       return root; 

    // Key is greater than root's key 
    if (root->key < key) 
       return search(root->right, key); 

    // Key is smaller than root's key 
    return search(root->left, key); 

How to handle duplicates in Binary Search Tree? 描述了如何处理插入重复项,而不是如何处理提取最后出现的重复项。

另一个想法是返回最正确的唯一键,如下所示:

struct node * maxValueNode(struct node* node) 
{ 
    struct node* current = node; 

    /* loop down to find the rightmost leaf */
    while (current->right != NULL) 
        current = current->right; 

    return current; 
} 

我在这里遗漏了什么吗?如何找到二叉树的最深 UNIQUE 节点?

【问题讨论】:

  • 制作一个键映射,。当您向树中添加某些内容时,请检查其是否在地图中。如果它在三个中的深度大于地图值,则更新。不过,不要认为你需要二叉树来解决这个问题,这将有助于更详细地解释你删除无用操作的规则。

标签: c algorithm search data-structures tree


【解决方案1】:

我不明白您为什么需要 BST,但无论如何,您可以进行一次不会在第一次出现时停止的搜索,并使用指针跟踪找到的最深节点。这应该可以解决问题:

void deepest_search(struct node * root, int key, int currentDepth, int * maxDepth, struct node * deepestNode)
{
  // Do nothing if root is null
  if (root != NULL)
  {
        // Update deepest node if needed
        if(root->key == key && currentDepth > *maxDepth)
        {
            *maxDepth = currentDepth;
            *deepestNode = *root;
        }

        // Might need to search both sides because of duplicates
        // Can make this an if/else if duplicates are always in left/right subtree
        if(root->key <= key)
            deepest_search(root->right, key, currentDepth + 1, maxDepth, deepestNode);
        if(root->key >= key)
            deepest_search(root->left, key, currentDepth + 1, maxDepth, deepestNode);
    }
}

我在您的(小)示例上对其进行了测试,它似乎工作正常:

struct node
{
    int key;
    int val;
    struct node *left, *right;
};

void main(void)
{
    int key = 1;
    int currentDepth = 1;

    struct node n5 = {2, 5, NULL, NULL};
    struct node n4 = {1, 4, NULL, NULL};
    struct node n3 = {3, 3, &n5, NULL};
    struct node n2 = {1, 2, NULL, &n4};
    struct node n1 = {2, 1, &n2, &n3};

    struct node * deepestNode = (struct node *) malloc(sizeof(struct node));
    int maxDepth = 0;

    deepest_search(&n1, key, currentDepth, &maxDepth, deepestNode);
    printf("%d\n", maxDepth);
    printf("%d\n", deepestNode->val);
}

【讨论】:

    【解决方案2】:

    如果您确定要处理重复值,那么您提到的文章提供了如何在 BST 中处理它们的好主意。假设您实现了这两种插入方法中的一种,让我们看看如何在其中任何一种方法中实现删除节点。

    1。将重复项推送到右侧或左侧子树(丑陋的解决方案)

    如果您选择此解决方案,那么如果您找到一个具有给定值的节点(我们称之为值 X),则无法保证它不会出现在树的其他位置。您必须在其中一个子树中搜索该值。还有更多,您必须传播具有值 X 的每个节点的深度并选择最深的那个。这需要一些编码。这就是为什么我认为第二种解决方案要好得多。

    2。计数值(更好)

    根据这种方法,每个节点都有一个计数器,用于告诉给定值出现了多少次。如果你想删除这个值的一个实例,那么如果计数器>1,那么你只需减少计数器。否则,如果 counter == 1,您将像在常规 BST 中那样删除节点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-08
      • 2015-09-15
      • 2021-02-19
      • 1970-01-01
      • 2022-01-27
      • 2020-07-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多