5.1.1 二叉搜索树
来源:互联网 发布:上瘾 顾海 知乎 编辑:程序博客网 时间:2024/06/16 16:58
5.1.1 二叉搜索树
二叉树是指任何节点最多只有两个子节点;而二叉搜索树(也称二叉查找树)的规则如下:
- 对数时间的元素插入和访问;(O(h) == O(lgn))
- 任何节点的
键值
一定大于其左子树
中的每一个节点的键值,一定小于其右子树
节点的键值。
根据上面的定义,判断下图中的树哪个不是二叉搜索树:
左边的是,右边的不是;因为根节点的键值6小于左子树中其中一个节点的键值7。请记住:从根节点一直往左(右)走,直到无左(右)路可走,即得最小(大)元素。如下图所示:
5.1.2 操作
二叉搜索树的常用操作有:查找最小/大元素,插入及删除元素。下面给出具体的操作步骤。注意:这里以int型数据作为研究对象,当然可以写成模板,这里一切从简,以聚焦于算法的原理。树中存放节点数据的结构体如下:
struct Node{ int key; // 以int型数据为例 Node *Left, *Right; // 指向左右子节点的指针};
每个节点的数据结构包含一个int型键值,两个分别指向左、右子节点的节点指针,当不存在左(或右)子节点时,Left(或Right)为NULL。
5.1.2.1 查找最小节点
要在一颗二叉搜索树中查找最大值或最小值,一直往右或往左走即可。这里只给出查找最小节点的程序,查找最大节点类似,下面代码中的Left换成Right即可;注意边界条件的判断也相当重要,尤其在面试时,不可忘记!!!
// 递归实现Node* findMin(Node* T){ // 边界条件判断 if(T == NULL) return NULL; else if(T->Left == NULL) return T; else return findMin(T->Left);}// 非递归实现Node* findMin(Node* T){ if(T == NULL) return NULL; while(T->Left != NULL) { T = T->Left; } return T;}
这里找到了最小的节点(Node* node),那么结构体中的数据轻而易得(node->key)!
5.1.2.2 插入
插入新元素到二叉搜索树中的规则很简单:从根节点开始,遇到键值大的(即新元素的值<节点的键值)往左走,遇到键值小的往右走。
// 递归实现Node* insert(Node* T, int x){ if(!T)// T == NULL {// 空树->构造一个节点 T = malloc(sizeof(Node)); if(T){ T->key = x; T->Left = NULL; T->Right = NULL; return T; }else{ //FetalError("Out of space!"); } } if(x < T->key) // 向左走 insert(T->Left, x); else if(x > T->key) // 向右走 insert(T->Right, x); return T; }// 非递归实现Node* insert(Node* T, int x){ if(!T)// T == NULL {// 空树->构造一个节点 T = malloc(sizeof(Node)); if(T){ T->key = x; T->Left = NULL; T->Right = NULL; return T; }else{ //FetalError("Out of space!"); } } while(x != T->key) { if(x < T->key) T = T->Left; else T = T->Right; if(!T){// 判断是否到达尾端 T = malloc(sizeof(Node)); T->key = x; T->Left = T->Right = NULL; break; } } return T;}
5.1.2.3 删除
图5-6是二叉搜索树的元素移除操作图解。欲删除旧节点A,有两种情况:
- 情形1:节点A(当前根节点)只有一个子节点。即要么有左子节点,要么有子节点;那么,仅需把该子节点连至A节点的父节点,而后再删除节点A;
- 情形2:节点A(当前根节点)有两个子节点。根据二叉搜索树的性质,左子树所有节点的键值 < 根节点的键值 < 右子树所有节点的键值;那么,欲删除旧节点A,需找到右子树中的最小元素节点(使用findMin函数),而后更新旧节点A的键值(不需要更新指向
左
子节点的指针),最后递归调用delete函数删除右子树的最小元素的节点并更新旧节点A的右子树的根节点(A->Right)。
程序如下:
// 《数据结构和算法分析——C语言描述》,该方法永远返回根节点Node* Delete(Node* T, int x){ Node* tmpNode; // 依然是边界条件判断 if(!T) return NULL; else{// 先找到要删除元素的节点 if(x < T->key) T->Left = delete(T->Left, x); else if(x > T->key) T->Right = delete(T->Right, x); else{// 找到,要删除的节点为T if(T->Left && T->Right){// 2个孩子 tmpNode = findMin(T->Right);// 复制一份 T->key = tmpNode->key; T->Right = Delete(T->Right, T->key); }else{ // 0或1个孩子 tmpNode = T; // 复制一份 if(!T->Left) T = T->Right; else if(!T->Right) T = T->Left; free(tmpNode); } } } return T;}
阅读全文
0 0
- 5.1.1 二叉搜索树
- 最优二叉搜索树1
- 查找(1) 二叉搜索树
- 【二叉搜索数】HDU3791二叉搜索树
- 二叉树--二叉搜索树
- 【二叉树】二叉搜索树
- 二叉树- 二叉搜索树
- 【搜索树】二叉搜索树
- 二叉搜索树BSTree
- 二叉搜索树
- 二叉搜索树
- 二叉搜索树
- 最优二叉搜索树
- 二叉搜索树
- 二叉搜索树
- HDOJ3791 二叉搜索树
- 二叉查找树搜索
- 二叉搜索树
- Linux 应用开发
- ocp Oracle.1z0-053 711--23
- Python学习15_霍夫线变换
- 如何适配手机端
- 大数据常见问题
- 5.1.1 二叉搜索树
- Lumen 框架路由访问一直报404错误
- 常用Linux命令
- fastjson相互转换
- Java对象的创建过程
- jQuery中keyup与keydown事件的用法
- mfc非模态对话框Child窗口CEdit控件获取不到焦点问题
- 不允许保存更改。您所做的更改要求删除并重新创建以下表。您对无法重新创建的标进行了更改或者启用了“阻止保存要求重新创建表的更改"选项。
- Bug解决方案:org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 8; 不允许有匹配 "[xX][mM][lL]" 的处理指令目标