二查排序树
来源:互联网 发布:德国禁止儿童手表知乎 编辑:程序博客网 时间:2024/05/17 20:31
二叉排序树(Binary Sort Tree),又称为二查搜索树。它要么是一颗空树,要么是符合性质的二叉树
- 若它的左子树不为空,那么左子树上的所有结点的值均小于它的根结点的值
- 若它的右子树不为空,那么右子树上的所有结点的值均大于它的根结点的值
- 它的左右子树也分别为二叉排序树
以上性质就造成了左结点<根结点<右结点,那么可以想象一下,如果对二叉排序树进行中序遍历,很明显,我们得到的是一个递增的序列。我们可以根据这个,来判断自己建立的二叉排序树的正确性。需要说明的是,二叉排序树虽然带排序俩字,但却不是为了排序,而是为了提高查找和插入删除的效率。
接下来,我们看一下,二叉排序树的查找是如何实现的。首先给出二叉树的结点结构体
//二叉树结点结构定义typedef struct BSTNode{int m_data;BSTNode *Lchild,*Rchild;}BSTNode,*BiTree;
二叉排序树查找代码如下
//在二查搜索树中查找特定的值,返回值在树中的地址//递归查找树pRoot中是否存在value//指针pfather指向pRoot的双亲,当pRoot是开始的跟结点时,值为NULL//指针pValue,指向找到value的结点,找不到则指向最后一个结点bool SearchBST(BiTree pRoot,int value,BiTree pfather,BiTree *pValue){if (!pRoot) //当最后发现value不存在时,pfther指向最后一个结点{*pValue = pfather;return false;}else if (value == pRoot->m_data) //等于根结点,返回true{*pValue = pRoot;return true;}else if (value < pRoot->m_data) //比根结点小,递归左子树查询{SearchBST(pRoot->Lchild,value,pRoot,pValue);}else SearchBST(pRoot->Rchild,value,pRoot,pValue); //递归右子树查询}以上代码很好理解,接下我们看一下如何对二叉排序树进行插入操作。
//向二叉排序树中插入一个元素value//*pRoot代表一颗二叉排序树bool insertBST(BiTree * pRoot, int value){BiTree p = NULL; //用于接收返回的查找的结点地址或路径中最后一个结点地址if (!SearchBST(*pRoot,value,NULL,&p)) //二叉排序树中不能有重复的值{BiTree s = new BSTNode();s->m_data = value;s->Lchild = NULL;s->Rchild = NULL;if (NULL == *pRoot) //如果传过来的是一颗空树{*pRoot = s;}else if (value < p->m_data) //比最后一个结点小,放左边{p->Lchild = s;}elsep->Rchild = s; //否则放右边return true;}else{cout<<"invalid value"<<endl;return false;}}插入有了,那么创建一颗二叉排序树的可想而知了
//创建二叉排序树//state用于判断上一次插入是否成功,不成功返回bool creatBinarySortTree(BiTree *pRoot,int *array, int size){bool state = true;for (int i = 0;(i < size)&&state; i++){state = insertBST(pRoot, array[i]);}return state;}
//销毁二查搜索树void DestoryBST(BiTree pRoot){if(NULL != pRoot){DestoryBST(pRoot->Lchild); //释放左子树DestoryBST(pRoot->Rchild); //释放右子树delete pRoot;}}好了,至此我们创建了一棵二叉排序树,可以对它进行查找,插入操作了,那么问题来了,我要是想对它进行删除怎么办?对于二叉排序树可是“请神容易送神难”。想想删除可那么简单,因为不能因为你删除了一个结点,这棵树就不是二叉排序树了吧?所以删除时,要考虑多种情况。
- 删除的是叶子结点,可以想象,删除叶子结点不会对其他结点照成任何影响,此种情况可以直接删除。
- 删除的结点仅有左子树或者右子树,这种情况也相对容易,我把那个结点删除了,把它的左子树或者右子树整体移动到它的位置就可以了。
- 左右子树都存在,那么找要删除结点的前驱或者后继去替换它,然后把它的前驱或者后继删掉。
接下来看看代码怎么怎么写
<pre name="code" class="cpp">bool deleteBST(BiTree *pRoot,int key){if (!*pRoot) //删除的结点不存在return false;else{if (key == (*pRoot)->m_data) //找到值等于key的结点returnDelete(pRoot);else if (key < (*pRoot)->m_data){return deleteBST(&(*pRoot)->Lchild,key);}elsereturn deleteBST(&(*pRoot)->Rchild,key);}}bool Delete(BiTree * pRoot){BiTree q = NULL ,s = NULL;if ((*pRoot)->Lchild == NULL) //左子树为空,重接右子树{q = *pRoot;(*pRoot) = (*pRoot)->Rchild;free(q);}else if ((*pRoot)->Rchild == NULL) //右子树为空,重接左子树{q =*pRoot;*pRoot = (*pRoot)->Lchild;free(q);}else{q = *pRoot; //q指向待删除的结点s =(*pRoot)->Lchild; //while (s->Rchild) //前驱没有右子树{q = s;s = s->Rchild;}(*pRoot)->m_data = s->m_data; //s指向被删除结点的前驱if (q != *pRoot){q->Rchild = s->Lchild; //前驱的左孩子做前驱父节点的右孩子}else{q->Lchild = s->Lchild; //重接q的左子树}free(s);}return true;}二叉排序树的查找,走的就是根节点到要查找的结点路径,其比较次数等于给定值的结点在二叉树的深度,极端情况下,最少为1,即根节点就是要找的结点,最多不会超过树的深度,也就是说,查找的时间很大层度上取决于树的形状,但是二叉排序树的形状又是不确定的,那么问题有来了,由于形状的不同,查找的时间差异很大,怎么样才能保证树的深度呢,嘿嘿,往下就涉及到了平衡二叉树。
0 0
- 二查排序树
- 二查排序树
- 二查排序树的基本操作(插入,删除,找前驱与后继)
- 二树 ,增 、删、查
- 二插排序树
- 二插排序树
- 树状数组,二查索引树,BIT
- 排序二:索引、桶排序、败者树
- 数据库基础(二),t-sql(通配符、运算符、增删改查语句、重命名、排序)
- AnjularJs增查、排序
- 慢查日志(二)
- 并查集和拓扑排序加最小生成树
- 排序(二)
- hdoj 4514 并查集 树的直径 (二)
- UVA - 10304(最优二查搜索树 dp)
- 打印二查搜索树中的第k个结点
- 排序二--堆排序
- 排序(二)-冒泡排序
- Hibernate与 MyBatis的比较
- Jogl2.0 jogamp-all-platforms 在eclipse 中的配置
- Yeelink http请求
- Localization from Mere Connectivity-基于连通性的定位
- ubuntu 14.04 在连接无线的情况下,进行宽带连接
- 二查排序树
- UVA10361(字符串水题多坑)
- 信标网络和非信标网络
- 网页注册的短信验证的按钮特效
- 走吧,邱东(一)
- 第十周项目4 大奖赛计分
- CUDA学习日志:常量内存和纹理内存
- window与虚拟机之前的文件传输
- android的两个设置标题主题属性