算法导论Part3: 二叉搜索树

1、概念

二叉搜索树性质:设x是二叉搜索树的一个节点,那么:

a) 对x左子树中任意节点y, y.key < x.key

b) 对x右子树种任意节点y, y.key >= x.key

2、数据结构

 1 struct TreeNode
 2 {
 3     TreeNode(int key): left(NULL), right(NULL), parent(NULL), key(key) {};
 4     TreeNode* left;
 5     TreeNode* right;
 6     TreeNode* parent;
 7     int key;
 8 };
 9
10 class Tree
11 {
12 public:
13     Tree(): m_root(NULL) {};
14     TreeNode* minimum(TreeNode* );
15     TreeNode* maximum(TreeNode* );
16     void creat(int keys[], int n);
17     int insert(int key);
18     int remove(int key);
19     TreeNode* search(int key);
20     void walk(TreeNode *root);
21     TreeNode* get_root() const;
22
23 protected:
24     inline TreeNode* node_creat(int key);
25     void transplant(TreeNode* x, TreeNode *y);
26
27 private:
28     TreeNode* m_root;
29 };

3、算法

3.1 遍历

由二叉搜索树的性质,中序遍历的结果为keys的有序排列

1 void Tree::walk(TreeNode *root)
2 {
3     if (root == NULL)
4         return;
5     walk(root->left);
6     cout << root->key << " ";
7     walk(root->right);
8 }

3.2 最大/最小值

 1 TreeNode* Tree::minimum(TreeNode *root)
 2 {
 3     TreeNode *visit = root;
 4     if (visit == NULL)
 5         return NULL;
 6     while (visit->left != NULL)
 7         visit = visit->left;
 8     return visit;
 9 }
10
11 TreeNode* Tree::maximum(TreeNode* root)
12 {
13     TreeNode *visit = root;
14     if (visit == NULL)
15         return NULL;
16     while (visit->right != NULL)
17         visit = visit->right;
18     return visit;
19 }

3.3 查找

 1 TreeNode* Tree::search(int key)
 2 {
 3     TreeNode* visit = m_root;
 4
 5     while (visit != NULL)
 6     {
 7         if (key == visit->key)
 8             return visit;
 9         if (key < visit->key)
10             visit = visit->left;
11         else
12             visit = visit->right;
13     }
14
15     return visit;
16 }

3.4 插入

插入时,必然是插入到某个叶子节点上,而不是两节点之间。

先查找到插入位置,然后插入。

 1 int Tree::insert(int key)
 2 {
 3     TreeNode* z = new TreeNode(key);
 4     TreeNode* x = m_root;
 5     TreeNode* y = NULL;
 6     while (x != NULL)
 7     {
 8         y = x;
 9         if (z->key < x->key)
10             x = x->left;
11         else
12             x = x->right;
13     }
14     z->parent = y;
15     if (y == NULL) // tree is empty
16         m_root = z;
17     else if (z->key < y->key)
18         y->left = z;
19     else
20         y->right = z;
21
22     return 0;
23 }

3.5 删除

删除时,情况较复杂,对于待删除节点z:

IF z.left is NULL

  replace z by z.right

ELSE IF z.right is NULL

  replace z by z.left

ELSE // z 包含左右子树

  找出z的后继y,即key大于z.key的最小节点, y在z的右子树中且y没有左子树

  IF y.parent is z

    replace z by y, 留下y.right

  ELSE

    replace z.right by y,

    replace z by y

 1 // replace x by node y
 2 void Tree::transplant(TreeNode* x, TreeNode *y)
 3 {
 4     if (x->parent == NULL) // x is root
 5         m_root = y;
 6     else if (x->parent->left == x)
 7         x->parent->left = y;
 8     else
 9         x->parent->right = y;
10
11     if (y != NULL)
12         y->parent = x->parent;
13 }
14
15 int Tree::remove(int key)
16 {
17     TreeNode* y = NULL;
18     TreeNode* z = search(key);
19     if (z == NULL)
20         return -1;
21
22     if (z->left == NULL)
23         transplant(z, z->right);
24     else if (z->right == NULL)
25         transplant(z, z->left);
26     else
27     {
28         y = minimum(z->right);
29         if (y->parent != z)
30         {
31             transplant(y, y->right); // replace y by right child
32             // let y be parent of z->right
33             y->right = z->right;
34             y->right->parent = y;
35         }
36         transplant(z, y);
37         y->left = z->left;
38         y->left->parent = y;
39     }
40
41     return 0;
42 }

tips:源码

时间: 2024-10-30 16:39:55

算法导论Part3: 二叉搜索树的相关文章

【算法导论】二叉搜索树

