欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

二叉搜索树

程序员文章站 2022-05-06 23:43:57
...

二叉搜索树:二叉搜索树是由二叉树来组织的,树中每一个子树的根节点key值都大于左树的key值而小于右子树的key值。

                   二叉搜索树的中序遍历key值恰好是从小到达排序。查询二叉树、MinMum、MaxMum、Insert和delete等操作时间复杂                    度为O(h); h为树的高度log2(n);

c++实现代码如下:

              头文件,树节点和树 类的定义

Binary_SearchTree.h

   

#ifndef _BINARY_SEARCHTREE
#define  _BINARY_SEARCHTREE

template<typename T>//定义Element类,便于外部调用函数更改数据类型
class Element
{
public:
	T key;//便于在节点中随时加入数据
	char name;

};

template<typename T> class BST;//BST模板类的声明

template<typename T>
class BSTNode
{
	friend class BST<T>;//友元类声明 BST二叉树要访问节点私有元素
public:
	Element<T> getElement();
	private:
		Element<T> data;
	    BSTNode *leftChild;
	    BSTNode *rightChild;
		void display(int i);//递归展示当前节点信息
	
};

template<typename T>//搜索二叉树模板类
class BST
{
public:
	BST(BSTNode<T>*init = 0);
	bool BST_insert(const Element<T> &node);//插入元素
	BSTNode<T>* BST_Search(const Element<T>&node);//递归搜索
	BSTNode<T>* BST_Search(BSTNode<T>*,const Element<T>&);

	BSTNode<T>*BST_Search_Iterator(const Element<T>&);//迭代搜索
	bool Delete_Node(const Element<T>&node);//删除节点
	BSTNode<T>*MinMum();//树的key最大节点
	BSTNode<T>*MaxMum();//树的key最小节点

	void midOrder();//中序遍历
	void midOrder(BSTNode<T>*root);

	void display();//递归左右子树展示当前树所有节点信息
	~BST();

private:
	BSTNode<T> *root;

};

#endif

hpp文件 实现类的成员函数

#include"Binary_SearchTree.h"
#include"iostream"
using namespace std;
//节点的成员函数

//节点内容获取
template<typename T>
void BSTNode<T>::display(int i)
{
	cout << "position: " << i << "  data.Key:" << data.key << " value:" << data.name << endl;
	if (leftChild)
		leftChild->display(2 * i);
	if (rightChild)
		rightChild->display(2 * i + 1);
}
//获取节点Element
template<typename T>
Element<T> BSTNode<T>::getElement()
{
	return data;
}


//树的成员函数

//构造初始化
	template<typename T>
	BST<T>::BST(BSTNode<T>*init = NULL)
	{
		root = init;
	}
//插入节点 
	template<typename T>
	bool BST<T>::BST_insert(const Element<T> &node)
	{
		BSTNode<T>*p = NULL;
		BSTNode<T>*q = root;
		while (q)//查找插入位置 最终肯定为叶子
		{
			p = q;
			if (node.key == q->data.key)
			{
				return false;
			}
			if (node.key > q->data.key)
			{
				q = q->rightChild;
			}
			else
			{
				q = q->leftChild;
			}
		}
        //创建新节点保存插入元素
		q = new BSTNode<T>;
		q->data = node;//Element数据类型浅拷贝,若Element包含指针元素得重载=操作符
		q->leftChild = NULL;
		q->rightChild = NULL;
        //空树的情况
		if (root == NULL)
		{
			root = q;
		}
		else
		{
			if (p->data.key > q->data.key)
			{
				p->leftChild = q;
			}
			else
			{
				p->rightChild = q;
			}
		}
		return true;
	}


