动态查找:动态查找不仅要查找结点,而且还要不断地插入和删除结点,当表采用顺序结构时,这需要花费大量的时间用于结点的移动,效率很低。这里采用树表的形式,树表本身可以动态建立,树表主要有二叉排序树,平衡二叉树,B-树和B+树等。
二叉排序树的特点是:lchild <= root <= rchild,对此树中序遍历就可以找到一组有序的数组。二叉树的复杂度一般为O(log n ),但在特殊情况为O(n)。
这里要强调一点就是二叉排序树删除时要分两种情况,一种被删除点没有左子树,另外一种是有左子树。详细请见源代码:
#include <iostream.h>
#include <string.h>
typedef int KeyType;
#define NUM 11
class BinStree;
class BinSTreeNode
{
public:
KeyType key;
BinSTreeNode *lchild;
BinSTreeNode *rchild;
BinSTreeNode()
{
lchild = NULL;
rchild = NULL;
}
};
class BinSTree
{
public:
BinSTreeNode *root;
BinSTree()
{
root = NULL;
}
~BinSTree()
{
// DeleteTree();
}
BinSTreeNode *BSTreeSearch( BinSTreeNode *bt, KeyType k, BinSTreeNode *&p );
void BSTreeInsert( BinSTreeNode *&bt, KeyType k );
int BSTreeDelete( BinSTreeNode *&bt, KeyType k );
// void Destroy( BinSTreeNode *current );
// void DeleteTree()
// {
// Destroy( root );
// root = NULL;
// }
bool IsEmpty()
{
return root == NULL;
}
};
/**
* 二叉树排序查找算法
* 在根指针为bt的二叉排序树中查找元素k的节点,若查找成功,则返回指向该节点的指针
* 参数p指向查找到的结点,否则返回空指针,参数p指向k应插入的父结点
*/
BinSTreeNode* BinSTree::BSTreeSearch( BinSTreeNode *bt, KeyType k, BinSTreeNode *&p )
{
BinSTreeNode *q = NULL;
q = bt;
while( bt )
{
q = bt;
if( bt->key == k )
{
p = bt;
return( bt );
}
if( bt->key > k )
bt = bt->lchild;
else
bt = bt->rchild;
}
p = q;
return( bt );
}
/**
* 二叉排序树的插入节点算法
* bt指向二叉排序树的根结点,插入元素k的结点
*/
void BinSTree::BSTreeInsert( BinSTreeNode *&bt, KeyType k )
{
BinSTreeNode *p = NULL, *q;
q = bt;
if( BSTreeSearch( q, k, p ) == NULL )
{
BinSTreeNode *r = new BinSTreeNode;
r->key = k;
r->lchild = r->rchild = NULL;
if( q == NULL )
{
bt = r; //被插入节点做为树的根节点
}
if( p && k < p->key )
p->lchild = r;
else if( p )
p->rchild = r;
}
}
/**
* 二叉排序树的删除结点算法
* 在二叉排序树中删除元素为k的结点,*bt指向二叉排序树的根节点
* 删除成功返回1,不成功返回0.
*/
int BinSTree::BSTreeDelete( BinSTreeNode *&bt, KeyType k )
{
BinSTreeNode *f, *p, *q, *s;
p = bt;
f = NULL;
//查找关键字为k的结点,同时将此结点的双亲找出来
while( p && p->key != k )
{
f = p;
if( p->key > k )
p = p->lchild;
else
p = p->rchild;
}
if( p == NULL ) //找不到待删除的结点时返回
return 0;
if( p->lchild == NULL ) //待删除结点的左子树为空
{
if( f == NULL ) //待删除结点为根节点
bt = p->rchild;
else if( f->lchild == p ) //待删结点是其双亲结点的左节点
f->lchild = p->rchild;
else
f->rchild = p->rchild; //待删结点是其双亲结点的右节点
delete p;
}
else //待删除结点有左子树
{
q = p;
s = p->lchild;
while( s->rchild ) //在待删除结点的左子树中查找最右下结点
{
q = s;
s = s->rchild;
}
if( q == p )
q->lchild = s->lchild;
else
q->rchild = s->lchild;
p->key = s->key;
delete s;
}
return 1;
}
int main( void )
{
int a[NUM] = { 34, 18, 76, 13, 52, 82, 16, 67, 58, 73, 72 };
int i;
BinSTree bst;
BinSTreeNode *pBt = NULL, *p = NULL, *pT = NULL;
for( i = 0; i < NUM; i++ )
{
bst.BSTreeInsert( pBt, a[i] ); //创建二叉排序树
}
pT = bst.BSTreeSearch( pBt, 52, p ); //搜索排序二叉树
bst.BSTreeDelete( pBt, 13 ); //删除无左孩子的情况
bst.BSTreeDelete( pBt, 76 ); //删除有左孩子的情况
return 0;
}
本文详细介绍二叉排序树的基本概念及其插入、查找与删除算法的实现。通过具体实例演示了如何利用二叉排序树进行数据组织,并给出了完整的C++代码实现。
1658

被折叠的 条评论
为什么被折叠?