什么是二叉搜索树 顾名思义,一棵二叉搜索树是以一棵二叉树来组织的.这样一棵树可以使用一个链表数据结构来表示,其中每个结点就是一个对象.除了key和卫星数据之外,每个结点还包含属性left.right和p,它们分别指向结点的左孩子.右孩子和双亲.如果某个孩子结点和父结点不存在,则相应属性的值为NIL.根结点是树中唯一父指针为NIL的结点. 二叉搜索树中的关键字总是以满足二叉搜索树性质的方式来存储: 设x是二叉搜索树中的一个结点.如果y是x左子树中的一个结点,那么 y.key <= x.key.如果

算法导论:二叉搜索树

定义: (0)二叉树 (1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值: (2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值: (3)左.右子树也分别为二叉排序树 数据结构定义 public class TreeNode { public int val; public TreeNode left; public TreeNode right; public TreeNode(int val){ this.val = val; this.left = left=null

【算法导论】二叉搜索树的插入和删除

上一篇说了有关二叉树遍历的三种方式,文本将继续探讨如何实现二叉搜索树的插入和删除节点. 在继续之前,我们先来了解两个概念:前驱和后继. 一.后继和前驱 后继:如果所有的关键字互不相同,则一个节点x的后继是大于x.key的最小关键字的节点. 前驱:如果所有的关键字互不相同,则一个节点x的前驱是小于x.key的最大关键字的节点. 如果联系二叉搜索树的性质: 节点的key值总是大于它的左节点(如果存在)的key值并且小于它的右节点(如果存在)的key值.那么我们容易推知:如果一个节点有右子树,它后继即

算法学习9——二叉搜索树

数据结构与算法之二叉搜索树

与链表不同,树是一种非线性的数据结构.树中最常用的是二叉树,二叉树限制了子树的数量,也就是每个结点的子树至多2个,并且这两个子树是有顺序的.而二叉搜索树(二叉查找树,二叉排序树)是指根节点的关键字大于左子树的,而小于右子树,并且,左右子树也是一颗二叉搜索树.也就是说中序遍历一颗二叉搜索树,它的输出是从小到大排序好的. 除了普通的二叉搜索树之外,还有很多关于它的变形. 二叉平衡搜索树,即即是一颗二叉平衡树,也是一颗搜索树,平衡树即任意一个结点的左子树的高度与右子树的高度之差的绝对值不大于1. 红黑

算法导论第十二章 二叉搜索树

一.二叉搜索树概览 二叉搜索树(又名二叉查找树.二叉排序树)是一种可提供良好搜寻效率的树形结构,支持动态集合操作,所谓动态集合操作,就是Search.Maximum.Minimum.Insert.Delete等操作,二叉搜索树可以保证这些操作在对数时间内完成.当然,在最坏情况下,即所有节点形成一种链式树结构,则需要O(n)时间.这就说明,针对这些动态集合操作,二叉搜索树还有改进的空间,即确保最坏情况下所有操作在对数时间内完成.这样的改进结构有AVL(Adelson-Velskii-Landis)

【算法导论】学习笔记——第12章 二叉搜索树

搜索树数据结构支持多种动态集合操作,包括SEARCH.MINIMUM.MAXIMUM.PREDECESSOR.SUCCESSOR.INSRT和DELETE操作等.基本的搜索树就是一棵二叉搜索树.12.1 什么是二叉搜索树1. 二叉搜索树的性质:设x是二叉搜索树中的一个结点.如果y是x左子树中的一个结点,那么y.key<=x.key.如果y是x右子树中的一个结点,那么y.key>=x.key.三种遍历时间复杂度是O(n),这是显然的. 12.1-3 1 void Inorder_Tree_Wal

算法导论(Introduction to Algorithms )— 第十二章 二叉搜索树— 12.1 什么是二叉搜索树

搜索树数据结构支持许多动态集合操作,如search(查找).minmum(最小元素).maxmum(最大元素).predecessor(前驱).successor(后继).insert(插入).delete(删除),这些都是基本操作,可以使用一颗搜索树当做一个字典或者一个优先队列. 12.1.什么事二叉搜索树 二叉搜索树是以一棵二叉树来组织的,可以用一个链表数据结构来表示,也叫二叉排序树.二叉查找树: 其中的每个结点都是一个对象,每个对象含有多个属性(key:该结点代表的值大小,卫星数据:不清楚

【算法导论学习-24】二叉树专题2:二叉搜索树(Binary Search Tree,BST)

一.   二叉搜索树(Binary SearchTree,BST) 对应<算法导论>第12章.相比一般二叉树,BST满足唯一的条件:任意节点的key>左孩子的key,同时<右孩子的key. 1.     节点类: public class BinarySearchTreesNode<T> { private int key; private T satelliteData; private BinarySearchTreesNode<T> parent, l