数据结构-二叉搜索树

数据结构-二叉搜索树

二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树

原理

二叉排序树的查找过程和次优 二叉树类似,通常采取 二叉链表作为 二叉排序树存储结构中序遍历二叉排序树可得到一个 关键字的有序序列,一个无序序列可以通过构造一棵二叉排序树变成一个有序序列,构造树的过程即为对无序序列进行排序的过程。每次插入的新的结点都是二叉排序树上新的 叶子结点,在进行插入操作时,不必移动其它结点,只需改动某个结点的 指针,由空变为非空即可。搜索,插入,删除的复杂度等于树高,O(log(n)).

算法实现

1 二叉排序树的查找算法
2 在 二叉排序树插入结点的算法
3 在 二叉排序树删除结点的算法

查找算法

在二叉排序树b中查找x的过程为:
若b是空树,则搜索失败,否则:
若x等于b的根结点的数据域之值,则查找成功;否则:
若x小于b的根结点的数据域之值,则搜索左子树;否则:
查找右子树。
#include <iostream>
#include <string>
using namespace std;
template <typename T>
struct binaryTreeNode
{
	T element;// pair<const K,E> element;
	binaryTreeNode<T>* leftChild;
	binaryTreeNode<T>* rightChild;
	//没有初始化数据域
	binaryTreeNode()
	{
		leftChild = rightChild = nullptr;
	}
	//都初始化
	binaryTreeNode(const T& element) :element(element)
	{
		leftChild = rightChild = nullptr;
	}
	//构造函数--->初始化参数列表的方式
	binaryTreeNode(const T& element, binaryTreeNode<T>* leftChild, binaryTreeNode<T>* rightChild) :element(element)
	{
		this->leftChild = leftChild;
		this->rightChild = rightChild;
	}
};
template <class K,class E>
class binarySearchTree
{
public:
	//构造函数
	binarySearchTree()
	{
		treeSize = 0;
		root = nullptr;
	}
	//两个万金油函数
	int size()const 
	{
		return treeSize;
	}
	bool empty()const
	{
		return treeSize == 0;
	}
	//查找
	pair<const K, E>* find(const K& theKey)const;
	//构建--->插入结点的过程
	//插入--->数对  +  也可以用指针
	void insert(const pair<const K, E>& thePair)
	{
		//插入-->找到指定位置
		//1:树为空
		//2.键已经存在,  选择 可以覆盖,选择放那一边都可以
		//键:比较准则, 值:存放数据
		binaryTreeNode<pair<const K, E>>* p = root;   //移动指针
		binaryTreeNode<pair<const K, E>>* pp = nullptr;		 //表示p的父节点
		//找到合适的位置
		while (p != nullptr)
		{
			pp = p;		//记录p的父节点
			if (thePair.first < p->element.first)
			{
				p = p->leftChild;
			}
			else if (thePair.first>p->element.first)
			{
				p = p->rightChild;
			}
			else
			{
				//first 已经存在树中,直接修改second
				p->element.second = thePair.second;
				return;
			}
		}
		//创建插入的结点--调用构造函数
		binaryTreeNode<pair<const K, E>>* newNode = new binaryTreeNode<pair<const K, E>>(thePair);
		//插入的位置插在pp下面
		if (root != nullptr)
			if (thePair.first < pp->element.first)
				pp->leftChild = newNode;
			else
				pp->rightChild = newNode;
		else //树为空 ,新的结点就要成为根结点
			root = newNode;
		treeSize++;
	}
	//打印当前节点中的值
	void visit(binaryTreeNode<pair<const K, E>>* Node)
	{
		//map中讲过
		cout << Node->element.first << ":" << Node->element.second << "\t";
	}
	//中序遍历打印树
	void printNode(binaryTreeNode<pair<const K, E>>* root)
	{
		if (root != nullptr)
		{
			printNode(root->leftChild);
			visit(root);
			printNode(root->rightChild);
		}
	}
	void printTree()
	{
		printNode(root);
	}
	//通过键(first)去删除
	void erase(const K& theKey);


protected:
	//T -->pair<const K,E>
	binaryTreeNode<pair<const K, E>>* root;//指向树根结点
	int treeSize;		//树的结点个数
};

