无需订购即可插入二叉树

时间:2019-02-05 18:39:27

标签: c binary-tree

是否可以在不比较键值的情况下将新节点插入二叉树(不是bst)中?以下代码仅适用于前三个节点。

node *insert (node *root, int *key) {

if (root==NULL) {
    root=newNode(root, key);
    return root;
}

else if (root->left == NULL)
    root->left=insert(root->left,key);
else if  (root-> right == NULL)
    root->right=insert(root->right,key);

return root;

}

5 个答案:

答案 0 :(得分:1)

如果您更改

else if  (root-> right == NULL)

只是

else

然后它将具有始终添加到右侧的效果。


如果您希望它随机选择,请在此功能之外向srand添加一个呼叫。

srand(time(NULL));

然后在此函数中,调用

else if (rand() > MAX_RAND / 2) {
    root->right = insert(root->right, key);
} else {
    root->left = insert(root->left, key);
}

位于现有if / else结构的末尾。

另请参阅:


如果树跟踪每个节点的高度,则可以在进行null检查之后添加

else if (root->left->height <= root->right->height) {
    root->left = insert(root->left, key);
} else {
    root->right = insert(root->right, key);
}

这将使树自动保持平衡。但它需要其他代码来管理高度。例如。

root->height = 1 + ((root->left->height > root->right->height) ? root->left->height : root->right->height);

这笔额外的开销是否值得,由您自己决定。


建议使用堆的人建议使用索引作为排序。这对于堆来说是没有用的,但是会生成一个平衡的二叉树。因此,根节点将是第一个插入的节点,而最近插入的将是最右边的叶子。

答案 1 :(得分:1)

您可以只跟踪每个节点的高度,并始终将其插入到子节点较少的一侧:

node *insert (node *root, int *key) {
    if (root==NULL) {
        root=newNode(root, key);
        root->height = 0
    }
    else if (root->left == NULL) {
        insert(root->left,key);
    }
    else if (root->right == NULL) {
        insert(root->right,key);
    }
    else if (root->left->height <= root->right->height) {
        insert(root->left,key);
    } else {
        insert(root->right,key);
    }
    root->height++
}

答案 2 :(得分:0)

else if (root->left == NULL)
  root->left=insert(root->left,key);

您知道root->left为NULL,为什么要进行递归调用?

当然,下一个 else

  

以下代码仅适用于前三个节点。

如果 left right 都不为NULL,则您不会插入,这时有必要在两个分支之一上进行递归调用,您将考虑密钥(因此请按顺序插入)决定哪个密钥。请注意,如果您插入有排序树,则您对NULL进行的2次测试是不正确的。

答案 3 :(得分:0)

比较值实际上是不相关的,您唯一需要做的就是设置一个指针。由于您没有指定任何实际要求,因此一种解决方案如下:

稍微更改签名,现在您有了一个指向已分配节点的指针:

void insertNode(node *&root, node *newNode) {
    if (root == NULL) { 
         root = newNode;
         return;
    }
    if (root->left == NULL) {
        root-left = newNode;
        return;
    }
    helperInsert(root->left, newNode);
    return;
}

这将设置头(假设我的签名正确),否则检查左子。

void helperInsert(node *it, node *newNode) {
    if (it->left == NULL) {
        it->left = newNode;
        return;
    }
    helperInsert(it->left, newNode);
    return;
}

这显然是一种有缺陷的方法(几乎不会平衡树),几乎将树视为链接列表,但是据我对问题的最佳理解,这是如何完成此问题的示例。

答案 4 :(得分:0)

堆建议最合理。您无需堆积任何东西,只需遵循索引public class RetriableProcessorExponentialDecorator implements AbsMessageProcessorDecorator { private final AbsMessageProcessor messageProcessor; @Autowired private AbsMessageActiveMQConfiguration configuration; @Override public void onMessage(AbsMessage message) throws Exception { int executionCounter = 0; int delayCounter = 1000; final int maxRetries = this.configuration.getExceptionRetry() + 1; do { executionCounter++; try { this.messageProcessor.onMessage(message); } catch (RetriableException e) { log.info("Failed to process message. Retry #{}", executionCounter); Thread.sleep(delayCounter); delayCounter = delayCounter * 2; } catch (Exception e) { // We don't retry on this, only RetriableException. throw e; } } while (executionCounter < maxRetries && delayCounter < Long.MAX_VALUE); } } 上的元素在k2*k + 1上具有子元素的规则。

另一种方法是在没有数组但动态生成节点的情况下有用,它是逐级填充树。请注意,在2*k + 2级,有k个时隙,方便地用k位整数索引。将索引解释为沿着树的路径(清除位指示跟随左子节点,置位指示跟随右子节点),沿以下行:

2 ** k