如何找到启动二叉搜索树的好点

时间:2014-07-31 03:30:29

标签: c++ binary-search-tree fstream

我有一个包含大量单词的文本文件,20K +,但它们都按字母顺序排列,现在说你得到一个随机文件,你不知道它有多大,你怎么会找到一个制作一个平衡良好的树的良好起点?注意:我是用C ++做的。谢谢你的建议!我现在正在这样读它们:

template <typename T>
int BST<T>::loadFromFile(string filename)
{
    int count = 0;
    string tempdata;
    ifstream fin(filename);
    if(!fin)
{
    cout<< "Error: Could no open file\n";
    count--;
}
while(fin)
{
    fin>>tempdata;
    if(fin)
    {
        insertEntry(tempdata);
        cout<<"Word: "<<tempdata<<" Count:"<<count<<endl;
        count++;

    }
}
fin.close();
return count;
}//end of loadFromFile() function

^间隔错误,我永远无法将我的代码正确复制到问题中:P

编辑:如果我的插入方法单词正确,我相信在读入按字母排序的文件后,它应该是一个\行,因为每个单词都大于下一个单词。

2 个答案:

答案 0 :(得分:2)

  

你怎么能找到一个良好的起点来平衡   树?

将文件读入元素的向量v

排序矢量v;

a)从中间加载单个树元素=(size / 2)

b)从左半部递归负荷(v [0] .. v [中] -1),

c)从右半部递归负荷(v [中+ 1] .. v [size()]

删除矢量


2014-08-02更新。

以为我会提供一些关于“递归”的见解。将排序后的矢量内容传送到“好”字母中的二叉树的本质。 order ..一个非随机的顺序,它应该在完成时保持(简单二进制)树的平衡。

最坏的情况插入可能会让您进行O(n)搜索。

平衡(简单)二叉树是O(log n)。

     static void buildTree(std::vector< std::string >& v)
        { 
           // validation code ... 

           // create 1st node of tree 
           treeStart = new(TreeNode);
           assert(treeStart);

           // announce
           std::cout << "buildTree(std::vector& v)\n" << std::endl;

           // recurse through vector, invoking insertR() for each element
           buildTreeR(v,
                      0,             // smallest index
                      (v.size()-1)); // biggest index

        }


     // recurse through the vector to determine which element to insert
     static void buildTreeR(std::vector< std::string >& v,
                            size_t si,  size_t bi) // small indx, big indx
        {
           // validation code
           do
           {
              size_t di = bi - si;  // delta index 

              switch (di)
              {

              case 0: // 1 elment
              {
                 treeStart->insertR(v[si]);
              }
              break; 

              case 1: // 2 consecutive elements - i.e. 7-6 = 1,  6 7
              {
                 treeStart->insertR(v[si]);  // left
                 treeStart->insertR(v[bi]);  // right
              }
              break;

              case 2: // 3 consecutive elements - i.e. 3-1 = 2,  1 2 3 
              {
                 size_t m = si + 1;
                 treeStart->insertR(v[m]);   // insert middle

                 treeStart->insertR(v[si]);  // insert left 

                 treeStart->insertR(v[bi]);  // insert right 
              }
              break;               

              default: // 4 or more elements - i.e. 32767-0 = 32767, 
              {
                 size_t delta = (bi - si) / 2;

                 size_t m = si + delta;  // the middle of this range

                 treeStart->insertR(v[m]); // insert middle element 

                 buildTreeR (v, si, m-1);  // recurse on left  
                                           // smallest index thru (middle-1)

                 buildTreeR (v, m+1, bi);  // recurse on right 
                                           // (middle+1) thru biggest index
              }
              break;

              }// switch   

           }while(0);

        } // void buildR(std::vector< std::string >& v, size_t si, size_t bi)

仅供参考 - 在我7岁的戴尔,g ++ v4.8.1,ubuntu 12.04,

性能为32,767项,152,729字节(每个字符串约5个字节)。

  buildTree from vec: 
            duration: 132,013 us
         total bytes: 152,729

此外,使用

调用此向量的种类
 std::stable_sort(v.begin(), v.end());
 // this resulted in a lexicographic sort, probably what you want



 vector    after sort: 
        sort duration: 25,273 us
          total bytes: 152,729
       sizeof(vector): 12
        vector.size(): 32767

存在替代品,更复杂 - AVL树,红黑树等。另一方面,有了这些,您可能会放弃向量和排序。

(表现结果使用-O0)

答案 1 :(得分:0)

特别是如果您的数据已经排序,那么最好不要使用树,而是将单词读取到矢量并执行二进制搜索以找到所需的单词。二进制搜索具有O(log(n))复杂度,就像二叉树一样。构建向量具有O(n)复杂度与树的O(n * log(n))。即使单词没有排序,对数组进行排序也可能比将所有单词插入树中表现更好。使用排序向量进行搜索的优点是内存开销较少,缓存友好性较高,从而提高了性能。