二叉查找树(BST树)

二叉查找树的特点:

在二叉查找树中左子树上所有结点的数据都小于等于根结点的数据,而右子树上所有结点的数据都大于根结点的数据

 1 //存储结构:
 2 struct node
 3 {
 4     Int data;
 5     node *lchild;
 6     node *rchild;
 7 };
 8
 9 //在建树前根节点不存在:
10 Node *root = NULL;
11
12 //新建结点:
13 node *newNode(int v)
14 {
15     node *Node = new node;
16     Node->data = v;
17     Node->lchild = NULL;
18     Node->rchild = NULL;
19     return Node;
20 }
21
22 //二叉查找树结点的查找、修改:
23 //时间复杂度:O(h) h是二叉查找树的高度
24 void search(node *root,int x,int newdata) // 在这里修改的是root指针指向的内容,所以不需要加引用&
25 {
26     if(root == NULL)
27         return;
28     if(root->data == x)
29         root->data = newdata;
30     if(root->data <= x) search(root->lchild,x,newdata);
31     else if(root->data > x)
32         search(root->rchild,x,newdata);
33 }
34 //二叉查找树的插入:
35 //时间复杂度:O(h) h是二叉查找树的高度
36 void insert(node *&root,int x) // 这里要加引用,是因为修改的是root指针本身
37 {
38     if(root == NULL)
39     {
40         root = newNode(x);
41         return root;
42     }
43     if(x<=root->data)   // 生成二叉查找树
44         insert(root->lchild,x);
45     else
46         insert(root->rchild,x);
47 }
48
49 //二叉查找树的创建:
50 node *create(int data[],int n)
51 {
52     node *root = NULL;
53     for(int i=0;i<n;++i)
54         insert(root,data[i]);
55     return root;
56 }

二叉查找树的删除
一般有两种常见做法,时间复杂度都是$O(h)$,h是二叉查找树的高度。为了保证删除之后仍然是二叉查找树。
一种方法是以树中比删去数小而又最大的结点(称为该结点的前驱)覆盖删去数,再删去该结点。
另一种则是以树中比删去数大而又最小的结点(称为该结点的后继)覆盖删去数,再删去该结点。

 1 node *findMax(node *root)
 2 {
 3     while(root->rchild != NULL)
 4         root = root->rchild;
 5     return root;
 6 }
 7
 8 node *findMin(node *root)
 9 {
10     while(root->lchild != NULL)
11         root = root->lchild;
12     return root;
13 }
14
15 void deleteNode(node *&root,int x) // 加引用是因为要修改指针本身(删除)
16 {
17     if(root == NULL) // 树中没有x这个数据
18         return;
19     if(root->data == x)
20     {
21         if(root->lchild==NULL && root->rchild==NULL)  //没有左右子树,直接删除
22         {
23             root = NULL;
24         }
25         else if(root->lchild!=NULL) // 有左子树,则找前驱来覆盖root
26         {
27             node *pre = findMax(root->lchild);
28             root->data = pre->data;
29             deleteNode(root,pre->data);
30         }
31         else if(root->rchild!=NULL) // 有右子树,则找后继来覆盖root
32         {
33             node *next = findMin(root->rchild);
34             root->data = next->data;
35             deleteNode(root,next->data);
36         }
37     }
38     else if(root->data > x)  // 根据二叉查找树特性继续找x
39     {
40         deleteNode(root->lchild,x);
41     }
42     else
43     {
44         deleteNode(root->rchild,x);
45     }
46 }

这段代码还可以进行优化,例如在找到欲删除结点root的后继结点next后,不进行递归删除,而通过这样的手段直接删除该后继:假设结点next的父亲结点是结点S,显然next是结点S的左孩子,那么由于结点next一定没有左子树,便可以直接把结点next的右子树代替结点next成为S的左子树,这样就删去了结点next。前驱同理。但这个优化需要在结点定义中额外记录每个结点的父亲结点地址。
而且我们可以发现上面的二叉查找树删除操作总是优先删除前驱(或者后继),这样容易使树的左右子树高度不平衡,最终使二叉查找树退化成一条链。
有两种方法解决这个问题:1.每次交替删除前驱或者后继 2.记录每个节点子树的高度,并且总是优先在高度较高的子树里删除结点。(也是平衡二叉树(AVL树)的原理)

二叉查找树的一个性质:因为二叉查找树本身的特点(左<=根<右),因此对二叉查找树进行中序遍历,遍历的结果是有序的。

原文地址:https://www.cnblogs.com/kachunyippp/p/10256805.html

时间: 2024-10-02 15:00:13

二叉查找树(BST树)的相关文章

二叉查找树(BST),平衡二叉查找树(AVL),红黑树(RBT),B~/B+树(B-tree)的比较

