二叉查找树

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值