你也许用过传统的双向链表,对于这样的链表而言,在查找时的平均效率理论上应该是遍历一半以上的链表数据。而通过二叉数的方法则可以大大提高其排序的效率,如果你对此感兴趣的话,请耐心看完此文,我发现可以在百度上找到很多,但基本都是有错误的,而且有一些讲的很复杂(通常我认为,不能把问题讲简单的人都是不理解问题本质的)。这里我不做过深的讨论,只做一种可行的较简单的实现,当然我相信如果您看懂了此文,对于更复杂的实现方法,您完全可以自由去发挥您的智慧,呵呵。
Root
Left Right
LeafA LeafB LeafC
如上所示,我们称最上面的那个结点为根,根(Root)的左右带有子结点的为子树(SubTree),对于不带有子结点的如LeafA称之为叶,呵呵,说了这么多,这些名字其实不是因为要定义什么概念而必要的,只是这么称呼是不是能让你远远的一看,想一想,是不是像一棵倒着的树呢?
下面我们进入正题,我将讲一下数据结构、统计、查找、遍历及插入,如果你已经百度过,前几个基本上都没有什么大的问题,你可以直接跳过看最后一个内容:
1.
数据结构
struct TreeNode{
string item;
TreeNode *left;
TreeNode *right;
TreeNode(string str){
item = str;
left = NULL;
right = NULL;
}
};
2. 统计
这个函数用于统计root下的项数,一般都是用递归实现,如下:
int CountNodes(TreeNode *root){
// count the nodes in the binary tee
if(root == NULL){
return 0;
}
else{
return (1 + CountNodes(root->left)
+ CountNodes(root->right));
}
}
3. 查找
这个函数用于查找二叉树并判断所给定的项是否已经存在,可以用递归与循环两种方法实现,原理是我们已知Root的left 小于 Root 小于 Root的right,所以依据此原则,小的查左边,大的查右边:
bool treeContains( TreeNode *root, string item){
if(NULL == root){
return false;
}
else if( root->item == item){
return true;
} else if(root->item < item){
return treeContains( root->right,
item );
} else{
return treeContains( root->left,
item );
}
}// end treeContains
bool treeContainsNonRecursive(TreeNode *root, string item){
// return true if item is one of the
items in the binary sort tree
TreeNode *runner;
ruuner = root;
while(1){
if(runner == NULL){
return false;
} else if(runner->item == item){
return true;
} else if(runner->item < item){
runner = runner->right;
} else{
runner = runner->left;
}
}
}// end treeContainsNorRecursive
4. 遍历
此函数实现从小到大遍历,原理与查找类似,但根据处理位置的不同,我们可以有以下很多种方式进行遍历,典型的有三种,网上很多人译成中文叫前序中序后序,容易误解,我就不译了叫preorder traversal, postorder traversal, inorder traversal。
Preorder: 顺序为先root, 再left再right
Postorder: 顺序为先left, 再right 再root
Inorder: 顺序为先left,再right,再root,也就是从小到大的正常的顺序
void preorderPrint( TreeNode *root){
If(root != NULL){
Cout << root->item << “ “;
preorderPrint( root->left );
preorderPrint( root->right );
}
}// end preorderPrint
Void postorderPrint( TreeNode *root){
If(root != NULL){
postorderPrint( root->left );
postorderPrint( root->right );
cout << root->item << “ “;
}
}//end postorderPrint
Void inorderPrint( TreeNode *root)
{
If(root != NULL){
inorderPrint( root->left );
count << root->item << “ “;
inorderPrint(root->right);
}
}
5. 插入
此函数正是很多文章中未提的,理论上如果是完全随机的数据插入,则理想情况下树的两边是平衡的,此算法也被优化
void treeInsert(TreeNode *&root, string newItem){
if( NULL == root ){
root = new TreeNode( newItem );
return;
}
else if( newItem < root->item){
treeInsert( root->left, newItem );
}
else{
treeInsert( root->right, newItem);
}
}// end treeInsert
PS: 谢谢你的浏览,有不正之处欢迎指正

被折叠的 条评论
为什么被折叠?



