C++实现搜索二叉树

二叉查找树(英语:Binary Search Tree),也称二叉搜索树、有序二叉树(英语:ordered binary tree),排序二叉树(英语:sorted binary tree),是指一棵空树或者具有下列性质的二叉树:

  • 任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
  • 任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
  • 任意节点的左、右子树也分别为二叉查找树;
  • 没有键值相等的节点。
#pragma once

template<class K, class V>
struct BSTreeNode
{
	K _key;
	V _value;
	BSTreeNode<K, V>* _left;
	BSTreeNode<K, V>* _right;

	BSTreeNode(const K& key, const V& value)
		:_key(key)
		,_value(value)
		,_left(NULL)
		,_right(NULL)
	{}
};

template<class K, class V>
class BSTree
{
	typedef BSTreeNode<K, V> Node;
public:
	BSTree()
		:_root(NULL)
	{}

	bool Insert(const K& key, const V& value)
	{
		if (NULL == _root)//若为空树
		{
			_root = new Node(key, value);
			return true;
		}

		Node* parent = NULL;
		Node* cur = _root;

		//确定插入节点的位置
		while (cur)
		{
			if (key < cur->_key)
			{
				parent = cur;
				cur = cur->_left;
			}
			else if (key > cur->_key)
			{
				parent = cur;
				cur = cur->_right;
			}
			else//已经存在key
			{
				return false;
			}
		}

		//插入节点
		if (key > parent->_key)
			parent->_right = new Node(key, value);
		else
			parent->_left = new Node(key, value);
	}

	//Insert递归写法
	bool InsertR(const K& key, const V& value)
	{
		return _InsertR(_root, key, value);
	}

	bool _InsertR(Node*& root, const K& key, const V& value)
	{
		if (NULL == root)
		{
			root = new Node(key, value);
			return true;
		}

		if (key > root->_key)
			return _InsertR(root->_right, key, value);
		else if (key < root->_key)
			return _InsertR(root->_left, key, value);
		else
			return false;
	}

	Node* Find(const K& key)
	{
		Node* cur = _root;

		while (cur)
		{
			if (key > cur->_key)
				cur = cur->_right;
			else if (key < cur->_key)
				cur = cur->_left;
			else
				return cur;
		}

		return NULL;
	}

	//Find递归写法
	Node* FindR(const K& key)
	{
		return _FindR(_root, key);
	}

	Node* _FindR(Node* root, const K& key)
	{
		if (NULL == root)
			return NULL;

		if (key > root->_key)
			return _FindR(root->_right, key);
		else if (key < root->_key)
			return _FindR(root->_left, key);
		else
			return root;
	}

	bool Remove(const K& key)
	{
		Node* parent = NULL;
		Node* cur = _root;

		//确定删除节点的位置
		while (cur)
		{
			if (key > cur->_key)
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (key < cur->_key)
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				break;
			}
		}

		if (NULL == cur)//没有该节点
		{
			return false;
		}

		Node* del;
		if (NULL == cur->_left)//删除节点的左孩子为空
		{
			del = cur;

			//删除的节点为根节点
			if (NULL == parent)
			{
				_root = _root->_right;
			}
			else
			{
				if (cur == parent->_left)
					parent->_left = cur->_right;
				else
					parent->_right = cur->_right;
			}
		}
		else if (NULL == cur->_right)//删除节点的右孩子为空
		{
			del = cur;

			if (NULL == parent)
			{
				_root = _root->_left;
			}
			else
			{
				if (cur == parent->_left)
					parent->_left = cur->_right;
				else
					parent->_right = cur->_left;
			}
		}
		else//删除节点的左右孩子都不为空,找右子树最左节点代替该节点删除
		{
			parent = cur;

			Node* leftmost = cur->_right;
			while (leftmost->_left)
			{
				parent = leftmost;
				leftmost = leftmost->_left;
			}

			del = leftmost;

			cur->_key = leftmost->_key;
			cur->_value = leftmost->_value;

			if (leftmost == parent->_left)
				parent->_left = leftmost->_right;
			else
				parent->_right = leftmost->_right;
		}

