在学习基本数据结构过程中,我们常碰到二叉树,二叉树是一棵每个节点至多只有两个孩子的数,学习其常见的操作和变换可以参见我的另一篇博文《c++二叉树构建及面试常见问题代码实现》,在这儿,二叉树中引用得比较广的二叉搜索树(BSF)、平衡二叉树(AVL)及其AVL的常用替代结构伸展树(Splay Tree)和跳表(Skip List)。
头文件:binaryTree.h
#ifndef __BINARYTREE_H__
#define __BINARYTREE_H__
#include
//节点
template
class CTreeNode
{
public:
Element key;
CTreeNode *lchild;
CTreeNode *rchild;
CTreeNode(Element value):key(value),lchild(NULL), rchild(NULL){};
~CTreeNode(){lchild = NULL; rchild = NULL;};
};
//二叉树
template
class CBinaryTree
{
public:
CBinaryTree();
~CBinaryTree();
bool treeEmpty(); //树是否为空
bool insertElement(Element value); //插入元素
bool reinsertElement(CTreeNode * &proot,Element value); //使用递归的插入
void inorderTree(CTreeNode *root); //中序遍历
CTreeNode * minValue(CTreeNode * root); //返回最小值结点
CTreeNode * maxValue(CTreeNode * root); //返回最大值结点
CTreeNode * search( Element value); //查找元素
bool deleteValue(Element value); //删除元素
CTreeNode * parent(CTreeNode * child); //查找父结点
CTreeNode * postNode(CTreeNode * node); //后继结点
void deleteTree(CTreeNode * root); //删除一棵树
public:
CTreeNode *root;
};
#endif
源文件:binaryTree.cpp
#include "binaryTree.h"
using namespace std;
//构造函数
template
CBinaryTree::CBinaryTree()
{
root = NULL;
}
//析构函数
template
CBinaryTree::~CBinaryTree()
{
deleteTree(root);//释放空间
root = NULL;
}
//判断树是否为空
template
bool CBinaryTree::treeEmpty()
{
return root == NULL;
}
//插入元素
template
bool CBinaryTree::insertElement(Element value)
{
//找到插入点父节点q
CTreeNode *p = root;
CTreeNode *q = NULL;
while ( p != NULL )
{
q = p;//记录要插入点的父节点
if ( value < p->key )
p = p->lchild;
else if ( value > p->key ) p = p->rchild;
else return false;//表示有相同元素,插入不成功
}
if ( q == NULL )//树为空情况
{
root = new CTreeNode(value);
return true;
}
if ( value < q->key )//树不为空
{
q->lchild = new CTreeNode(value);
return true;
}else
{
q->rchild = new CTreeNode(value);
return true;
}
}
//使用递归的插入,看起来更简洁
template
bool CBinaryTree::reinsertElement(CTreeNode * &proot,Element value)
{
if(!proot)
{
proot=new CTreeNode(value);
return true;
}
else if(value>proot->key) return reinsertElement(proot->rchild,value);
else if(valuekey) return reinsertElement(proot->lchild,value);
else return false;
}
//中序遍历
//二叉查找树一般只考虑中序遍历,因为中序遍历为有序数列
template
void CBinaryTree::inorderTree(CTreeNode *root)
{
if ( root )
{
inorderTree(root->lchild);
cout<key<rchild);
}
}
//二叉树查找元素 ,也可以由递归的实现方法
template
CTreeNode * CBinaryTree::search(Element value)
{
CTreeNode *p = root;
while ( p != NULL && p->key != value)
{
if ( value < p->key )
p = p->lchild;
else
p = p->rchild;
}
return p;
}
//得到父节点,主要用于删除元素时使用
template
CTreeNode * CBinaryTree::parent(CTreeNode * child)
{
CTreeNode *p = root;
CTreeNode *q = NULL;
while ( p != NULL && p->key != child->key )
{
q = p;
if( p->key > child->key )
{
p = p->lchild;
}
else
{
p = p->rchild;
}
}
return q;
}
//得到最小值
template
CTreeNode * CBinaryTree::minValue(CTreeNode * root)
{
if(!root) return root;
CTreeNode *p = root;
while ( p->lchild != NULL)
{
p = p->lchild;
}
return p;
}
//得到最大值
template
CTreeNode * CBinaryTree::maxValue(CTreeNode * root)
{
if(!root) return root;
CTreeNode *p = root;
while ( p->rchild != NULL)
{
p = p->rchild;
}
return p;
}
//找到一个元素的后继元素 ,用于删除
/*
这个程序值得分析,后继总共两种情况:
1.一个节点的右子树存在,则后继即为右子树的最小元素
2.右子树不存在,找父节点,往前回溯
*/
template
CTreeNode * CBinaryTree::postNode(CTreeNode * node)
{
if( node->rchild != NULL )
return minValue(node->rchild);
CTreeNode *p = node;
CTreeNode *par = parent(p);
while ( par != NULL && par->rchild == p )
{
p = par;
par = parent(p);
}
return par;
}
//删除元素,分三种情况
/*
1.叶子节点,直接删除
2.有一个子树为空的节点,删除之后连接
3.两个子树都不为空的节点,用后继节点替换,再删除后继节点
当然了,这需要前面做好准备,写好求取父节点和后继元素的函数
*/
template
bool CBinaryTree::deleteValue(Element Value)
{
CTreeNode * p = search(Value);
if(!p) return false;
CTreeNode * q = NULL;
CTreeNode * s = NULL;
//情况1
if ( p->lchild == NULL&&p->rchild == NULL )
{
q=parent(p);
if(q->lchild==p) q->lchild=NULL;
else q->rchild=NULL;
delete p;
return true;
}else if(p->lchild == NULL||p->rchild == NULL)//情况2
{
q=parent(p);
if(p->lchild)
{
if(q->lchild==p) q->lchild=p->lchild;
else q->rchild=p->lchild;
}else
{
if(q->lchild==p) q->lchild=p->rchild;
else q->rchild=p->rchild;
}
delete p;
return true;
}else//情况3
{
s=postNode(p);
std::swap(s->key,p->key);
return deleteValue(p->key);
}
}
//删除一棵以root为根的树
template
void CBinaryTree::deleteTree(CTreeNode * root)
{
if(!root)
{
delete root;
deleteTree(root->lchild);
deleteTree(root->rchild);
}
}
测试代码:
#include
#include "binaryTree.h"
#include "binaryTree.cpp" //必不可少
#include
#include
using namespace std;
int main()
{
CBinaryTree m_bTree;
srand((unsigned)time(NULL));
for(int i=0;i<20;i++)
// m_bTree.insertElement(rand()%100);
m_bTree.reinsertElement(m_bTree.root,rand()%100);
m_bTree.inorderTree(m_bTree.root);
system("pause");
m_bTree.deleteValue(m_bTree.maxValue(m_bTree.root)->key);
cout<key<key<
头文件:AVLTree.h
#ifndef AVLTREE_H
#define AVLTREE_H
#include
#include
#include
using namespace std;
static const string PRINT_SPACES =" ";
template
class AVLTree
{
public:
AVLTree(){root=NULL;} //构造函数
void insert(const Object &x) {insert(x,root);} //插入元素X
void remove(const Object &x) {remove(x,root);} //移除元素x
void print(); //打印AVLTree
private:
struct AVLnode
{
Object data;
AVLnode *left;
AVLnode *right;
int height; //还可以是平衡因子
AVLnode(Object ob,AVLnode *l,AVLnode *r,int h=0):data(ob),left(l),right(r),height(h){}
};
AVLnode *root;
void insert(const Object &x,AVLnode * &t);
void remove(const Object &x,AVLnode *&t);
void leftSingleRotation(AVLnode * &t);
void rightSingleRotation(AVLnode * &t);
void leftDoubleRotation(AVLnode * &t);
void rightDoubleRotation(AVLnode * &t);
int height(AVLnode * &t)
{
//结点的高度,空结点的高度为-1
return t==NULL?-1:t->height;
}
AVLnode * max_node(AVLnode * t)
{
if(!t)
return NULL;
if(t->right)
return max_node(t->right);
else
return t;
}
AVLnode * min_node(AVLnode * t)
{
if(t)
while(t->left)
t=t->left;
return t;
}
};
#endif
源文件:AVLTree.cpp
#include "AVLTree.h"
#include
using namespace std;
template
void AVLTree
测试代码:
#include "AVLTree.h"
#include "AVLTree.cpp"
#include
#include
int main()
{
AVLTree avl;
srand((unsigned)time(NULL));
for(int i=0;i<20;i++)
avl.insert(rand()%100);
avl.print();
std::cout<