二叉查找树(Binary Search Tree),或者是一棵空树,或者是具有下列性质的查找树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉查找树
中序周游二叉排序树可得到一个升序序列,一个无序序列可以通过构造一棵二叉排序树变成一个有序序列,构造树的过程即为对无序序列进行排序的过程。每次插入的新的结点都是二叉排序树上新的叶子节点,在进行插入操作时,不必移动其它结点,只需改动某个结点的指针,由空变为非空即可。搜索,插入,删除的复杂度等于树高,O(log(n)).
二叉查找树是二叉树的一个特例,因此我们继承至上篇二叉树,具体代码如下:
BinarySearchTree.h
#ifndef BIANRY_SEARCH_TREE_H
#define BINARY_SEARCH_TREE_H
template <typename T>
class BinarySearchTree : public BinaryTree<T>
{
public:
void initialize(BinaryTreeNode<T> *newPoint)
{
root = newPoint;
}
/************************************************************************/
/* 从根节点开始查找,newpointer若小于当前节点,则沿左路下降,当当前节点的
左孩子为空时,作为其左孩子插入;newpointer若大于当前节点,则沿右节点下降,当
当前节点的右孩子为空时,作为其右孩子插入 */
/************************************************************************/
void insertNode(BinaryTreeNode<T> *root,BinaryTreeNode<T> *newpointer)
{
BinaryTreeNode<T> *pointer = nullptr;
if(root == nullptr)//如果是空树,初始化
{
initialize(newpointer);//用指针newpointer初始化二叉搜索树树根,赋值实现
return;
}
else
{
pointer = root;
}
while(true)
{
if(newpointer->value() == pointer->value())
{
return;//相等则不用插入
}
if(newpointer->value() < pointer->value())
{
if(pointer->leftChild() == nullptr)
{
pointer->setLeftChild(newpointer);//作为左子树
return;
}
else
{
pointer = pointer->leftChild();//作为右子树
}
}
if(newpointer->value() > pointer->value())
{
if(pointer->rightChild() == nullptr)
{
pointer->setRightChild(newpointer);
return;
}
else
{
pointer = pointer->rightChild();
}
}
}
}
/************************************************************************/
/*删除节点过程如下:若pointer的左孩子为空,则用pointer的右孩子的节点代替pointer;
若pointer的左孩子不为空,则在pointer的左子树中按中序周游找到最后一个节点temppointer
,把temppointer的右指针设置为pointer右孩子的根,pointer左孩子的根代替被删除的节
点pointer,
弊端:有可能使树的高度增加*/
/************************************************************************/
void deleteNode(BinaryTreeNode<T> *pointer)
{
BinaryTreeNode<T> *temppointer = nullptr;
if(!pointer)
{
return;
}
BinaryTreeNode<T> *parenter = parent(pointer);
//被删结点无左子树,则将其右子树的根代替该删除结点
if(pointer->leftChild() == nullptr)
{
if(parenter == nullptr)//删除的是根节点
{
root = pointer->rightChild();
}
else if(parenter->leftChild() == pointer)
{
parenter->setLeftChild(pointer->rightChild());
}
else
{
parenter->setRightChild(parenter->rightChild()) ;
}
delete pointer;//删除该节点
pointer = nullptr;
return;
}
else//有左子树的情况
{
temppointer = pointer->leftChild();
while(temppointer->rightChild() != nullptr)
{
temppointer = temppointer->rightChild();
}
//被删除结点的右子树作为temppointer的右子树
temppointer->setRightChild(pointer->rightChild());
if(parenter == nullptr)//删除的是根节点
{
root = pointer->leftChild();
}
//pointer左孩子的根代替被删除的节点pointer
else if(parenter->leftChild() == pointer)
{
parenter->setLeftChild(pointer->leftChild());
}
else
{
parenter->setRightChild(pointer->leftChild()) ;
}
delete pointer;//删除该节点
pointer = nullptr;
return;
}
}
/************************************************************************/
/*为了克服上个删除算法可能使树高度增加的弊端,新的删除节点过程如下:
若pointer的左孩子为空,则用pointer的右孩子的节点代替pointer;
若pointer的左孩子不为空,则在pointer的左子树中按中序周游找到最后一个节点
temppointer,temppointer左孩子的根代替temppointer,把temppointer代替pointer */
/************************************************************************/
void deleteNodeEx(BinaryTreeNode<T> *pointer)
{
BinaryTreeNode<T> *temppointer = nullptr;// 用于保存替换结点
BinaryTreeNode<T> *tempparent = nullptr;// 用于保存替换结点的父结点
if(!pointer)
{
return;
}
BinaryTreeNode<T> *parenter = parent(pointer);// 保存删除结点的父结点
//被删结点无左子树,则将其右子树的根代替该删除结点
if(pointer->leftChild() == nullptr)
{
if(parenter == nullptr)//删除的是根节点
{
root = pointer->rightChild();
}
else if(parenter->leftChild() == pointer)
{
parenter->setLeftChild(pointer->rightChild());
}
else
{
parenter->setRightChild(parenter->rightChild()) ;
}
delete pointer;//删除该节点
pointer = nullptr;
return;
}
else//有左子树的情况
{
temppointer = pointer->leftChild();
while(temppointer->rightChild() != nullptr)
{
tempparent = temppointer;
temppointer = temppointer->rightChild();
}
if(tempparent == nullptr)//替换节点就是被删除节点的左子节点,如果不处理此处边界情况,则tempparent为空,tempparent->setRightChild(temppointer->leftChild())无法执行
{
//替换节点左子树挂接到被删除节点的左子树,其实也就是temppointer左孩子的根代替temppointer
pointer->setLeftChild(temppointer->leftChild());
}
else
{
//temppointer左孩子的根代替temppointer
tempparent->setRightChild(temppointer->leftChild());
}
//将pointer的左右子树挂到temppointer下面
temppointer->setLeftChild(pointer->leftChild());
temppointer->setRightChild(pointer->rightChild());
if(parenter == nullptr)//删除的是根节点
{
root = pointer->leftChild();
}
//temppointer代替被删除的节点pointer
else if(parenter->leftChild() == pointer)
{
parenter->setLeftChild(temppointer);
}
else
{
parenter->setRightChild(temppointer) ;
}
delete pointer;//删除该节点
pointer = nullptr;
return;
}
}
};
#endif
测试代码:
#include "BinaryTree.h"
#include "BinarySearchTree.h"
#include <iostream>
const int N = 11;
int main()
{
int K[N] = {50,19,35,55,20,5,100,52,88,53,92}; //建一棵图5.11所示的树,见北大张铭《数据结构与算法》
BinarySearchTree<int> aBST;
BinaryTreeNode<int > *newpointer, *node1, *node2; // 循环插入结点
for (int i = 0; i < N; i ++) {
newpointer = new BinaryTreeNode<int>();
newpointer->setValue(K[i]);
aBST.insertNode(aBST.getRoot(), newpointer); //依次插入结点
if (K[i] == 52){ //记录待删除结点的指针node1
node1 = newpointer;
// cout<<node1->value()<<endl;
}
if (K[i] == 55) //记录待删除结点的指针node2
node2 = newpointer;
}
// 遍历结点
cout << "中序周游二叉搜索树:" << endl;
aBST.inOrder(aBST.getRoot());
cout << endl;
//删除两个结点
cout << "删除结点52, 55." << endl;
//aBST.deleteNodeEx(node1);
aBST.deleteNodeEx(node2);
// 遍历节点
cout << "删除结点之后中序周游二叉搜索树:" << endl;
aBST.inOrder(aBST.getRoot());
cout << endl;
system("pause");
return 0;
}