		return true;
	}

	//Remove递归写法
	bool RemoveR(const K& key)
	{
		return _RemoveR(_root, key);
	}

	bool _RemoveR(Node*& root, const K& key)
	{
		if (NULL == root)
			return false;

		if (key > root->_key)
		{
			return _RemoveR(root->_right, key);
		}
		else if (key < root->_key)
		{
			return _RemoveR(root->_left, key);
		}
		else
		{
			Node* del = root;

			if (NULL == root->_left)
			{
				root = root->_right;
			}
			else if (NULL == root->_right)
			{
				root = root->_left;
			}
			else
			{
				Node* leftmost = root->_right;
				while (leftmost->_left)
				{
					leftmost = leftmost->_left;
				}

				swap(root->_key, leftmost->_key);
				swap(root->_value, leftmost->_value);

				return _RemoveR(root->_right, key);
			}

			delete del;
		}

		return true;
	}

	//中序遍历递归写法
	void InOrder()
	{
		_InOrder(_root);
	}

	void _InOrder(Node* root)
	{
		if (NULL == root)
			return;

		_InOrder(root->_left);
		cout<<root->_key<<" ";
		_InOrder(root->_right);
	}

protected:
	Node* _root;
};

void Test()
{
	BSTree<int, int> t;
	int a[] = {5, 3, 4, 1, 7, 8, 2, 6, 0, 9};
	for (size_t i = 0; i < sizeof(a)/sizeof(a[0]);++i)
	{
		t.InsertR(a[i], i);
	}

	cout<<t.FindR(8)->_key<<endl;
	cout<<t.FindR(5)->_key<<endl;
	cout<<t.FindR(9)->_key<<endl;

	t.RemoveR(8);
	t.RemoveR(7);
	t.RemoveR(9);
	t.RemoveR(6);
	t.RemoveR(5);
	t.RemoveR(3);
	t.RemoveR(1);
	t.RemoveR(4);
	t.RemoveR(0);
	t.RemoveR(2);

	t.InOrder();
}

时间: 2024-11-12 21:03:22

C++实现搜索二叉树的相关文章

判断一个数列是不是搜索二叉树后续遍历输出的结果

剑平面阿里被问到这个,刚开始画了下看有什么性质,乱蒙了几个都被推翻了,初始感觉就是要O(n)的,因为印象中BST的构树都可以O(nlogn)搞定.然后剑平说最后一个数肯定是根节点,一下反应过来了,就是二分出间隔点然后两边递归判断,不过这好像还是构树的思路,可以把整棵树构造出来.然后剑平说不是二分,直接遍历.不科学啊,明显的二分,然后去网上搜一下,都是遍历的,O(n^2)的吧.想了想,二分是当做合法的情况来构树的,不合法怎么判断?构造出搜索二叉树后中序遍历一下不就行了么,妥妥的O(nlogn)吧.

搜索二叉树

二叉查找树(BinarySearch Tree,也叫二叉搜索树,或称二叉排序树Binary Sort Tree)或者是一棵空树,或具有如下性质: 每个节点都有一个作为搜索依据的关键码(key),所有节点的关键码互不相同. 左子树上所有节点的关键码(key)都小于根节点的关键码(key). 右子树上所有节点的关键码(key)都大于根节点的关键码(key). 左右子树都是二叉搜索树. 二叉搜索树相关操作: (1)插入:新节点 在二叉查找树中插入新结点,要保证插入新结点后仍能满足二叉查找树的性质.插入

java递归方法建立搜索二叉树,具备查找关键字,插入新节点功能

二叉排序树的定义: 二叉排序树满足以下三个性质(BST性质): <1>若它的左子树非空,则左子树上所有节点的值均小于根节点的值 <2>若它的右子树非空,则右子树上所有节点的值均大于根节点的值 <3>左,右子树本身又各是一棵二叉排序树 根据二叉排序树的BST性质,可以说二叉排序树每个节点上的值(或称关键字)都是唯一的,并且二叉排序树以中序遍历输出的结果必然是一个有序的递增序列. 如下图所示: 用递归方法建立二叉排序树,减少了繁复的比较程序,效率较高.只需要知道每个节点的值

