树 - (二叉查找树,红黑树,B树)-二叉查找树 BST
来源:互联网 发布:uber打车软件下载 编辑:程序博客网 时间:2024/05/17 06:09
二叉查找树 BST
查找树是一种数据结构,支持动态集合操作。在二叉查找树上执行基本操作的时间与树的高度成正比。对已n个节点的完全二叉树,各种操作的最坏情况运行时间O(logn)
. 但是如果二叉查找树退化成含n个节点的线性链,各种操作的最坏情况运行时间O(n)
。 一颗随机构造的二叉查找树的操作平均时间是O(logn)
.
性质:
对于任何节点x
,其左子树的关键字最大不超过key[x]
,其右子树的关键字最小不小于key[x]
. 因此可以使用中序遍历算法,输出有序的树的所有关键字。
不同的二叉查找树可以表示同一组值。
查找二叉查找树的时间可以在O(h) = O(logn)
的时间内完成。
关于二叉树的一些数学性质:
1. 在二叉树的第i层上至多有2(i-1)个节点(i>=1)
2. 深度为k的二叉树至多有2k-1个节点
3. 对于任何一棵二叉树T,如果其叶子节点数为n0,度为2的节点数为n2,则n0=n2+1.
操作及代码
// 返回指向包含关键字k的节点的指针 public TreeNode search(TreeNode root, int k){ if(root==null){ return null; } if(root.val == k) return root; if(root.val > k){ return search(root.left,k); } else return search(root.right,k); } //非递归 - 返回指向包含关键字k的节点的指针 public TreeNode searchIterative(TreeNode root, int k){ while(root!=null){ if(root==null || root.val == k){ return root; } if(root.val>k) { root = root.left; } else root = root.right; } return root; } // 返回最小值节点 public TreeNode minimal(TreeNode root){ if(root ==null){ return null; } while(root.left!=null){ root = root.left; } return root; } // 返回最大值节点 public TreeNode maximal(TreeNode root){ if(root ==null){ return null; } while(root.right!=null){ root = root.right; } return root; }
插入
插入:从根结点开始,沿树下降。指针 x 跟踪这条路径,而 y 始终指向 x 的父结点。根据 key[z] 与 key[x] 的比较结果,决定向左向右转。直到 x 成为 NIL 为止。这个 NIL 所占位置及我们想插入 z 的地方,y 即为 z 的父结点。
// 插入 public TreeNode insert (TreeNode root, TreeNode x){ TreeNode p = root; TreeNode y = new TreeNode(); if(p==null){ root = x; return root; } while(p!=null) { if(p.val >= x.val){ y = p; p = p.left; } else{ y = p; p =p.right; } } // 树本来没有节点的时候 x.parent = y; if(x.val <= y.val){ y.left = x; } else{ y.right = x; } return root; }
完整代码
package test;/** * @author 作者 MarcoSpring: * @version 创建时间:2012-8-3 上午10:14:51 二叉搜索树 */public class Tree {public TreeNode root;// 根节点// 查找节点public TreeNode search(int Key) {TreeNode node = root;// 首先定义一个节点让其指向根,在下面的循环中// 只要节点值不等于要查找的节点值就进入循环如果没有找到则返回nullwhile (node.keyValue != Key) {if (Key < node.keyValue) { // 如果要查找的值小于节点值则指向左节点node = node.leftNode;} else { // 否则指向右节点node = node.rightNode;}if (node == null) { // 如果节点为空了则返回nullreturn null;}}return node;}
插入节点,递归方式private TreeNode insert(x,TreeNode root){if(t==null)return new TreeNode(x,null,null);else if(x<root.data){root.left=insert(x,root.left);}else if(x<root.data){root.right=insert(x,root.right);}else ;return root;}
实际用途
在搜索应用中使用,尤其是数据频繁插入和删除等等更改操作。比如set
和map
。
虽然BST的操作用数组完全可以实现,但是数组只适合那种write once, read many times的操作。
然而当要进行操作诸如 插入
,删除
,交换
的时候,BST的性能远远超过了数组。BST 是 node based 数据结构,
而数组是 contiguous chunk of memory, 即基于连续内存的数据结构,插入
,删除
,交换
要BST更好。
举个例子
BST和哈希表有何区别? 存储手机上的通讯录用哪个数据结构好?
哈希表可以O(1)
时间进行搜索
和插入
。
BST 可以O(nlogn)
时间进行搜索
和插入
。 在这一点BST稍慢。
但是二者最大的区别是哈希表是一个无序的DS,while, BSTs 是有序的DS。
当设计手机通讯录这种对内存要求很高的应用时候,需要考虑存储空间而且手机通讯录需要元素有序。哈希表无序,需要额外的空间和时间去排序,而BST就不需要额外的空间去
排序,而且在n<5000
条记录的时候,BST的O(nlogn)
足够快。
所以应该采用BST。
- BST二叉查找树
- BST二叉查找树
- 二叉查找树 BST
- BST二叉查找树
- 二叉查找树BST
- 二叉查找树BST
- BST二叉查找树
- BST-二叉查找树
- 二叉查找树(BST)
- 二叉查找树(BST)
- 二叉查找树(BST)
- 二叉查找树(BST)
- 二叉查找树(BST)
- 二叉查找树(BST)
- 二叉查找树(BST)
- 二叉查找树(BST)
- 二叉查找树(BST)
- 二叉查找树(BST)
- Android 实例:返回上个Activity 数据
- golang简单实现Websocket
- 设计模式(Design Patterns)
- 爆点TV的成功之路
- BP神经网络(一) --- 感知器
- 树 - (二叉查找树,红黑树,B树)-二叉查找树 BST
- 正则表达式限制输入框只能输入数字
- Redis在Windows上的配置方案
- OSX系统修改$PATH环境变量
- Ubuntu 用户管理
- java生成32位字符串
- 调一次ajax执行两次action或是还有执行其他的action
- Jekyll解决Deprecation:you haven't included the `jekyll-paginate` gem
- Palindrome Number