//点展示树左右子树
//根据节点递归显示左右子树

	template<typename T>
	void BST<T>::display()
	{
		if (root == NULL)
		{
			cout << "树为空" << endl;
		}
		else
		{
			root->display(1);
		}
	}

	//查找节点 递归方法 
	//递归的部分需要传入根节点(BSTNode)
	//外部以Element类型加载数据,故写两个函数,改为一个Element端口
	template<typename T>
	BSTNode<T>*BST<T>::BST_Search(const Element<T>&node)
	{
		return BST_Search(root, node);
	}

	template<typename T>
	BSTNode<T>*BST<T>::BST_Search(BSTNode<T>*b, const Element<T>&node)
	{
		if (b == NULL)
		{
			return NULL;
		}
		if (node.key == b->data.key)
		{
			return b;
		}
		else if (node.key < b->data.key)
		{
			return BST_Search(b->leftChild, node);
		}
		else
		{
			return BST_Search(b->rightChild, node);
		}
	}
	
	//非递归查找 迭代方式实际中对大多数计算机更有效
	template<typename T>
	BSTNode<T>*BST<T>::BST_Search_Iterator(const Element<T>&node)
	{
		BSTNode<T>*t = root;
		while (t)
		{
			if (node.key == t->data.key)
			{
				return t;
			}
			else if (node.key < t->data.key)
			{
				t = t->leftChild;
			}
			else
			{
				t = t->rightChild;
			}
		}
	}

	//删除节点
	template<typename T>
	bool BST<T>::Delete_Node(const Element<T>&node)
	{
		if (root == NULL)
		{
			cout << "root == NULL" << endl;
			return 0;
		}
		BSTNode<T> *del = NULL;
		BSTNode<T> *pcurr = root;
		BSTNode<T> *parent = NULL;
		while (pcurr != NULL && pcurr->data.key != node.key)//先找到
		{
			if (node.key < pcurr->data.key)
			{
				parent = pcurr;
				pcurr = pcurr->leftChild;
			}
			if (node.key > pcurr->data.key)
			{
				parent = pcurr;
				pcurr = pcurr->rightChild;
			}
		}
		if (pcurr == NULL)//找了一遍没找到
		{
			return false;
		}
		if (pcurr->leftChild == NULL)//只有右孩子
		{
			if (pcurr == root)//如果是根节点 则根节点移动到右孩子即可
				root = root->rightChild;
			else if (pcurr == parent->leftChild)//若待删节点是parent左孩子
			{
				parent->leftChild = pcurr->rightChild;
			}
			else if (pcurr == parent->rightChild)//若待删除节点是parent右孩子
			{
				parent->rightChild = pcurr->rightChild;
			}
			del = pcurr;
		}
		else if (pcurr->rightChild == NULL)//只有左孩子
		{
			if (pcurr == root)
				root = root->leftChild;
			else if (pcurr == parent->leftChild)
			{
				parent->leftChild = pcurr->leftChild;
			}
			else
			{
				parent->rightChild = pcurr->leftChild;
			}
			del = pcurr;
		}
		else//既有左孩子又有右孩子 找到右子树最小(最左)的元素替换,在按照以上方式删除
		{
			//找到最左边的节点
			BSTNode<T> *left = pcurr->rightChild;
			parent = pcurr;
			while (left->leftChild)
			{
				parent = left;
				left = left->leftChild;
			}
			del = left;
			pcurr->data.key = left->data.key;//交换节点的值
			if (parent->leftChild == left)
			{
				parent->leftChild = left->rightChild;
			}
			else//当pcurr只有一个右节点时,left是parent的右子树
			{
				parent->rightChild = left->rightChild;
			}
		}
		delete del;
	}


	//中序遍历
	template<typename T>
	void BST<T>::midOrder()
	{
		midOrder(root);
	}
	template<typename T>
	void BST<T>::midOrder(BSTNode<T>*root)
	{
		if (root == NULL)
		{
			return;
		}
		midOrder(root->leftChild);
		cout<<root->getElement().key<<" "<<root->getElement().name<<"\t";
		midOrder(root->rightChild);
	}

	//返回树中最小的节点
	template<typename T>
	BSTNode<T>*	BST<T>::MinMum()
	{
		BSTNode<T>*tmp = root;
		while (tmp->leftChild)
		{
			tmp = tmp->leftChild;
		}
		return tmp;
	}

	//返回树种最大的节点
	template<typename T>
	BSTNode<T>*	BST<T>::MaxMum()
	{
		BSTNode<T>*tmp = root;
		while (tmp->rightChild)
		{
			tmp = tmp->rightChild;
		}
		return tmp;
	}

template<typename T>
	BST<T>::~BST()
	{
		delTree(root);
	}
	template<typename T>
	void BST<T>::delTree(BSTNode<T>*root)
	{
		BSTNode<T>*tmpLeft = NULL;
		BSTNode<T>*tmpRight = NULL;
		while (root)
		{
			tmpLeft = root->leftChild;
			tmpRight = root->rightChild;
			delete root;
			delTree(tmpLeft);
			delTree(tmpRight);
		}
	}

测试文件

#include"dm_04_BST.hpp"
#include"iostream"
#include"cmath"
using namespace std;

void main()
{
	Element<int> a,b,c,d,e,f,g,h;
	BST<int> tree;
	a.key = 5; a.name = 'a'; cout << tree.BST_insert(a) << endl;
	b.key = 2; b.name = 'b'; cout << tree.BST_insert(b) << endl;
	c.key = 7; c.name = 'c'; cout << tree.BST_insert(c) << endl;
	d.key = 1; d.name = 'd'; cout << tree.BST_insert(d) << endl;
	e.key = 6; e.name = 'e'; cout << tree.BST_insert(e) << endl;
	f.key = 8; f.name = 'f'; cout << tree.BST_insert(f) << endl;
	g.key = 4; g.name = 'g'; cout << tree.BST_insert(g) << endl;
	h.key = 0; h.name = 'h'; cout << tree.BST_insert(h) << endl;
	//打印二叉树,从根节点开始,递归打印左右	
	tree.display();

	cout << "递归搜索Key" << endl;
	cout<<tree.BST_Search(e)->getElement().key<<endl;

	cout << "迭代搜索Key" << endl;
	cout << tree.BST_Search_Iterator(e)->getElement().key<<endl;

	cout << "搜索二叉树中序遍历恰好是从小到大" << endl;
	tree.midOrder();

	cout << "二叉搜索树中键值最大的" << endl;
	Element<int> max = tree.MaxMum()->getElement();
	cout << "key: " << max.key << " name: " << max.name << endl;
	cout << "二叉搜索树中键值最小的" << endl;
	Element<int> min = tree.MinMum()->getElement();
	cout << "key: " << min.key << " name: " << min.name << endl;

	cout <<endl<< "删除节点d" << endl;
	tree.Delete_Node(d);
	tree.midOrder();
	cout << endl;
	system("pause");
}

 

运行结果

二叉搜索树

二叉搜索树,在一定条件下会退化为链表,失去二叉搜索树的优点,构建二叉搜索树应当随机构建二叉搜索树,n个节点n!中排序,每一种排序等概。

平衡二叉树红黑树可以解决这个问题。

有些颓废,希望自己能珍惜时间。

相关标签: 二叉搜索树