Search binary tree [C++]

binary search tree

Binary search tree is also called binary sorting tree. It is either an empty tree or a binary tree with the following properties:

If its left subtree is not empty,
the values ​​of all nodes on the left subtree are less than the value of the root node.

If its right subtree is not empty,
then the values ​​of all nodes on the right subtree are greater than the value of the root node.

Its left and right subtrees are also binary search trees respectively.

Insert image description here

Simulation implementation of binary search tree

Constructor

	BSTree()
		:_root(nullptr)
	{
    
    

	}

copy constructor

	BSTree(const  BSTree<K>& t)
			//BSTree(  BSTree<K>  *this ,  const  BSTree<K> & t)
			//t1 =t 
		{
    
    
			_root = Copy(t._root);
		}
		
			private:
		Node* Copy(Node* root)
		{
    
    
			if (root == nullptr)
			{
    
    
				return nullptr;
			}
			Node* copyNode = new Node(root->_key);
			//递归 
			copyNode->_left = Copy(root->_left);
			copyNode->_right = Copy(root->_right);
			return  copyNode;

		}

assignment operator overloaded function

	//赋值重载 
		BSTree<K>& operator= (BSTree<K>& t)
			//t1 = t
			//深拷贝
		{
    
    
			swap(_root, t._root);
			return *this;
		}

destructor

~BSTree()
		{
    
    
			Destroy(_root);
		}
		
		private:
				void Destroy(Node*& root) //引用的目的:将每个节点释放后同时置空
		{
    
    
			//后序遍历 
			if (root == nullptr)
			{
    
    
				return;
			}
			Destroy(root->_left);
			Destroy(root->_right);
			delete root;
			root = nullptr;
		}

Insert

Core idea:

If it is an empty tree, the inserted node is directly used as the root node of the binary search tree.

If the tree is not empty, the node will be inserted according to the properties of the binary search tree.
If the value of the node to be inserted < the value of the root node, the node needs to be inserted into the left subtree.
If the value of the node to be inserted > the value of the root node, the node needs to be inserted into the right subtree.
If the value of the node to be inserted is equal to the value of the root node, the insertion fails.

cycle

bool Insert(const K & key )
	{
    
    
		//空树
		if (_root == nullptr)
		{
    
    
		 _root = new Node(key);
		 return true;
		}

		//不是空树

		Node* parent = nullptr;//找到父节点
		Node* cur = _root;
		while (cur)
		{
    
    
			//比较
			if (cur->_key < key)
			{
    
    
				//往右子树走
				parent = cur;
				cur  = cur->_right;
			 }
			else if (cur->_key > key)
			{
    
    
				//往左子树走
				parent = cur;
				cur = cur->_left;
			}
			else
			{
    
    
				return false;
			}
	
		}

		//插入节点
		cur = new Node(key);
			
		
			//不知道parent在那一边,需要进一步判断
			if (parent->_key > key)
			{
    
    
				//parent在左边
				parent->_left = cur;
			}
			else if (parent->_key < key)
			{
    
    
				//parent在右边
				parent->_right = cur;

			}
			else
			{
    
    
				return false;
			}
		

		return true;
	}

recursion

	bool InsertR(const K& key)//递归版本
		{
    
    
			return _InsertR(_root, key);
		}
		private:
			bool _InsertR(Node*& root, const K& key) //引用的目的:不用找父节点,不需要用父节点比较大小
		{
    
    
			//结束条件
			if (root == nullptr)
			{
    
    
				root = new Node(key);
				return true;
			}
			//往左子树走
			if (root->_key > key)
			{
    
    
				return _InsertR(root->_left, key);
			}
			//往右子树走
			else if (root->_key < key)
			{
    
    
				return _InsertR(root->_right, key);

			}
			else
			{
    
    
				return false;
			}
		}

Erase

First find the node that needs to be deleted.
The node that needs to be deleted may have three situations:
1. The left subtree of the node to be deleted is empty (the left and right subtrees of the node to be deleted are both empty and included).
2. The right subtree of the node to be deleted is empty.

