二叉树排序的正解

  你也许用过传统的双向链表,对于这样的链表而言,在查找时的平均效率理论上应该是遍历一半以上的链表数据。而通过二叉数的方法则可以大大提高其排序的效率,如果你对此感兴趣的话,请耐心看完此文,我发现可以在百度上找到很多,但基本都是有错误的,而且有一些讲的很复杂(通常我认为,不能把问题讲简单的人都是不理解问题本质的)。这里我不做过深的讨论,只做一种可行的较简单的实现,当然我相信如果您看懂了此文,对于更复杂的实现方法,您完全可以自由去发挥您的智慧,呵呵。

 

                    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.       查找

这个函数用于查找二叉树并判断所给定的项是否已经存在,可以用递归与循环两种方法实现,原理是我们已知Rootleft 小于 Root 小于 Rootright,所以依据此原则,小的查左边,大的查右边:
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, leftright

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: 谢谢你的浏览,有不正之处欢迎指正

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值