http://www.iteye.com/topic/614070 此少侠总结的特棒,直接收藏了. 我们这个专题介绍的动态查找树主要有: 二叉查找树(BST),平衡二叉查找树(AVL),红黑树(RBT),B~/B+树(B-tree).这四种树都具备下面几个优势: (1) 都是动态结构.在删除,插入操作的时候,都不需要彻底重建原始的索引树.最多就是执行一定量的旋转,变色操作来有限的改变树的形态.而这些操作所付出的代价都远远小于重建一棵树.这一优势在<查找结构专题(1):静态查找结构概论 >中讲到

二叉查找树BST 模板

二叉查找树BST 就是二叉搜索树 二叉排序树. 就是满足 左儿子<父节点<右儿子 的一颗树,插入和查询复杂度最好情况都是logN的,写起来很简单. 根据BST的性质可以很好的解决这些东西 1.查询值 int Search(int k,int x) { if(x<a[k].key && a[k].l) Search(a[k].l,x); else if(x>a[k].key && a[k].r) Search(a[k].r,x); else retur

BST树

http://www.cnblogs.com/bizhu/archive/2012/08/19/2646328.html 4. 二叉查找树(BST) Technorati 标记: 二叉查找树,BST,二叉查找树合并 4.1 BST数据结构定义 使用C++语言,如果需要使用BST,那么不用重新造轮子了,C++语言里的map, set等STL容器应该可以满足需求了(虽然STL里这些容器大多是以红黑树作为其底层实现),如果你需要使用小/大根堆(也叫优先队列,特殊的.自平衡的BST),STL也能满足你的

详解二叉查找树(BST)

详解二叉查找树(BST) 本篇随笔简单讲解一下数据结构--二叉查找树(\(Binary\,\,Sort\,\,Tree,BST\)),(后文的"二叉查找树"一词均用\(BST\)代替). BST的概念 首先,\(BST\)是一棵二叉树. 它的定义是,根节点左子树全部严格小于根节点,右子树大于等于根节点,并且,左右子树都是\(BST\). 很好理解,很明朗很简单的定义. 可以看出,这是一个通过递归方式定义的数据结构,所以,它的诸多操作自然要用到递归. BST的功能 我们可以看出来,这个二

POJ 2309 BST 树状数组基本操作

Description Consider an infinite full binary search tree (see the figure below), the numbers in the nodes are 1, 2, 3, .... In a subtree whose root node is X, we can get the minimum number in this subtree by repeating going down the left node until t

有序单链表转BST树+时间复杂度要求O(n)

问题描述 针对有序的数组或链表,要转为相对平衡的BST树时,通常有多种做法. 1. 对于有序的数组A,转为BST时,取数组中间元素A[m],转为根,然后递归转换A[1..m-1], A[m+1 .. n]即可.时间复杂度 T(n) = 2 * T(n/2) + O(1),得出T(n) = O(n) 2. 针对有序的链表,如果依据上述方法,也可以进行.然而要取到A[m]的话,则需要遍历n/2长度的数组,因此需要额外O(n)的时间来取到A[m].因此时间复杂度为T(n) = 2 * T(n/2) +

BST树遍历O(n)时间复杂度+O(1)空间复杂度

问题描述 BST树的遍历问题常常遇到,前序.中序.后序等.如果用递归的话,是非常方便的,其时间复杂度是O(n),空间复杂度是O(log n)级别.PS:stackoverflow问答网站上有一个问题指出,这类问题的复杂度不应该直接说是O(log n),因为编译器会进行一些优化,比如修改成尾递归等.不过我们这里暂时不考虑优化,从程序逻辑上来讲,BST递归遍历认为是O(log n)的复杂度. OK,那么如果改进遍历方法,使得空间复杂度只有O(1)呢? 解决方案 解决方法中,是针对每个叶节点,将其右指

BST树、B树、B+树、B*树

1. BST树 即二叉搜索树: 1.所有非叶子结点至多拥有两个儿子(Left和Right): 2.所有结点存储一个关键字: 3.非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树: 如: B树的搜索,从根结点开始,如果查询的关键字与结点的关键字相等,那么就命中:否则,如果查询关键字比结点关键字小,就进入左儿子:如果比结点关键字大,就进入右儿子:如果左儿子或右儿子的指针为空,则报告找不到相应的关键字. 如果B树的所有非叶子结点的左右子树的结点数目均保持差不多(平衡),那么B树的

A1135 | 红黑树判断:审题、根据“先序遍历”和“BST树”的条件生成后序遍历、递归判断

对A1135这题有心里阴影了,今天终于拿下AC.学习自柳神博客:https://www.liuchuo.net/archives/4099 首先读题很关键: There is a kind of balanced binary search tree named red-black tree in the data structure------ 红黑树首先应该是一棵BST树,不然从何谈起维护二分查找结构? 所以第一步就应该根据先序遍历以及BST树的特性来判断是否是一棵BST树,然后根据这两个条