In both cases 1 and 2, the deleted node has only one child.

3. The left and right subtrees of the node to be deleted are not empty.
Use the replacement method to handle the third situation: the largest node of the left subtree is the rightmost node, or the smallest node of the right subtree is the leftmost node, and delete the replaced node.

cycle

	bool Erase(const K& key)
	{
    
    
		Node* parent = nullptr;//待删除节点的父节点
		Node* cur = _root;//待删除的节点

		//不是空树
		while (cur)
		{
    
    
			//往左边走
			if (cur->_key > key)
			{
    
    
				parent = cur;
				cur = cur->_left;
			}
			//往右边走
			else if (cur->_key < key)
			{
    
    
				parent = cur;
				cur = cur->_right;
			}
			//找到待删除的节点
			else
			{
    
    
				//待删除节点的左子树为空 ,即一个孩子的情况
				if (cur->_left == nullptr)
				{
    
    
					  //待删除节点是根节点
					if (cur == _root)
					{
    
    
						//将根节点改为待删除节点的右孩子
						_root = cur->_right;
					}
					//待删除节点不是根节点,并且此时parent不为nullptr
					else
					{
    
    
						if (parent->_right == cur)
						{
    
    
							parent->_right = cur->_right;
						}
						else//parent->_left ==cur
						{
    
    
							parent->_left = cur->_right;
						}
					}
					
				}
				//待删除节点的右子树为空 ,即一个孩子的情况
				else if (cur->_right == nullptr)
				{
    
    
					//待删除节点是根节点
					if (cur == _root)
					{
    
    
						//将根节点改为待删除节点的左孩子
						_root = cur->_left;
					}
					//待删除节点不是根节点,并且此时parent不为nullptr
					else
					{
    
    
						if (parent->_right == cur)
						{
    
    
							parent->_right = cur->_left;
						}
						else//parent->_left==cur
						{
    
    
							parent->_left = cur->_left;
						}
					}
				} 

				else //待删除的节点的左右孩子都不为空 (替换法:左子树的最大节点即最右节点,或者右子树的最小节点即最左节点,并且将替换的节点删除)
				{
    
    
					//替换法

					//找替代节点
					Node* parent = cur;
					//找左子树的最大节点
					Node* leftMax = cur->_left;
					
					while (leftMax->_right)
					{
    
    
						parent = leftMax; //记录leftMax的父节点,防止删除leftMax时找不到该节点位置 
						//一直往右子树找
						leftMax = leftMax->_right;
					}
					//左子树的最大节点和待删除节点替换
					swap(cur->_key, leftMax->_key);
					//重新改变链接关系
					 
					//特殊情况 
					if (parent->_left == leftMax)
					{
    
    
						parent->_left = leftMax->_left;
					}
					else//普通情况 
					{
    
    
						parent->_right = leftMax->_left;
						//parent->_right =nullptr;
					}
					cur = leftMax;
				}
				//删除左子树的最大节点
				delete cur;
				return true;
			}
			
		}
		return false;
	}

recursion

	bool EraseR(Node* _root, const K& key)//递归版本
		{
    
    
			return _EraseR(_root, key);
		}
		private:
				bool _EraseR(Node*& root, const K& key)//引用的目的:不用找父节点,不需要用父节点比较大小
		{
    
    
			//结束条件
			if (root == nullptr)
			{
    
    
				return false;
			}
			//往左树找
			if (root->_key > key)
			{
    
    
				return _EraseR(root->_left, key);
			}
			//往右树找
			else if (root->_key < key)
			{
    
    
				return _EraseR(root->_right, key);
			}
			else//找到,开始删除
			{
    
    
				Node* del = root;
				//待删除节点的左子树为空 ,即一个孩子的情况
				if (root->_left == nullptr)
				{
    
    
					root = root->_right;
				}
				//待删除节点的右子树为空 ,即一个孩子的情况
				else if (root->_right == nullptr)
				{
    
    
					root = root->_left;
				}
				//待删除的节点的左右孩子都不为空 (替换法:左子树的最大节点即最右节点,或者右子树的最小节点即最左节点,并且将替换的节点删除)
				else
				{
    
    
					//找左子树最大节点
					Node* leftMax = root->_left;
					//一直往左边找,直到找到左子树最大节点
					while (root->_left)
					{
    
    
						root = root->_left;
					}
					//将左子树最大节点与被删除节点替换
					swap(leftMax->_key, root->_key);

					return _EraseR(root, key);
				}

				delete del;//?
				return true;

			}


		}