数据结构--‘搜索二叉树’

'二叉树'是数据结构中比较重要的一部分,这里主要讨论一下'搜索二叉树',针对'搜索二叉树的插入.删除和查找节点进行分情况讨论,希望能够帮助读者更加的理解搜索二叉树的原理. ◆搜索二叉树的性质: 1.每个节点都有一个一个作为搜索依据的关键码,所有节点的关键码都不相同. 2.左子树所有的关键码(key)都小于根节点的关键码(key). 3.右子树所有的关键码(key)都大于根节点的关键码(key). 4.左.右子树都是二叉搜索树. 实现'搜索二叉树'的节点结构可以实现为K形式,和K.V形式,若实现K

【数据结构】搜索二叉树的(递归与非递归)实现,包括:增Insert,删Remove,查Find

搜索二叉树,是二叉树一种特殊的结构. 特点: (1)每个节点都有一个关键码,并且关键码不重复. (2)左子树上的每个节点的关键码都小于根节点的关键码. (3)右子树上的每个节点的关键码都大于根节点的关键码. (4)左右子树都是搜索二叉树. 下面,为方便大家理解,我举例画一个搜索二叉树,如下: 代码见下: #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> using namespace std; //搜索二叉树的节点结构 template&

《github一天一道算法题》:搜索二叉树接口实现大合集

读书.思考.写代码! 说明: (1)这里实现了搜索二叉树的全部常用操作 (2)限于时间和精力,实现的较为粗糙,内存泄露.成员变量访问控制.返回类型.异常安全等没有照顾的到 (3)一切实现的手段都是贴近底层操作,关注原理.以后可能对推倒重来,实现一个完备的接口系统. /********************************************* * [email protected] * 题目:二叉树接口实现大合集 * 具体:二叉树的创建.插入.最大值.最小值.前中后序递归遍历与非递

搜索二叉树的操作

搜索二叉树的数据结构定义: /*二叉搜索树的结构定义*/ typedef struct TreeNode* SearchTree; typedef struct TreeNode* Position; struct TreeNode { int Element; SearchTree Left; SearchTree Right; } 搜索二叉树的插入操作: SearchTree Insert(int x, SearchTree T) { if(T == NULL)//空树 { T = mall

搜索二叉树应用——简单字典实现

搜索二叉树基本概念请看上篇博客这两个问题都是典型的K(key)V(value)问题,我们用KV算法解决. 判断一个单词是否拼写正确:假设把所有单词都按照搜索树的性质插入到搜索二叉树中,我们判断一个单词拼写是否正确就是在树中查找该单词是否存在(查找key是否存在). 结构声明下 typedef char* KeyType; typedef struct BSTreeNode { struct BSTreeNode *_left; struct BSTreeNode *_right; KeyType

搜索二叉树之字典实现

利用搜索二叉树判断一个单词是否拼写正确: 假设把所有单词都按照搜索树的性质插入到搜索二叉树中,我们判断一个单词拼写是否正确就是在树中查找该单词是否存在(查找key是否存在). /***************************************** *Date:2018年3月26日14:42:54 *Author: Meng *WebSite:msyci.com *QQ:3515955122 *****************************************/ # i

栈和队列----将搜索二叉树转换成双向链表

将搜索二叉树转换成双向链表 对于BST 来说,有本身的值域,有指向左孩子和右孩子的两个指针:对于双向链表来说,有本身的值域,有指向上一个节点和下一个节点的指针.将这个BST转换成双向链表,对于每一个节点来说,原来的right指针等价于转换后的next指针,原来的left指针等价于转换后的left指针,最后返回双向链表的头节点. [解析] 用队列等容器收集二叉树 中序遍历的结果的方法.其时间复杂度是O(N),空间复杂度是O(N). 1. 生成一个队列,记为queue,按照二叉树的中序遍历的顺序,将