在二叉搜索树的根进行插入

对二叉树可以进行底部插入,也可以进行根部插入,使得每个新节点插入到树根。

假设被插入数据项的关键字大于树根的关键字。我们可以这样着手建造一棵新树:把新数据项放入一个新的根节点,把原有根作为左子树,原有根的右子树作为新树的右子树。然而右子树也许包含一些较小的关键字,所以我们必须做更多的工作才能完成这次插入。类似地,如果被插入数据项的关键字小于树根的关键字,但大于树根左子树的关键字,我们依旧可建造一棵新数据项处于树根的新树;但如果左子树包含一些较大的关键字,也必须做更多的工作。

更多的工作可以通过基于旋转的递归解决方案。一次旋转允许我们使一棵树中根和其中一个根的子孙互换角色,但仍然保持关键字之间的次序。右旋转使得原来的根成为新根(根原来的左子树)的右子树;左旋转使得原来的根成为新根(根原来的右子树)的左子树。

1 void rotR(link& h)
2 {link x = h->l; h->l = x->r; x->r = h; h = x;}
3 
4 void rotL(link& h)
5 {link x = h->r; h->r = x->l; x->l = h; h = x;}

在实践中,根插入方法的一个优点是新近插入的关键字接近树顶部。而对新近插入关键字的搜索命中的开销也因此很可能低于标准方法的开销。这个性质十分重要,因为许多应用在它们的搜索和插入操作中恰好有这类动态混合。一个符号表可能包含大量数据项,但一大部分的搜索操作也许只访问最近插入的数据项。例如在一个商业事务处理系统中,当前活动的事物可以逗留在顶部附近并可迅速处理,而无须访问已遗失的旧事物。根插入方法自动给予数据结构这种性质以及类似性质。

 1 private:
 2     void insertT(link& h, Item x)
 3     { if (h == 0) {h = new node(x); return;}
 4        if (x.key() < h->item.key())
 5            { insertT(h->l, x); rotR(h);}
 6        else {insertT(h->r, x); rotL(h);}
 7      }
 8 public:
 9     void insert(Item item)
10     {insertT(head, item);}

 

posted @ 2020-05-12 21:11  ~宁静致远~  阅读(302)  评论(0编辑  收藏  举报