二叉查找树的实现——c++
二叉查找树的c++实现:
1. 节点和二叉查找树的定义
1.1 二叉查找树节点
template <class T>
class BSTNode{
public:
T key; // 关键字(键值)
BSTNode *left; // 左孩子
BSTNode *right; // 右孩子
BSTNode *parent;// 父结点 BSTNode(T value, BSTNode *p, BSTNode *l, BSTNode *r):
key(value),parent(),left(l),right(r) {}
};
BSTNode是二叉查找树的节点,它包含二叉查找树的几个基本信息:
(01) key -- 它是关键字,是用来对二叉查找树的节点进行排序的。
(02) left -- 它指向当前节点的左孩子。
(03) right -- 它指向当前节点的右孩子。
(04) parent -- 它指向当前节点的父结点。
1.2 二叉树操作
template <class T>
class BSTree {
private:
BSTNode<T> *mRoot; // 根结点 public:
BSTree();
~BSTree(); // 前序遍历"二叉树"
void preOrder();
// 中序遍历"二叉树"
void inOrder();
// 后序遍历"二叉树"
void postOrder(); // (递归实现)查找"二叉树"中键值为key的节点
BSTNode<T>* search(T key);
// (非递归实现)查找"二叉树"中键值为key的节点
BSTNode<T>* iterativeSearch(T key); // 查找最小结点:返回最小结点的键值。
T minimum();
// 查找最大结点:返回最大结点的键值。
T maximum(); // 找结点(x)的后继结点。即,查找"二叉树中数据值大于该结点"的"最小结点"。
BSTNode<T>* successor(BSTNode<T> *x);
// 找结点(x)的前驱结点。即,查找"二叉树中数据值小于该结点"的"最大结点"。
BSTNode<T>* predecessor(BSTNode<T> *x); // 将结点(key为节点键值)插入到二叉树中
void insert(T key); // 删除结点(key为节点键值)
void remove(T key); // 销毁二叉树
void destroy(); // 打印二叉树
void print();
private:
// 前序遍历"二叉树"
void preOrder(BSTNode<T>* tree) const;
// 中序遍历"二叉树"
void inOrder(BSTNode<T>* tree) const;
// 后序遍历"二叉树"
void postOrder(BSTNode<T>* tree) const; // (递归实现)查找"二叉树x"中键值为key的节点
BSTNode<T>* search(BSTNode<T>* x, T key) const;
// (非递归实现)查找"二叉树x"中键值为key的节点
BSTNode<T>* iterativeSearch(BSTNode<T>* x, T key) const; // 查找最小结点:返回tree为根结点的二叉树的最小结点。
BSTNode<T>* minimum(BSTNode<T>* tree);
// 查找最大结点:返回tree为根结点的二叉树的最大结点。
BSTNode<T>* maximum(BSTNode<T>* tree); // 将结点(z)插入到二叉树(tree)中
void insert(BSTNode<T>* &tree, BSTNode<T>* z); // 删除二叉树(tree)中的结点(z),并返回被删除的结点
BSTNode<T>* remove(BSTNode<T>* &tree, BSTNode<T> *z); // 销毁二叉树
void destroy(BSTNode<T>* &tree); // 打印二叉树
void print(BSTNode<T>* tree, T key, int direction);
};
BSTree是二叉树。它包含二叉查找树的根节点和二叉查找树的操作。二叉查找树的操作中有许多重载函数,例如insert()函数,其中一个是内部接口,另一个是提供给外部的接口。
2. 遍历(前序遍历、中序遍历、后序遍历、…)//相对于根节点来说
2.1 前序遍历
若二叉树非空,则执行以下操作:
(01) 访问根结点;
(02) 先序遍历左子树;
(03) 先序遍历右子树。
template <class T>
void BSTree<T>::preOrder(BSTNode<T>* tree) const
{
if(tree != NULL)
{
cout<< tree->key << " " ;
preOrder(tree->left);
preOrder(tree->right);
}
} template <class T>
void BSTree<T>::preOrder()
{
preOrder(mRoot);
}
2.2 中序遍历
若二叉树非空,则执行以下操作:
(01) 中序遍历左子树;
(02) 访问根结点;
(03) 中序遍历右子树。
template <class T>
void BSTree<T>::inOrder(BSTNode<T>* tree) const
{
if(tree != NULL)
{
inOrder(tree->left);
cout<< tree->key << " " ;
inOrder(tree->right);
}
} template <class T>
void BSTree<T>::inOrder()
{
inOrder(mRoot);
}
2.3 后序遍历
若二叉树非空,则执行以下操作:
(01) 后序遍历左子树;
(02) 后序遍历右子树;
(03) 访问根结点。
template <class T>
void BSTree<T>::postOrder(BSTNode<T>* tree) const
{
if(tree != NULL)
{
postOrder(tree->left);
postOrder(tree->right);
cout<< tree->key << " " ;
}
} template <class T>
void BSTree<T>::postOrder()
{
postOrder(mRoot);
}
3. 查找
递归版本的代码:
template <class T>
BSTNode<T>* BSTree<T>::search(BSTNode<T>* x, T key) const
{
if (x==NULL || x->key==key)
return x; if (key < x->key)
return search(x->left, key);
else
return search(x->right, key);
} template <class T>
BSTNode<T>* BSTree<T>::search(T key)
{
search(mRoot, key);
}
非递归:
template <class T>
BSTNode<T>* BSTree<T>::iterativeSearch(BSTNode<T>* x, T key) const
{
while ((x!=NULL) && (x->key!=key))
{
if (key < x->key)
x = x->left;
else
x = x->right;
} return x;
} template <class T>
BSTNode<T>* BSTree<T>::iterativeSearch(T key)
{
iterativeSearch(mRoot, key);
}
4. 最大值和最小值
查找最大值:
template <class T>
BSTNode<T>* BSTree<T>::maximum(BSTNode<T>* tree)
{
if (tree == NULL)
return NULL; while(tree->right != NULL)
tree = tree->right;
return tree;
} template <class T>
T BSTree<T>::maximum()
{
BSTNode<T> *p = maximum(mRoot);
if (p != NULL)
return p->key; return (T)NULL;
}
查找最小值:
template <class T>
BSTNode<T>* BSTree<T>::minimum(BSTNode<T>* tree)
{
if (tree == NULL)
return NULL; while(tree->left != NULL)
tree = tree->left;
return tree;
} template <class T>
T BSTree<T>::minimum()
{
BSTNode<T> *p = minimum(mRoot);
if (p != NULL)
return p->key; return (T)NULL;
}
5. 前驱和后继
节点的前驱:是该节点的左子树中的最大节点。
节点的后继:是该节点的右子树中的最小节点。
查找前驱节点代码:
/*
* 找结点(x)的前驱结点。即,查找"二叉树中数据值小于该结点"的"最大结点"。
*/
template <class T>
BSTNode<T>* BSTree<T>::predecessor(BSTNode<T> *x)
{
// 如果x存在左孩子,则"x的前驱结点"为 "以其左孩子为根的子树的最大结点"。
if (x->left != NULL)
return maximum(x->left); // 如果x没有左孩子。则x有以下两种可能:
// (01) x是"一个右孩子",则"x的前驱结点"为 "它的父结点"。
// (01) x是"一个左孩子",则查找"x的最低的父结点,并且该父结点要具有右孩子",找到的这个"最低的父结点"就是"x的前驱结点"。
BSTNode<T>* y = x->parent;
while ((y!=NULL) && (x==y->left))
{
x = y;
y = y->parent;
} return y;
}
查找后继节点的代码:
/*
* 找结点(x)的后继结点。即,查找"二叉树中数据值大于该结点"的"最小结点"。
*/
template <class T>
BSTNode<T>* BSTree<T>::successor(BSTNode<T> *x)
{
// 如果x存在右孩子,则"x的后继结点"为 "以其右孩子为根的子树的最小结点"。
if (x->right != NULL)
return minimum(x->right); // 如果x没有右孩子。则x有以下两种可能:
// (01) x是"一个左孩子",则"x的后继结点"为 "它的父结点"。
// (02) x是"一个右孩子",则查找"x的最低的父结点,并且该父结点要具有左孩子",找到的这个"最低的父结点"就是"x的后继结点"。
BSTNode<T>* y = x->parent;
while ((y!=NULL) && (x==y->right))
{
x = y;
y = y->parent;
} return y;
}
6. 插入节点
/*
* 将结点插入到二叉树中
*
* 参数说明:
* tree 二叉树的根结点
* z 插入的结点
*/
template <class T>
void BSTree<T>::insert(BSTNode<T>* &tree, BSTNode<T>* z)
{
BSTNode<T> *y = NULL;
BSTNode<T> *x = tree; // 查找z的插入位置
while (x != NULL)
{
y = x;
if (z->key < x->key)
x = x->left;
else
x = x->right;
} z->parent = y;
if (y==NULL)
tree = z;
else if (z->key < y->key)
y->left = z;
else
y->right = z;
} /*
* 将结点(key为节点键值)插入到二叉树中
*
* 参数说明:
* tree 二叉树的根结点
* key 插入结点的键值
*/
template <class T>
void BSTree<T>::insert(T key)
{
BSTNode<T> *z=NULL; // 如果新建结点失败,则返回。
if ((z=new BSTNode<T>(key,NULL,NULL,NULL)) == NULL)
return ; insert(mRoot, z);
}
注:本文实现的二叉查找树是允许插入相同键值的节点的。若想禁止二叉查找树中插入相同键值的节点,可以参考"二叉查找树(一)之 图文解析 和 C语言的实现"中的插入函数进行修改。
7. 删除节点
/*
* 删除结点(z),并返回被删除的结点
*
* 参数说明:
* tree 二叉树的根结点
* z 删除的结点
*/
template <class T>
BSTNode<T>* BSTree<T>::remove(BSTNode<T>* &tree, BSTNode<T> *z)
{
BSTNode<T> *x=NULL;
BSTNode<T> *y=NULL; if ((z->left == NULL) || (z->right == NULL) )
y = z;
else
y = successor(z); if (y->left != NULL)
x = y->left;
else
x = y->right; if (x != NULL)
x->parent = y->parent; if (y->parent == NULL)
tree = x;
else if (y == y->parent->left)
y->parent->left = x;
else
y->parent->right = x; if (y != z)
z->key = y->key; return y;
} /*
* 删除结点(z),并返回被删除的结点
*
* 参数说明:
* tree 二叉树的根结点
* z 删除的结点
*/
template <class T>
void BSTree<T>::remove(T key)
{
BSTNode<T> *z, *node; if ((z = search(mRoot, key)) != NULL)
if ( (node = remove(mRoot, z)) != NULL)
delete node;
}
8. 打印二叉查找树
/*
* 打印"二叉查找树"
*
* key -- 节点的键值
* direction -- 0,表示该节点是根节点;
* -1,表示该节点是它的父结点的左孩子;
* 1,表示该节点是它的父结点的右孩子。
*/
template <class T>
void BSTree<T>::print(BSTNode<T>* tree, T key, int direction)
{
if(tree != NULL)
{
if(direction==) // tree是根节点
cout << setw() << tree->key << " is root" << endl;
else // tree是分支节点
cout << setw() << tree->key << " is " << setw() << key << "'s " << setw() << (direction==?"right child" : "left child") << endl; print(tree->left, tree->key, -);
print(tree->right,tree->key, );
}
} template <class T>
void BSTree<T>::print()
{
if (mRoot != NULL)
print(mRoot, mRoot->key, );
}
9. 销毁
/*
* 销毁二叉树
*/
template <class T>
void BSTree<T>::destroy(BSTNode<T>* &tree)
{
if (tree==NULL)
return ; if (tree->left != NULL)
return destroy(tree->left);
if (tree->right != NULL)
return destroy(tree->right); delete tree;
tree=NULL;
} template <class T>
void BSTree<T>::destroy()
{
destroy(mRoot);
}
本文来自http://www.cnblogs.com/skywang12345/p/3576373.html
二叉查找树的实现——c++的更多相关文章
- 数据结构:二叉查找树(C语言实现)
数据结构:二叉查找树(C语言实现) ►写在前面 关于二叉树的基础知识,请看我的一篇博客:二叉树的链式存储 说明: 二叉排序树或者是一棵空树,或者是具有下列性质的二叉树: 1.若其左子树不空,则左子树上 ...
- 数据结构笔记--二叉查找树概述以及java代码实现
一些概念: 二叉查找树的重要性质:对于树中的每一个节点X,它的左子树任一节点的值均小于X,右子树上任意节点的值均大于X. 二叉查找树是java的TreeSet和TreeMap类实现的基础. 由于树的递 ...
- codevs 1285 二叉查找树STL基本用法
C++STL库的set就是一个二叉查找树,并且支持结构体. 在写结构体式的二叉查找树时,需要在结构体里面定义操作符 < ,因为需要比较. set经常会用到迭代器,这里说明一下迭代器:可以类似的把 ...
- 平衡二叉查找树(AVL)的理解与实现
AVL树的介绍 平衡二叉树,又称AVL(Adelson-Velskii和Landis)树,是带有平衡条件的二叉查找树.这个平衡条件必须要容易保持,而且它必须保证树的深度是 O(log N).一棵AVL ...
- 二叉查找树 C++实现(含完整代码)
一般二叉树的查找是通过遍历整棵二叉树实现,效率较低.二叉查找树是一种特殊的二叉树,可以提高查找的效率.二叉查找树又称为二叉排序树或二叉搜索树. 二叉查找树的定义 二叉排序树(Binary Search ...
- 数据结构——二叉查找树、AVL树
二叉查找树:由于二叉查找树建树的过程即为插入的过程,所以其中序遍历一定为升序排列! 插入:直接插入,插入后一定为根节点 查找:直接查找 删除:叶子节点直接删除,有一个孩子的节点删除后将孩子节点接入到父 ...
- Java for LintCode 验证二叉查找树
给定一个二叉树,判断它是否是合法的二叉查找树(BST) 一棵BST定义为: 节点的左子树中的值要严格小于该节点的值. 节点的右子树中的值要严格大于该节点的值. 左右子树也必须是二叉查找树. ...
- 数据结构和算法 – 9.二叉树和二叉查找树
9.1.树的定义 9.2.二叉树 人们把每个节点最多拥有不超过两个子节点的树定义为二叉树.由于限制子节点的数量为 2,人们可以为插入数据.删除数据.以及在二叉树中查找数据编写有效的程序了. 在 ...
- 二叉树-二叉查找树-AVL树-遍历
一.二叉树 定义:每个节点都不能有多于两个的儿子的树. 二叉树节点声明: struct treeNode { elementType element; treeNode * left; treeNod ...
- 二叉查找树的Java实现
为了克服对树结构编程的恐惧感,决心自己实现一遍二叉查找树,以便掌握关于树结构编程的一些技巧和方法.以下是基本思路: [1] 关于容器与封装.封装,是一种非常重要的系统设计思想:无论是面向过程的函数,还 ...
随机推荐
- Halcon对文件的创建、读取、写入、删除等操作总结
Halcon可以操作普通文本文件,也可以操作二进制文件.如下图所示,只需要设置“FileType”参数的取值即可明确是操作文本文件还是二进制文件: 下面的程序是操作一个.txt文本文件的完整代码: * ...
- linux下nginx tomcat集群
集群系统一般通过两台或多台节点服务器系统通过相应的硬件及软件互连,每个群集节点都是运行其自己进程的独立服务器. 这些进程可以彼此通信,对网络客户机来说就像是形成了一个单一系统,协同起来向用户提供应用程 ...
- Oracle增加一列、修改一列数据类型
Oracle增加一列.修改一列数据类型: 添加一列: alter table A add( CFYJSNR varchar2(20)); 修改列: alter table A ren ...
- mysql的头文件
yum install mysql /usr/include/mysql yum install mysql-devel
- OSGi 系列(十六)之 JDBC Service
OSGi 系列(十六)之 JDBC Service compendium 规范提供了 org.osgi.service.jdbc.DataSourceFactory 服务 1. 快速入门 1.1 环境 ...
- mvc模拟实现
.定义httpmodule <system.webServer> <modules> <add name="UrlRoutingModule" typ ...
- 关于使用smsx.cab控件做web打印使用方法(转)
注意:在使用之前先告诉下我的痛苦经历 在做WEB项目是我的JSP页面在jsp文件夹里,我把smsx.cab放在js文件夹里(jsp和js是用级别目录) 在本机上测试可以正确下载控件,但是部署到测试服务 ...
- yii2 beforeAction 重定向问题
不跳转代码:return $this->redirect('http://www.yiichina.com/'); 跳转代码:return $this->redirect('http:// ...
- HDU 2161 Primes (素数筛选法)
题意:输入一个数判断是不是素数,并规定2不是素数. 析:一看就很简单吧,用素数筛选法,注意的是结束条件是n<0,一开始被坑了... 不说了,直接上代码: #include <iostrea ...
- 函数作用域和块级作用域--你不知道的JavaScript
et和const在{}内声明都会变为外部不能访问的值,但是const声明的是常量,也不能修改 函数是 JavaScript 中最常见的作用域单元.本质上,声明在一个函数内部的变量或函数会在所处的作用域 ...