二叉搜索树
来源:互联网 发布:网络空间用什么来描绘 编辑:程序博客网 时间:2024/05/16 23:41
二叉搜索树定义
1.每个结点都有一个作为搜索依据的关键码,所有结点的关键码都不相同。
2.左子树上所有结点的关键码都小于根节点的关键码。
3.右子树上所有结点的关键码都大于根节点的关键码。
4.左子树和右子树也是二叉搜索树。
二叉搜索树实现
使用c++实现二叉搜索树,这些是必要的声明。
#include <iostream>#include <stack>using namespace std;template <class Type> class BST; //二叉搜索树的前向声明
首先给出二叉搜索树的结点数据结构,和普通树的结点类相同。
template <class Type>class BstNode{ template <class T> friend class BST; //BST需要访问私有成员datapublic: //构造函数 BstNode() : leftChild( NULL ), rightChild( NULL ) {} BstNode( const Type d = 0, BstNode* L = NULL, BstNode* R = NULL ) : data( d ), leftChild( L ), rightChild( R ) {} ~BstNode() {} //Type get_data() { return data; }//测试中用到protected: Type data; //结点数据域 BstNode<Type>* leftChild, *rightChild;};
二叉搜索树的抽象数据类型。
template <class Type>class BST{public: BST() : root( NULL ) {} BST( Type value ); //指定输入结束符的构造函数 ~BST() { MakeEmpty( root ); } void MakeEmpty() { MakeEmpty( root ); root = NULL; } void PrintTree() { PrintTree( root ); } int Find( const Type&x ) const { return Find( x, root ) != NULL; } Type Min(); Type Max(); void Insert( const Type &x ) { Insert( x, root ); }; void Remove( const Type &x) { Remove( x, root ); };private: void MakeEmpty( BstNode<Type>*& ptr ); //将以ptr为根节点的二叉树置空 void Insert( const Type& x, BstNode<Type>*& ptr ); //插入 void Remove( const Type& x, BstNode<Type>*& ptr ); //删除 void PrintTree( BstNode<Type>* ptr ) const; BstNode<Type>* Copy( const BstNode<Type>* ptr ); //复制 BstNode<Type>* Find( const Type& x, BstNode<Type> *ptr ) const; //搜索 BstNode<Type>* Min( BstNode<Type>* ptr ) const; //最小元素 BstNode<Type>* Max( BstNode<Type>* ptr ) const; //最大元素private: BstNode<Type>* root; //二叉搜索树的根节点 Type refValue; //数据输入停止标识};
构造函数:从标准输入构造二叉搜索树,直到遇到输入停止标识
template <class Type>BST<Type>::BST( Type value ) : refValue( value ), root( NULL ){ Type x; //重载>> cin >> x; //Type 需要重载!=,否则这块会失效 while ( x != refValue ) { Insert( x, root ); cin >> x; }}
二叉搜索树置空:
MakeEmpty()删除参数中传入的结点,使用MakeEmpty()递归删除二叉搜索树种的每个结点。
//递归实现template <class Type>void BST<Type>::MakeEmpty( BstNode<Type>*& ptr ){ if ( ptr == NULL ) return ; if ( ptr->leftChild == NULL && ptr->rightChild == NULL ) { delete ptr; ptr = NULL; return ; } else if ( ptr->leftChild != NULL ) MakeEmpty( ptr->leftChild ); else MakeEmpty( ptr->rightChild );}
二叉搜索树中查找元素
template <class Type>BstNode<Type>* BST<Type>::Find( const Type& x, BstNode<Type>* ptr ) const{ while ( ptr != NULL ) { if ( ptr->data == x ) return ptr; if ( x > ptr->data ) ptr = ptr->rightChild; else ptr = ptr->leftChild; } return ptr;}
删除结点:递归实现,容易理解,容易实现
//删除结点的递归实现//相对于非递归实现轻松许多template <class Type>void BST<Type>::Remove( const Type& x, BstNode<Type>*& ptr ){ if ( ptr == NULL ) return ; if ( ptr->data == x ) { if ( ptr->leftChild == NULL && ptr->rightChild == NULL ) { delete ptr; ptr = NULL; return ; } else if ( ptr->leftChild == NULL ) { BstNode<Type>* temp = ptr; ptr = ptr->rightChild; delete temp; return ; } else if ( ptr->rightChild == NULL ) { BstNode<Type>* temp = ptr; ptr = ptr->leftChild; delete temp; return ; } else { ptr->data = Min( ptr->rightChild )->data; Remove( ptr->data, ptr->rightChild ); } } else if ( x > ptr->data ) { Remove( x, ptr->rightChild ); } else { Remove( x, ptr->leftChild ); }}
删除结点:非递归实现,要考虑各种特殊情况,理解麻烦
//删除结点的非递归实现//非递归实现比较麻烦template <class Type>void BST<Type>::Remove( const Type& x, BstNode<Type>*& ptr ){ BstNode<Type>* fp = ptr; BstNode<Type>* p = ptr; //如果是删除根节点要特殊处理,麻烦 if ( ptr->data == x ) { if ( ptr->leftChild == NULL && ptr->rightChild == NULL ) { delete ptr; ptr = NULL; return ; } else if ( ptr->leftChild == NULL ) { BstNode<Type>* temp = ptr; ptr = temp->rightChild; delete temp; return ; } else if ( ptr->rightChild == NULL ) { BstNode<Type>* temp = ptr; ptr = temp->leftChild; delete temp; return ; } else { ptr->data = Min(ptr->rightChild)->data; Remove( ptr->data, ptr->rightChild ); return ; } } while ( p != NULL ) { //找到目标,进行删除 if ( x == p->data ) { BstNode<Type>* temp = p; if ( p->leftChild == NULL ) { //左孩子和右孩子同时为空,直接删除即可 if ( p->rightChild == NULL ) { if ( p->data > fp->data ) fp->rightChild = NULL; else fp->leftChild = NULL; delete p; } //左孩子为空,右孩子不为空,将右孩子替代根节点 else { if ( p->data > fp->data ) fp->rightChild = p->rightChild; else fp->leftChild = p->rightChild; delete p; } } //左孩子不为空,右孩子为空,将左孩子替代根节点 else if ( p->rightChild == NULL ) { if ( p->data > fp->data ) fp->rightChild = p->leftChild; else fp->leftChild = p->leftChild; delete p; } //左孩子和右孩子都不为空,选择右孩子中最小的元素替代根节点 else { //将p的键值改成p的右子树中最小的那个键值 p->data = Min( p->rightChild )->data; //调用自己删除p的右子树中键值最小的那个结点 Remove( p->data, p->rightChild ); } } else if ( x > p->data ) { fp = p; p = p->rightChild; } else { fp = p; p = p->leftChild; } }}
求二叉搜索树键最小的结点
template <class Type>BstNode<Type>* BST<Type>::Min(BstNode<Type>* ptr) const{ if ( ptr == NULL ) return NULL; while ( ptr->leftChild != NULL ) { ptr = ptr->leftChild; } return ptr;}template <class Type>Type BST<Type>::Min(){ BstNode<Type>* result = Min( root ); if ( result == NULL ) return refValue; else return result->data;}
求二叉搜索树键值最大的结点
template <class Type>Type BST<Type>::Max(){ BstNode<Type>* result = Max( root ); if ( result == NULL ) return refValue; else return result->data;}template <class Type>BstNode<Type>* BST<Type>::Max( BstNode<Type>* ptr ) const{ if ( ptr == NULL ) return NULL; while ( ptr->rightChild != NULL ) { ptr = ptr->rightChild; } return ptr;}
插入,
//迭代实现template <class Type>void BST<Type>::Insert(const Type& x, BstNode<Type>*& ptr){ //若根节点为空,直接插入到根节点位置 if ( ptr == nullptr ) { ptr = new BstNode<Type>( x ); return ; } //fp 插入点的父结点 p 未来的插入点 BstNode<Type>* p = ptr; BstNode<Type>* fp = ptr; //找到插入点 while ( p != nullptr ) { fp = p; if ( x > p->data ) p = p->rightChild; else if ( x <= p->data ) p = p->leftChild; } //构造新结点 p = new BstNode<Type>( x ); //判断新节点是左子树还是右子树并且插入 if ( x > fp->data ) fp->rightChild = p; else fp->leftChild = p;}
打印二叉搜索树并输出,即非递归实现二叉树的中序遍历
//中序遍历二叉搜索树template <class Type>void BST<Type>::PrintTree( BstNode<Type>* ptr ) const{ if ( ptr == NULL ) return ; //上一次对栈的操作是push还是pop //用这个解决回溯时不能确定左子树是否被访问过的问题 //如果上一次对栈是push操作,说明栈顶部是一个新结点,新结点的左子树肯定没有被访问过 //如果上一次是pop操作,说明栈顶的元素的左子树已经被访问过了 bool pre_is_push = true; stack<BstNode<Type>*> mid_order_stack; //迭代实现中序遍历二叉搜索树辅助栈 mid_order_stack.push( ptr ); while ( !mid_order_stack.empty() ) { //show_stack( stack<BstNode<Type>*>( mid_order_stack ) );//脚手架 显示栈内容 //cout << mid_order_stack.top()->data << endl;//显示栈顶元素 if ( pre_is_push && mid_order_stack.top()->leftChild != NULL ) { ptr = mid_order_stack.top()->leftChild; mid_order_stack.push( ptr ); pre_is_push = true; } else { BstNode<Type>* temp_mid = mid_order_stack.top(); mid_order_stack.pop(); pre_is_push = false; if ( temp_mid->rightChild != NULL ) { mid_order_stack.push( temp_mid->rightChild ); pre_is_push = true; } cout << temp_mid->data << " "; } } cout << endl;}
测试主函数
int main( void ){ BST<int> int_bstree( 0 ); cout << int_bstree.Max() << endl; cout << int_bstree.Min() << endl; int_bstree.PrintTree(); int_bstree.Remove( 67 ); cout << int_bstree.Find( 5 ) << endl; cout << int_bstree.Find( 100 ) << endl; int_bstree.PrintTree(); int_bstree.MakeEmpty(); int_bstree.PrintTree();}
阅读全文
0 0
- 【二叉搜索数】HDU3791二叉搜索树
- 二叉树--二叉搜索树
- 【二叉树】二叉搜索树
- 二叉树- 二叉搜索树
- 【搜索树】二叉搜索树
- 二叉搜索树BSTree
- 二叉搜索树
- 二叉搜索树
- 二叉搜索树
- 最优二叉搜索树
- 二叉搜索树
- 二叉搜索树
- HDOJ3791 二叉搜索树
- 二叉查找树搜索
- 二叉搜索树
- 二叉搜索树
- BST 二叉搜索树
- 二叉搜索树
- 语言,框架等等工具的选择
- 乘积最大
- 2017的OI之路的梦想
- Conway's law
- netty4 UDP的使用
- 二叉搜索树
- hibernate-继承映射-15(不太重要)
- 你需要尝试的25个Android第三方库(现在开始还不迟)
- python在pandas.DataFrame添加一行
- cas server的使用
- [LeetCode] Decode Ways
- LintCode-两数组的交 II
- Android Studio JNI学习之(2)-JAVA与原生代码通信
- linux虚拟机——网络模式