Find

cycle

	bool Find(const K & key)
	{
    
    
		Node* cur = _root;
		while (cur)
		{
    
    
			if (cur->_left > key)
			{
    
    
				cur = cur->_left;
			}
			else if (cur->_left < key)
			{
    
    
				cur = cur->_right;
			}
			else
			{
    
    
				return false;
			}
			return true;
		}
	}

recursion

	bool FindR(Node* _root, const K& key)//递归版本
		{
    
    
			return _FindR(_root, key);
		}
		private:
		bool  _FindR(Node* root, const K& key)
		{
    
    
			//结束条件
			if (root == nullptr)
			{
    
    
				return false;
			}

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

Application of Binary Search Tree

K model

K model, that is, only key is used as the key code, and only the key is stored in the structure, and the key code is the value that needs to be searched.

For example: given a word, determine whether the word is spelled correctly. The specific methods are as follows:

	void TestBSTree1()
	{
    
    
		BSTree<string, string > dict;
		dict.InsertR("insert", "插入");
		dict.InsertR("sort", "排序");
		dict.InsertR("right", "右边");
		dict.InsertR("date", "日期");
		
		string str;
		while (cin>>str)
		{
    
    
			
			auto * ret  = dict.FindR(str);
			//auto ret = dict.FindR(str);
			if (ret)
			{
    
    
				cout << ret->_value << endl;
			}
			else
			{
    
    
				cout << "无此单词" << endl;
			}
		}
	}

KV model

In the KV model, for each key key, there is a corresponding value, that is, a key-value pair of <key, value>.

The English-Chinese dictionary is the correspondence between English and Chinese, that is, <word, Chinese> constitutes a key-value pair. The specific method is as follows

1. Construct a binary search tree using <word, Chinese meaning> as the key-value pair. Note: Binary search trees need to be compared, and only keys are compared when comparing key-value pairs.
2. When querying English words, just give the English word and you can quickly find its corresponding Chinese meaning.

Complete code

Normal version

#pragma once 

template <class K>

struct BSTreeNode
{
    
    
	BSTreeNode<K>* _left;
	BSTreeNode<K>* _right;
	K _key;
	BSTreeNode(const K & key)
		:_left(nullptr)
		,_right(nullptr)
		,_key(key)
	{
    
    

	}
};

template <class K> 
class BSTree
{
    
    
	typedef  BSTreeNode<K> Node;
public:
	BSTree()
		:_root(nullptr)
	{
    
    

	}

	bool Insert(const K & key )
	{
    
    
		//空树
		if (_root == nullptr)
		{
    
    
		 _root = new Node(key);
		 return true;
		}

		//不是空树

		Node* parent = nullptr;//找到父节点
		Node* cur = _root;
		while (cur)
		{
    
    
			//比较
			if (cur->_key < key)
			{
    
    
				//往右子树走
				parent = cur;
				cur  = cur->_right;
			 }
			else if (cur->_key > key)
			{
    
    
				//往左子树走
				parent = cur;
				cur = cur->_left;
			}
			else
			{
    
    
				return false;
			}
	
		}

		//插入节点
		cur = new Node(key);
			
		
			//不知道parent在那一边,需要进一步判断
			if (parent->_key > key)
			{
    
    
				//parent在左边
				parent->_left = cur;
			}
			else if (parent->_key < key)
			{
    
    
				//parent在右边
				parent->_right = cur;

			}
			else
			{
    
    
				return false;
			}
		

		return true;
	}
	bool Find(const K & key)
	{
    
    
		Node* cur = _root;
		while (cur)
		{
    
    
			if (cur->_left > key)
			{
    
    
				cur = cur->_left;
			}
			else if (cur->_left < key)
			{
    
    
				cur = cur->_right;
			}
			else
			{
    
    
				return false;
			}
			return true;
		}
	}

	bool Erase(const K& key)
	{
    
    
		Node* parent = nullptr;//待删除节点的父节点
		Node* cur = _root;//待删除的节点

		//不是空树
		while (cur)
		{
    
    
			//往左边走
			if (cur->_key > key)
			{
    
    
				parent = cur;
				cur = cur->_left;
			}
			//往右边走
			else if (cur->_key < key)
			{
    
    
				parent = cur;
				cur = cur->_right;
			}
			//找到待删除的节点
			else
			{
    
    
				//待删除节点的左子树为空 ,即一个孩子的情况
				if (cur->_left == nullptr)
				{
    
    
					  //待删除节点是根节点
					if (cur == _root)
					{
    
    
						//将根节点改为待删除节点的右孩子
						_root = cur->_right;
					}
					//待删除节点不是根节点,并且此时parent不为nullptr
					else
					{
    
    
						

						if (parent->_right == cur)
						{
    
    
							parent->_right = cur->_right;
						}
						else//parent->_left ==cur
						{
    
    
							parent->_left = cur->_right;
						}


					}
					
				}
				

				//待删除节点的右子树为空 ,即一个孩子的情况
				else if (cur->_right == nullptr)
				{
    
    
					//待删除节点是根节点
					if (cur == _root)
					{
    
    
						//将根节点改为待删除节点的左孩子
						_root = cur->_left;
					}
					//待删除节点不是根节点,并且此时parent不为nullptr
					else
					{
    
    
						
						if (parent->_right == cur)
						{
    
    
							parent->_right = cur->_left;
						}
						else//parent->_left==cur
						{
    
    
							parent->_left = cur->_left;
						}

					}
					
				} 

				else //待删除的节点的左右孩子都不为空 (替换法:左子树的最大节点即最右节点,或者右子树的最小节点即最左节点,并且将替换的节点删除)
				{
    
    
					//替换法

					//找替代节点
					Node* parent = cur;
					//找左子树的最大节点
					Node* leftMax = cur->_left;
					
					while (leftMax->_right)
					{
    
    
						parent = leftMax; //记录leftMax的父节点,防止删除leftMax时找不到该节点位置 
						//一直往右子树找
						leftMax = leftMax->_right;
					}
					//左子树的最大节点和待删除节点替换
					swap(cur->_key, leftMax->_key);
					//重新改变链接关系
					 
					//特殊情况 
					if (parent->_left == leftMax)
					{
    
    
						parent->_left = leftMax->_left;
					}
					else//普通情况 
					{
    
    
						parent->_right = leftMax->_left;
						//parent->_right =nullptr;
					}
					cur = leftMax;


				
				}
				//删除左子树的最大节点
				delete cur;
				return true;
			}
			
		}
		return false;
	}



	//中序遍历
	void InOrder()
	{
    
    
		_InOrder(_root);
		cout << endl;
	}
	
	void _InOrder(Node *root  )
	{
    
    
		if (root == nullptr)
		{
    
    
			return; 
		}
		_InOrder(root->_left);
		cout << root->_key << " ";
		_InOrder(root->_right);

	}


private:
	Node* _root;
};

void TestBSTree1()
{
    
    
	int a[] = {
    
     8, 3, 1, 10, 6, 4, 7, 14, 13 };
	BSTree<int> t;
	for (auto e : a)
	{
    
    
		t.Insert(e);
	}
	t.InOrder();

	t.Erase(4);
	t.InOrder();

	t.Erase(6);
	t.InOrder();

	t.Erase(7);
	t.InOrder();

	t.Erase(3);
	t.InOrder();

	for (auto e : a)
	{
    
    
		t.Erase(e);
	}
	t.InOrder();

}

recursive version

#pragma once 
#include<string>
using namespace std;
namespace key
{
    
    

	template <class K>

	struct BSTreeNode
	{
    
    
		BSTreeNode<K>* _left;
		BSTreeNode<K>* _right;
		K _key;
		BSTreeNode(const K& key)
			:_left(nullptr)
			, _right(nullptr)
			, _key(key)
		{
    
    

		}
	};

	template <class K>
	class BSTree
	{
    
    
	public:
		typedef  BSTreeNode<K> Node;
	public:
		BSTree()
			:_root(nullptr)
		{
    
    

		}

		~BSTree()
		{
    
    
			Destroy(_root);
		}
		//拷贝构造
		BSTree(const  BSTree<K>& t)
			//BSTree(  BSTree<K>  *this ,  const  BSTree<K> & t)
			//t1 =t 
		{
    
    
			_root = Copy(t._root);
		}
		//赋值重载 
		BSTree<K>& operator= (BSTree<K>& t)
			//t1 = t
		{
    
    
			swap(_root, t._root);
			return *this;
		}
		bool EraseR(Node* _root, const K& key)//递归版本
		{
    
    
			return _EraseR(_root, key);
		}

		bool InsertR(const K& key)//递归版本
		{
    
    
			return _InsertR(_root, key);
		}

		bool FindR(Node* _root, const K& key)//递归版本
		{
    
    
			return _FindR(_root, key);
		}

	private:
		Node* Copy(Node* root)
		{
    
    
			if (root == nullptr)
			{
    
    
				return nullptr;
			}
			Node* copyNode = new Node(root->_key);
			//递归 
			copyNode->_left = Copy(root->_left);
			copyNode->_right = Copy(root->_right);
			return  copyNode;

		}

		void Destroy(Node*& root) //引用的目的:将每个节点释放后同时置空
		{
    
    
			//后序遍历 
			if (root == nullptr)
			{
    
    
				return;
			}
			Destroy(root->_left);
			Destroy(root->_right);
			delete root;
			root = nullptr;
		}
		bool _InsertR(Node*& root, const K& key) //引用的目的:不用找父节点,不需要用父节点比较大小
		{
    
    
			//结束条件
			if (root == nullptr)
			{
    
    
				root = new Node(key);
				return true;
			}
			//往左子树走
			if (root->_key > key)
			{
    
    
				return _InsertR(root->_left, key);
			}
			//往右子树走
			else if (root->_key < key)
			{
    
    
				return _InsertR(root->_right, key);

			}
			else
			{
    
    
				return false;
			}
		}

		bool _EraseR(Node*& root, const K& key)//引用的目的:不用找父节点,不需要用父节点比较大小
		{
    
    
			//结束条件
			if (root == nullptr)
			{
    
    
				return false;
			}
			//往左树找
			if (root->_key > key)
			{
    
    
				return _EraseR(root->_left, key);
			}
			//往右树找
			else if (root->_key < key)
			{
    
    
				return _EraseR(root->_right, key);
			}
			else//找到,开始删除
			{
    
    
				Node* del = root;
				//待删除节点的左子树为空 ,即一个孩子的情况
				if (root->_left == nullptr)
				{
    
    
					root = root->_right;
				}


				//待删除节点的右子树为空 ,即一个孩子的情况
				else if (root->_right == nullptr)
				{
    
    
					root = root->_left;
				}
				//待删除的节点的左右孩子都不为空 (替换法:左子树的最大节点即最右节点,或者右子树的最小节点即最左节点,并且将替换的节点删除)
				else
				{
    
    
					//找左子树最大节点
					Node* leftMax = root->_left;
					//一直往左边找,直到找到左子树最大节点
					while (root->_left)
					{
    
    
						root = root->_left;
					}
					//将左子树最大节点与被删除节点替换
					swap(leftMax->_key, root->_key);

					return _EraseR(root, key);
				}

				delete del;//?
				return true;

			}


		}

		bool  _FindR(Node* root, const K& key)
		{
    
    
			//结束条件
			if (root == nullptr)
			{
    
    
				return false;
			}

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



	public:
		//中序遍历
		void InOrder()
		{
    
    
			_InOrder(_root);
			cout << endl;
		}

		void _InOrder(Node* root)
		{
    
    
			if (root == nullptr)
			{
    
    
				return;
			}
			_InOrder(root->_left);
			cout << root->_key << " ";
			_InOrder(root->_right);

		}

	public:
		Node* _root;
	};


	void TestBSTree1()
	{
    
    
		int a[] = {
    
     8, 3, 1, 10, 6, 4, 7, 14, 13 };
		BSTree<int> t;
		for (auto e : a)
		{
    
    
			t.InsertR(e);
		}

		t.InOrder();
		//没有引用,释放了,只是指针没有置空,尤其是根节点_root,我们还能通过他找到
		/*t.Destroy(t._root);*/

		t.EraseR(t._root, 4);
		t.InOrder();

		t.EraseR(t._root, 6);
		t.InOrder();

		t.EraseR(t._root, 7);
		t.InOrder();

		t.EraseR(t._root, 3);
		t.InOrder();

		for (auto e : a)
		{
    
    
			t.EraseR(t._root, e);
		}
		t.InOrder();
	}

	void TestBSTree2()
	{
    
    
		int a[] = {
    
     8, 3, 1, 10, 6, 4, 7, 14, 13 };
		BSTree<int> t;
		for (auto e : a)
		{
    
    
			t.InsertR(e);
		}
		t.InOrder();
		BSTree<int> t1(t);
		t.InOrder();
		t1.InOrder();


	}
}

namespace key_value
{
    
    

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

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

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

		void InOrder()
		{
    
    
			_InOrder(_root);
			cout << endl;
		}

		Node* FindR(const K& key)
		{
    
    
			return _FindR(_root, key);
		}

		bool InsertR(const K& key, const V& value)
		{
    
    
			return _InsertR(_root, key, value);
		}

		bool EraseR(const K& key)
		{
    
    
			return _EraseR(_root, key);
		}

	private:
		bool _EraseR(Node*& root, const K& key)
		{
    
    
			if (root == nullptr)
				return false;

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

				// 1、左为空
				// 2、右为空
				// 3、左右都不为空
				if (root->_left == nullptr)
				{
    
    
					root = root->_right;
				}
				else if (root->_right == nullptr)
				{
    
    
					root = root->_left;
				}
				else
				{
    
    
					Node* leftMax = root->_left;
					while (leftMax->_right)
					{
    
    
						leftMax = leftMax->_right;
					}

					swap(root->_key, leftMax->_key);

					return _EraseR(root->_left, key);
				}

				delete del;
				return true;
			}
		}

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

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

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

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

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

			_InOrder(root->_left);
			cout << root->_key << ":" << root->_value << endl;
			_InOrder(root->_right);
		}
	private:
		Node* _root;
	};

	void TestBSTree1()
	{
    
    
		
		BSTree<string, string > dict;
		dict.InsertR("insert", "插入");
		dict.InsertR("sort", "排序");
		dict.InsertR("right", "右边");
		dict.InsertR("date", "日期");
		
		string str;
		while (cin>>str)
		{
    
    
			
			auto * ret  = dict.FindR(str);
			//auto ret = dict.FindR(str);
			if (ret)
			{
    
    
				cout << ret->_value << endl;
			}
			else
			{
    
    
				cout << "无此单词" << endl;
			}
		}
	}
	void TestBSTree2()
	{
    
    
		string arr[] = {
    
    "西瓜", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };
		BSTree<string, int > countTree;
		for (auto &str : arr)
		{
    
    
			auto ret = countTree.FindR(str);
			if (ret == nullptr)
			{
    
    
				countTree.InsertR(str,1);
			
			}
			else
			{
    
    
				ret->_value++;
			}
		}
		countTree.InOrder();
	}

}

If you think this article is helpful to you, you might as well like it, add it to your favorites, and forward it with your fingers, and give Hud a big following. Each of your support will be converted into motivation for me to move forward! ! !

Guess you like

Origin blog.csdn.net/qq_73478334/article/details/132990967