我有一个包含大量单词的文本文件,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
编辑:如果我的插入方法单词正确,我相信在读入按字母排序的文件后,它应该是一个\行,因为每个单词都大于下一个单词。
答案 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))。即使单词没有排序,对数组进行排序也可能比将所有单词插入树中表现更好。使用排序向量进行搜索的优点是内存开销较少,缓存友好性较高,从而提高了性能。