【问题标题】:Inserting millions of Elements into a Binary Search Tree BST将数百万个元素插入二叉搜索树 BST
【发布时间】:2015-12-06 22:58:39
【问题描述】:

我已经尝试解决这个问题将近 3 天了,但还没有运气。我正在尝试将许多大小为(500 万)个无符号整数的元素插入二叉树。

当我将要插入的总元素限制为 10K 时,此代码工作正常,但是,当我将总元素设置为 500 万时,它不起作用。 我在我的电脑上运行这段代码:

  • Windows 7 - 32
  • 内存 4 GB

任何帮助将不胜感激。提前致谢 :) 这是我的代码:

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

typedef int ElementType;

typedef struct TreeNode {
  ElementType element;
  struct TreeNode *left, *right;
} TreeNode;

TreeNode *createTree(){
    //Create the root of tree
    TreeNode *tempNode;
    tempNode = malloc(sizeof(TreeNode));
    tempNode->element = 0;
    tempNode->left = NULL;
    tempNode->right = NULL;
    return tempNode;
}

TreeNode *createNode(ElementType X){
    //Create a new leaf node and return the pointer
    TreeNode *tempNode;
    tempNode = malloc(sizeof(TreeNode));
    tempNode->element = X;
    tempNode->left = NULL;
    tempNode->right = NULL;
    return tempNode;
}

TreeNode *insertElement(TreeNode *node, ElementType X){
    //insert element to Tree
    if(node==NULL){
        return createNode(X);
    }
    else{
        if(X < node->element){
                node->left = insertElement(node->left, X);
                return node; // add this.
}
    else if(X > node->element){
                 node->right =  insertElement(node->right, X);
                 return node; // add t

        else if(X == node->element){
            printf("Oops! the element is already present in the tree.");
        }
    }
}

TreeNode *displayTree(TreeNode *node){
    //display the full tree
    if(node==NULL){
        return;
    }
    displayTree(node->left);
    printf("| %d ", node->element); 
    displayTree(node->right);
}

main(){
    //pointer to root of tree #2
    TreeNode *TreePtr;
    TreeNode *TreeRoot;
    TreeNode *TreeChild;

    //Create the root of tree
    TreePtr = createTree();

    TreeRoot = TreePtr;

    TreeRoot->element = 32;
    
  for ( int i=0; i < 5000000; i ++)
    insertElement(TreeRoot, i);
   
    displayTree(TreeRoot);
}

任何帮助将不胜感激。在此先感谢:)

【问题讨论】:

  • 很难说不知道您遇到了什么错误。由于您使用递归,根据添加项目的顺序,递归可能会导致堆栈溢出。由于二叉树不必平衡,插入数据大部分已经排序的项目将导致非常深且不平衡的树,并且深度递归调用将导致堆栈溢出。如果可以,请尝试使用 B-tree(平衡树)
  • 为什么总是插入值八 (8)?如我所见,你总是会得到一棵只有一个键(八个)的树
  • 其实是笔误,应该是“i”
  • “它不起作用”。这本身就不是一个有效的问题描述。请描述实际的错误或不正确的行为是什么。
  • ^^ 你以为我们不需要知道吗? :((

标签: c tree binary-search-tree


【解决方案1】:

假设您的代码中没有其他错误,总是插入 8 会将树退化为列表,我认为,您的堆栈将在远低于 500 万的某个递归级别溢出。

为了通常避免退化树,我建议您使用 AVL-Tree 的插入/删除语义。 这样做的好处是您的数据结构可以保持原样,但您只需调整插入和删除过程。

编辑:在您的评论中,您现在声明您并不总是插入 8 但 i。这意味着,您将预先排序的元素插入到二叉树中,这也会将其退化为列表,因此与始终插入“8”会出现同样的问题。

看起来像:

1
 \
  2
   \
    3
     \
      4
       \
       ...

按顺序插入元素后。 AVL-Tree 不会遇到这个问题: https://en.wikipedia.org/wiki/AVL_tree

【讨论】:

  • 不想引起争议,我认为你错了,因为@Faisal 阻止插入重复项
  • 他按排序顺序插入元素,这导致了同样的现象,正如我在下面写的(参见编辑部分:)
  • 我已阅读:“总是插入 8 会使树退化为列表”
【解决方案2】:

好的费萨尔。

如果您插入i 的值,那么您将始终插入一个大于树中当前包含的所有键的键。因此,您将获得一棵最大高度的树,它在性能(和形状)上相当于一个列表。由于你的算法是递归的,你会很快得到堆栈溢出。

处理您的问题的一种可能方法是插入随机键,但不能保证避免溢出。理论上,在不成功的搜索中修改的节点数的平均值是 O(log N)。

因此,您可以使用rand() 来获取随机数或更复杂且可靠的随机数生成器。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-09
    • 2012-05-13
    • 1970-01-01
    • 2016-07-07
    相关资源
    最近更新 更多