二叉搜索树
来源:互联网 发布:caffe matlab可视化 编辑:程序博客网 时间:2024/06/05 04:12
概述:
二叉搜索树中的关键词总是以满足二叉搜索树性质的方式来存储:
设x是二叉搜索树中的一个结点。如果y是x左子树中的一个结点,那么y.key<=x.key。如果y是x右子树中的一个结点,那么y.key>=x.key。
Notes:不同于一般二叉树,二叉搜索树的顺序与结点内容即key值有关,而一般二叉树对相应结点的key值没有要求,故若要对一般二叉树进行遍历,则要排序,因此才有常见的先序,中序,后序三种遍历方式
这样一棵树可以使用一个链表数据结构来表示。
对二叉搜索树的基本操作有:
查找(基于关键词、最小值、最大值、后继、前驱)、插入(考虑空树情况)、删除
(时间复杂度均为O(h), h为树的高度)
代码实现
#include<stdio.h>#include<stdlib.h>typedef int ElemType;typedef struct BiTree{//也即三叉链表 二叉链表少了双亲域 ElemType key;//结点值 struct BiTree *left;//左孩子 struct BiTree *right;//右孩子 struct BiTree *p;//双亲}BiTNode,*BiTree;/*基于关键词的查找*///递归表示BiTree Search_BST(BiTree T, ElemType k){ if (T != NULL&&T->key != k) { if (k < T->key) return Search_BST(T->left,k); else return Search_BST(T->right,k); } return T;}//迭代表示BiTree Interative_Search_BST(BiTree T, ElemType k){ while (T != NULL&&T->key != k) { if (k < T->key) T = T->left; else T = T->right; } return T;}/*最大关键字元素和最小关键字元素的查找*/BiTree Tree_Minimum(BiTree T){ while (T->left != NULL)//找到最左下的元素 T = T->left; return T;}BiTree Tree_Maximum(BiTree T){ while (T->right != NULL)//找到最右下的元素 T = T->right; return T;}/*对某结点的后继和前驱的查找*/BiTree Tree_Successor(BiTree T)//查找后继{ if (T->right != NULL)//T有右孩子,返回右子树的最小值 return Tree_Minimum(T->right); BiTree y; y = T->p;//y为T的双亲 while (y != NULL&&T == y->right)//直到找到一个结点是这个结点的双亲的左孩子 返回这个双亲 { T = y; y = y->p; } return y;}BiTree Tree_Predecessor(BiTree T)//查找前驱{ if (T->left != NULL) return Tree_Maximum(T->left); BiTree y; y = T->p; while (y != NULL&&T == y->left) { T = y; y = y->p; } return y;}/*二叉搜索树的插入*///note:要对搜索树结构进行修改void InsertBST(BiTree &T, ElemType e)//传入二叉树的根结点地址 note:《算法导论》传的是T.root 说明定义了另一个结构体存树的相关信息 如根结点地址 结点数等{ BiTree z, x, y=NULL; //对新增结点进行初始化,现在要修改的是它的双亲和它双亲的left或right z = (BiTree)malloc(sizeof(BiTNode)); if (z != NULL)//空间申请成功 { z->key = e; z->left = z->right=NULL; } x = T; while(x != NULL) { y = x; if (z->key < x->key)//z应该插入到左半部分 x = x->left; else x = x->right; }//循环跳出后 x=NULL, x的位置即z要插入的位置 y的位置为z的双亲的位置 //下面处理z和y的关系 z->p = y; if (y = NULL)//说明是空树 T = z;//新插入的z即为根结点 else if (z->key < y->key)//z为y左孩子 y->left = z; else y->right = z;}/*这个函数用一个以v为根的子树来替换一个以u为根的子树,二叉树的删除操作要用到*/void Transplant(BiTree &T, BiTree u, BiTree v){ if (u->p == NULL)//u没有双亲,说明u为根结点 T = v; else if (u->p->left == u)//若u是其双亲的左子树 u->p->left = v; else u->p->right = v; if (v != NULL)//要考虑v是否为空 v->p = u->p;}/*对二叉树的删除操作*/void DeleteBST(BiTree &T, BiTree z)//以T为根结点的二叉搜索树中删除结点z{ if (z->left == NULL)//第一种情况:要删除的结点没有左孩子 包含了z只有右孩子和右孩子为NULL即z没有孩子的情况 ,z右孩子代替z Transplant(T, z, z->right); else if (z->right == NULL)//第二种情况:z有且仅有非NULL左孩子(因为左孩子为NULL则说明没有孩子,这种情况上面已经包含了)z左孩子代替z Transplant(T, z, z->left); else { BiTree y = Tree_Minimum(z->right); if (y != z->right)//若z的右孩子不是z的后继 说明以右孩子为根的子树最小的那个结点才是z的后继 这个时候这个结点一定没有左孩子!!! { Transplant(T, y, y->right);//用y自己的右孩子来替代y // y->p = z->p;//???这一步不用吗???不用 因为后面还要将y Transplant到z 故只用处理好p的子树部分即可 y->right = z->right;//并置y为z的右孩子的双亲 y->right->p = y; }//处理完以后继结点y为根的子树后(包含本来y就是z的右孩子的情况) Transplant(T, z, y); y->left = z->left; y->left->p = y; }}
notes:
1.查询二叉搜索树,对于大多数计算机,用迭代方式比用递归效率要高得多。
2.《算法导论》中函数传入的是T.root 应该有个类似下面形式的结构体定义,T是Tree类型的变量,我的函数中传入的T默认是根结点地址。
typedef struct{ BiTree root;//根结点地址 int nodenum;//结点数量 //其他信息,如树的类型(二叉搜索树,红黑树,AVL树,B-/B+树)blablabla}Tree;
0 0
- 【二叉搜索数】HDU3791二叉搜索树
- 二叉树--二叉搜索树
- 【二叉树】二叉搜索树
- 二叉树- 二叉搜索树
- 【搜索树】二叉搜索树
- 二叉搜索树BSTree
- 二叉搜索树
- 二叉搜索树
- 二叉搜索树
- 最优二叉搜索树
- 二叉搜索树
- 二叉搜索树
- HDOJ3791 二叉搜索树
- 二叉查找树搜索
- 二叉搜索树
- 二叉搜索树
- BST 二叉搜索树
- 二叉搜索树
- Fedora 25安装后配置
- C#中基于GDI+(Graphics)图像处理系列之文字或者图片水印(透明、任意角度旋转)
- java语言基础—学习笔记—数组
- Hive高级查询(group by、 order by、 join等)
- 关于MyEclipse hot code replace fail 问题
- 二叉搜索树
- OAF 系列教程 四 新增CREATE
- 登录安全性 一天内连续输入密码错误3次,第二天才能登录(过了当天凌晨24点),实现原理
- shell简单处理mysql查询结果
- Spring事物的传播特性and隔离级别
- UML依赖与关联,聚合和组合
- JavaWeb-3-web服务启动时加载类中的某个方法配置(Spring mvc模式下)
- js笔记二:node.js的npm使用理解
- 简易ajax天气渲染