二叉查找树(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;
- }