//查找: 通过数对中键去查找
template<typename K,typename E>
pair<const K, E>* binarySearchTree<K, E>::find(const K& theKey)const
{
	//定义一个移动的指针去查找
	binaryTreeNode<pair<const K, E>>* p = root;
	while (p != nullptr)
	{
		//如果当前节点比他大 往左边找
		if (theKey < p->element.first)
			p = p->leftChild;
		//如果当前节点比他小,往右边找
		else if (theKey>p->element.first)
			p = p->rightChild;
		else//相等
			return &p->element;  //return 的类型要和函数的返回值类型(pair<const K,E>*)一致
	}
}
template <typename K,typename E>
void  binarySearchTree<K, E>::erase(const K& theKey)
{
	binaryTreeNode<pair<const K, E>>* p = root;	//从根开始找
	binaryTreeNode<pair<const K, E>>* pp = nullptr; //p的父节点
	//找到要删除的位置
	while (p != nullptr&&p->element.first != theKey)
	{
		pp = p;
		if (theKey < p->element.first)
			p = p->leftChild;
		else if (theKey>p->element.first)
			p = p->rightChild;
	}
	if (p == nullptr)
	{
		cout << "未找到指定位置,无法删除" << endl;
		system("pause");
		return;	//未找到,无法删除
	}
	//有两个孩子的时候
	if (p->leftChild != nullptr&&p->rightChild != nullptr)
	{
		//找到调整位置的那个结点
		binaryTreeNode<pair<const K, E>>* s = p->leftChild; //从删除结点左边去找
		binaryTreeNode<pair<const K, E>>* ps = p;	//s的父节点
		//左边找最右边,并记录要调整的结点的父节点
		while (s->rightChild != nullptr)
		{
			ps = s;
			s = s->rightChild;
		}
		//不能直接赋值的方式做--->const 的存在 所以要使用构造的方式
		binaryTreeNode<pair<const K, E>>* q = new binaryTreeNode<pair<const K, E>>
			(s->element, p->leftChild, p->rightChild);
		if (pp == nullptr)  //p就是根结点
			root = q;		//拿上来的那个结点要成为根结点
		//删除p结点上面还有结点
		//p不是根结点,存在父节点pp
		//确定q结点放在pp左边还是右边
		else if (p == pp->leftChild)//删除结点p在父节点的左边  ,q放在pp的左边
			pp->leftChild = q;
		else//删除结点p在父节点的右边  ,q放在pp的右边
			pp->rightChild = q;
		if (ps == p) //q=ps
			pp = q;
		else   //同样的方法删除多余的结点
			pp = ps;
		delete p;
		p = s;
	}
	//p只有一个孩子的,把孩子结点指针存放c
	binaryTreeNode<pair<const K, E>>* c;
	if (p->leftChild != nullptr)
		c = p->leftChild;
	else
		c = p->rightChild;
	//删除s也就 就是p
	if (root == p)
		root =c;
	else
	{
		if (p == pp->leftChild)
			//让删除p的父节点的指针指向p的下一个结点
			pp->leftChild = c;
		else
			pp->rightChild = c;
	}
	treeSize--;
	delete p;
}

int main()
{
	binarySearchTree<int, string> myBST;
	myBST.insert(pair<int, string>(1, "初心"));
	myBST.insert(pair<int, string>(7, "Mingle"));
	myBST.insert(pair<int, string>(2, "Honey"));
	myBST.insert(pair<int, string>(5, "村雨"));
	myBST.insert(pair<int, string>(6, "圆圆"));
	myBST.insert(pair<int, string>(4, "柠檬"));
	myBST.printTree();
	cout << endl;
	myBST.erase(1);
	cout << endl;
	myBST.printTree();
	myBST.erase(5);
	cout << endl;
	myBST.printTree();
	system("pause");
	return 0;
}
点击加入学习乐群

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值