国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

搜索二叉樹【C++】

這篇具有很好參考價(jià)值的文章主要介紹了搜索二叉樹【C++】。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

二叉搜索樹

二叉搜索樹又稱為二叉排序樹,它或者是一棵空樹,或者是具有以下性質(zhì)的二叉樹:

若它的左子樹不為空,
則左子樹上所有結(jié)點(diǎn)的值都小于根結(jié)點(diǎn)的值。

若它的右子樹不為空,
則右子樹上所有結(jié)點(diǎn)的值都大于根結(jié)點(diǎn)的值。

它的左右子樹也分別是二叉搜索樹。

搜索二叉樹【C++】,c++,java,數(shù)據(jù)結(jié)構(gòu)

二叉搜索樹的模擬實(shí)現(xiàn)

構(gòu)造函數(shù)

	BSTree()
		:_root(nullptr)
	{

	}

拷貝構(gòu)造函數(shù)

	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;

		}

賦值運(yùn)算符重載函數(shù)

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

析構(gòu)函數(shù)

~BSTree()
		{
			Destroy(_root);
		}
		
		private:
				void Destroy(Node*& root) //引用的目的:將每個(gè)節(jié)點(diǎn)釋放后同時(shí)置空
		{
			//后序遍歷 
			if (root == nullptr)
			{
				return;
			}
			Destroy(root->_left);
			Destroy(root->_right);
			delete root;
			root = nullptr;
		}

Insert

核心思路:

如果是空樹,則直接將插入結(jié)點(diǎn)作為二叉搜索樹的根結(jié)點(diǎn)。

如果不是空樹,則按照二叉搜索樹的性質(zhì)進(jìn)行結(jié)點(diǎn)的插入。
如果待插入結(jié)點(diǎn)的值<根結(jié)點(diǎn)的值,則需要將結(jié)點(diǎn)插入到左子樹當(dāng)中。
如果待插入結(jié)點(diǎn)的值>根結(jié)點(diǎn)的值,則需要將結(jié)點(diǎn)插入到右子樹當(dāng)中。
如果待插入結(jié)點(diǎn)的值等于根結(jié)點(diǎn)的值,則插入失敗。

循環(huán)

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

		//不是空樹

		Node* parent = nullptr;//找到父節(jié)點(diǎn)
		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;
			}
	
		}

		//插入節(jié)點(diǎn)
		cur = new Node(key);
			
		
			//不知道parent在那一邊,需要進(jìn)一步判斷
			if (parent->_key > key)
			{
				//parent在左邊
				parent->_left = cur;
			}
			else if (parent->_key < key)
			{
				//parent在右邊
				parent->_right = cur;

			}
			else
			{
				return false;
			}
		

		return true;
	}

遞歸

	bool InsertR(const K& key)//遞歸版本
		{
			return _InsertR(_root, key);
		}
		private:
			bool _InsertR(Node*& root, const K& key) //引用的目的:不用找父節(jié)點(diǎn),不需要用父節(jié)點(diǎn)比較大小
		{
			//結(jié)束條件
			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

先找到需要?jiǎng)h除的節(jié)點(diǎn)
需要?jiǎng)h除的節(jié)點(diǎn)可能會(huì)有三種情況:
1、待刪除結(jié)點(diǎn)的左子樹為空(待刪除結(jié)點(diǎn)的左右子樹均為空包含在內(nèi))

搜索二叉樹【C++】,c++,java,數(shù)據(jù)結(jié)構(gòu)

2、待刪除結(jié)點(diǎn)的右子樹為空。
搜索二叉樹【C++】,c++,java,數(shù)據(jù)結(jié)構(gòu)

1、2 兩種情況,被刪除的節(jié)點(diǎn)都只有一個(gè)孩子

3、待刪除結(jié)點(diǎn)的左右子樹均不為空,即被刪除節(jié)點(diǎn)有兩個(gè)孩子
使用替換法處理第3中情況:
1、找替換節(jié)點(diǎn):替換節(jié)點(diǎn)一般是左子樹的最大節(jié)點(diǎn)(最右節(jié)點(diǎn)),或者是右子樹的最小節(jié)點(diǎn)(最左節(jié)點(diǎn))
2、將替換的節(jié)點(diǎn)刪除

搜索二叉樹【C++】,c++,java,數(shù)據(jù)結(jié)構(gòu)
特殊情況:

搜索二叉樹【C++】,c++,java,數(shù)據(jù)結(jié)構(gòu)

循環(huán)

	bool Erase(const K& key)
	{
		Node* parent = nullptr;//待刪除節(jié)點(diǎn)的父節(jié)點(diǎn)
		Node* cur = _root;//待刪除的節(jié)點(diǎn)

		//不是空樹
		while (cur)
		{
			//往左邊走
			if (cur->_key > key)
			{
				parent = cur;
				cur = cur->_left;
			}
			//往右邊走
			else if (cur->_key < key)
			{
				parent = cur;
				cur = cur->_right;
			}
			//找到待刪除的節(jié)點(diǎn)
			else
			{
				//待刪除節(jié)點(diǎn)的左子樹為空 ,即一個(gè)孩子的情況
				if (cur->_left == nullptr)
				{
					  //待刪除節(jié)點(diǎn)是根節(jié)點(diǎn)
					if (cur == _root)
					{
						//將根節(jié)點(diǎn)改為待刪除節(jié)點(diǎn)的右孩子
						_root = cur->_right;
					}
					//待刪除節(jié)點(diǎn)不是根節(jié)點(diǎn),并且此時(shí)parent不為nullptr
					else
					{
						if (parent->_right == cur)
						{
							parent->_right = cur->_right;
						}
						else//parent->_left ==cur
						{
							parent->_left = cur->_right;
						}
					}
					
				}
				//待刪除節(jié)點(diǎn)的右子樹為空 ,即一個(gè)孩子的情況
				else if (cur->_right == nullptr)
				{
					//待刪除節(jié)點(diǎn)是根節(jié)點(diǎn)
					if (cur == _root)
					{
						//將根節(jié)點(diǎn)改為待刪除節(jié)點(diǎn)的左孩子
						_root = cur->_left;
					}
					//待刪除節(jié)點(diǎn)不是根節(jié)點(diǎn),并且此時(shí)parent不為nullptr
					else
					{
						if (parent->_right == cur)
						{
							parent->_right = cur->_left;
						}
						else//parent->_left==cur
						{
							parent->_left = cur->_left;
						}
					}
				} 

				else //待刪除的節(jié)點(diǎn)的左右孩子都不為空 (替換法:左子樹的最大節(jié)點(diǎn)即最右節(jié)點(diǎn),或者右子樹的最小節(jié)點(diǎn)即最左節(jié)點(diǎn),并且將替換的節(jié)點(diǎn)刪除)
				{
					//替換法

					//找替代節(jié)點(diǎn)
					Node* parent = cur;
					//找左子樹的最大節(jié)點(diǎn),左子樹的最大節(jié)點(diǎn)一定沒有右孩子
					Node* leftMax = cur->_left;
					
					while (leftMax->_right)
					{
						parent = leftMax; //記錄leftMax的父節(jié)點(diǎn),防止刪除leftMax時(shí)找不到該節(jié)點(diǎn)位置 
						//一直往右子樹找
						leftMax = leftMax->_right;
					}
					//左子樹的最大節(jié)點(diǎn)和待刪除節(jié)點(diǎn)替換
					swap(cur->_key, leftMax->_key);
					//重新改變鏈接關(guān)系
					 
					//特殊情況 
					if (parent->_left == leftMax)
					{
						parent->_left = leftMax->_left;
					}
					else//普通情況 parent->_right== leftMax
					{
						parent->_right = leftMax->_left;
						
					}
					cur = leftMax;
				}
				//刪除左子樹的最大節(jié)點(diǎn)
				delete cur;
				return true;
			}
			
		}
		return false;
	}

遞歸

	bool EraseR(Node* _root, const K& key)//遞歸版本
		{
			return _EraseR(_root, key);
		}
		private:
				bool _EraseR(Node*& root, const K& key)//引用的目的:不用找父節(jié)點(diǎn),不需要用父節(jié)點(diǎn)比較大小
		{
			//結(jié)束條件
			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;
				//待刪除節(jié)點(diǎn)的左子樹為空 ,即一個(gè)孩子的情況
				if (root->_left == nullptr)
				{
					root = root->_right;
				}
				//待刪除節(jié)點(diǎn)的右子樹為空 ,即一個(gè)孩子的情況
				else if (root->_right == nullptr)
				{
					root = root->_left;
				}
				//待刪除的節(jié)點(diǎn)的左右孩子都不為空 (替換法:左子樹的最大節(jié)點(diǎn)即最右節(jié)點(diǎn),或者右子樹的最小節(jié)點(diǎn)即最左節(jié)點(diǎn),并且將替換的節(jié)點(diǎn)刪除)
				else
				{
					//找左子樹最大節(jié)點(diǎn)
					Node* leftMax = root->_left;
					//一直往左邊找,直到找到左子樹最大節(jié)點(diǎn)
					while (root->_left)
					{
						root = root->_left;
					}
					//將左子樹最大節(jié)點(diǎn)與被刪除節(jié)點(diǎn)替換
					swap(leftMax->_key, root->_key);

					return _EraseR(root, key);
				}

				delete del;//?
				return true;

			}


		}

Find

循環(huán)

	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 FindR(Node* _root, const K& key)//遞歸版本
		{
			return _FindR(_root, key);
		}
		private:
		bool  _FindR(Node* root, const K& key)
		{
			//結(jié)束條件
			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;
			}
		}

二叉搜索樹的應(yīng)用

K模型

K模型,即只有key作為關(guān)鍵碼,結(jié)構(gòu)中只需存儲(chǔ)key即可,關(guān)鍵碼即為需要搜索到的值。

比如:給定一個(gè)單詞,判斷該單詞是否拼寫正確。具體方式如下:

	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模型

KV模型,對(duì)于每一個(gè)關(guān)鍵碼key,都有與之對(duì)應(yīng)的值value,即<key, value>的鍵值對(duì)。

英漢詞典就是英文與中文的對(duì)應(yīng)關(guān)系,即<word, Chinese>就構(gòu)成一種鍵值對(duì)。具體方式如下

1、以<單詞, 中文含義>為鍵值對(duì),構(gòu)建一棵二叉搜索樹。注意:二叉搜索樹需要進(jìn)行比較,鍵值對(duì)比較時(shí)只比較key。
2、查詢英文單詞時(shí),只需給出英文單詞就可以快速找到與其對(duì)應(yīng)的中文含義。

完整代碼

普通版本

#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;//找到父節(jié)點(diǎn)
		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;
			}
	
		}

		//插入節(jié)點(diǎn)
		cur = new Node(key);
			
		
			//不知道parent在那一邊,需要進(jìn)一步判斷
			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;//待刪除節(jié)點(diǎn)的父節(jié)點(diǎn)
		Node* cur = _root;//待刪除的節(jié)點(diǎn)

		//不是空樹
		while (cur)
		{
			//往左邊走
			if (cur->_key > key)
			{
				parent = cur;
				cur = cur->_left;
			}
			//往右邊走
			else if (cur->_key < key)
			{
				parent = cur;
				cur = cur->_right;
			}
			//找到待刪除的節(jié)點(diǎn)
			else
			{
				//待刪除節(jié)點(diǎn)的左子樹為空 ,即一個(gè)孩子的情況
				if (cur->_left == nullptr)
				{
					  //待刪除節(jié)點(diǎn)是根節(jié)點(diǎn)
					if (cur == _root)
					{
						//將根節(jié)點(diǎn)改為待刪除節(jié)點(diǎn)的右孩子
						_root = cur->_right;
					}
					//待刪除節(jié)點(diǎn)不是根節(jié)點(diǎn),并且此時(shí)parent不為nullptr
					else
					{
						

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


					}
					
				}
				

				//待刪除節(jié)點(diǎn)的右子樹為空 ,即一個(gè)孩子的情況
				else if (cur->_right == nullptr)
				{
					//待刪除節(jié)點(diǎn)是根節(jié)點(diǎn)
					if (cur == _root)
					{
						//將根節(jié)點(diǎn)改為待刪除節(jié)點(diǎn)的左孩子
						_root = cur->_left;
					}
					//待刪除節(jié)點(diǎn)不是根節(jié)點(diǎn),并且此時(shí)parent不為nullptr
					else
					{
						
						if (parent->_right == cur)
						{
							parent->_right = cur->_left;
						}
						else//parent->_left==cur
						{
							parent->_left = cur->_left;
						}

					}
					
				} 

				else //待刪除的節(jié)點(diǎn)的左右孩子都不為空 (替換法:左子樹的最大節(jié)點(diǎn)即最右節(jié)點(diǎn),或者右子樹的最小節(jié)點(diǎn)即最左節(jié)點(diǎn),并且將替換的節(jié)點(diǎn)刪除)
				{
					//替換法

					//找替代節(jié)點(diǎn)
					Node* parent = cur;
					//找左子樹的最大節(jié)點(diǎn)
					Node* leftMax = cur->_left;
					
					while (leftMax->_right)
					{
						parent = leftMax; //記錄leftMax的父節(jié)點(diǎn),防止刪除leftMax時(shí)找不到該節(jié)點(diǎn)位置 
						//一直往右子樹找
						leftMax = leftMax->_right;
					}
					//左子樹的最大節(jié)點(diǎn)和待刪除節(jié)點(diǎn)替換
					swap(cur->_key, leftMax->_key);
					//重新改變鏈接關(guān)系
					 
					//特殊情況 
					if (parent->_left == leftMax)
					{
						parent->_left = leftMax->_left;
					}
					else//普通情況 
					{
						parent->_right = leftMax->_left;
						//parent->_right =nullptr;
					}
					cur = leftMax;


				
				}
				//刪除左子樹的最大節(jié)點(diǎn)
				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();

}

遞歸版本

#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);
		}
		//拷貝構(gòu)造
		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) //引用的目的:將每個(gè)節(jié)點(diǎn)釋放后同時(shí)置空
		{
			//后序遍歷 
			if (root == nullptr)
			{
				return;
			}
			Destroy(root->_left);
			Destroy(root->_right);
			delete root;
			root = nullptr;
		}
		bool _InsertR(Node*& root, const K& key) //引用的目的:不用找父節(jié)點(diǎn),不需要用父節(jié)點(diǎn)比較大小
		{
			//結(jié)束條件
			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)//引用的目的:不用找父節(jié)點(diǎn),不需要用父節(jié)點(diǎn)比較大小
		{
			//結(jié)束條件
			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;
				//待刪除節(jié)點(diǎn)的左子樹為空 ,即一個(gè)孩子的情況
				if (root->_left == nullptr)
				{
					root = root->_right;
				}


				//待刪除節(jié)點(diǎn)的右子樹為空 ,即一個(gè)孩子的情況
				else if (root->_right == nullptr)
				{
					root = root->_left;
				}
				//待刪除的節(jié)點(diǎn)的左右孩子都不為空 (替換法:左子樹的最大節(jié)點(diǎn)即最右節(jié)點(diǎn),或者右子樹的最小節(jié)點(diǎn)即最左節(jié)點(diǎn),并且將替換的節(jié)點(diǎn)刪除)
				else
				{
					//找左子樹最大節(jié)點(diǎn)
					Node* leftMax = root->_left;
					//一直往左邊找,直到找到左子樹最大節(jié)點(diǎn)
					while (root->_left)
					{
						root = root->_left;
					}
					//將左子樹最大節(jié)點(diǎn)與被刪除節(jié)點(diǎn)替換
					swap(leftMax->_key, root->_key);

					return _EraseR(root, key);
				}

				delete del;//?
				return true;

			}


		}

		bool  _FindR(Node* root, const K& key)
		{
			//結(jié)束條件
			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();
		//沒有引用,釋放了,只是指針沒有置空,尤其是根節(jié)點(diǎn)_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();
	}

}

如果你覺得這篇文章對(duì)你有幫助,不妨動(dòng)動(dòng)手指給點(diǎn)贊收藏加轉(zhuǎn)發(fā),給鄃鱈一個(gè)大大的關(guān)注你們的每一次支持都將轉(zhuǎn)化為我前進(jìn)的動(dòng)力?。?!文章來源地址http://www.zghlxwxcb.cn/news/detail-723736.html

到了這里,關(guān)于搜索二叉樹【C++】的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 數(shù)據(jù)結(jié)構(gòu)——常見二叉樹的分類(完全二叉樹、滿二叉樹、平衡二叉樹、二叉搜索樹、紅黑樹)

    數(shù)據(jù)結(jié)構(gòu)——常見二叉樹的分類(完全二叉樹、滿二叉樹、平衡二叉樹、二叉搜索樹、紅黑樹)

    專業(yè)術(shù)語 中文 描述 Root 根節(jié)點(diǎn) 一棵樹的頂點(diǎn) Child 孩子結(jié)點(diǎn) 一個(gè)結(jié)點(diǎn)含有的子樹的根節(jié)點(diǎn)稱為該結(jié)點(diǎn)的子節(jié)點(diǎn) Leaf 葉子結(jié)點(diǎn) 沒有孩子的節(jié)點(diǎn) Degree 度 一個(gè)節(jié)點(diǎn)包含子樹的數(shù)量 Edge 邊 一個(gè)節(jié)點(diǎn)與另外一個(gè)節(jié)點(diǎn)的連接 Depth 深度 根節(jié)點(diǎn)到這個(gè)節(jié)點(diǎn)經(jīng)過邊的數(shù)量 Height 節(jié)點(diǎn)高度 從

    2024年02月03日
    瀏覽(29)
  • 數(shù)據(jù)結(jié)構(gòu)第四天: Complete Binary Search Tree 【搜索二叉樹,完全二叉樹】

    數(shù)據(jù)結(jié)構(gòu)第四天: Complete Binary Search Tree 【搜索二叉樹,完全二叉樹】

    ?這道題需要的操作時(shí)排序并且需要遍歷,最重要的一點(diǎn)它是個(gè)完全二叉樹,所以數(shù)組是最適合的 這道題我的思路來自于浙江大學(xué)課件7.0.2完全二叉樹 這道題說白就是將輸入的樣例構(gòu)造成一個(gè)完全搜索二叉樹。因?yàn)橥耆€索二叉樹的 根節(jié)點(diǎn)一定是是一個(gè)處于左右子樹中間的那

    2024年02月06日
    瀏覽(28)
  • 〖數(shù)據(jù)結(jié)構(gòu)〗一棵有點(diǎn)自律的樹——搜索二叉樹

    〖數(shù)據(jù)結(jié)構(gòu)〗一棵有點(diǎn)自律的樹——搜索二叉樹

    ??作者簡介: 花想云 ,在讀本科生一枚,致力于 C/C++、Linux 學(xué)習(xí)。 ?? 本文收錄于 C++系列 ,本專欄主要內(nèi)容為 C++ 初階、C++ 進(jìn)階、STL 詳解等,專為大學(xué)生打造全套 C++ 學(xué)習(xí)教程,持續(xù)更新! ?? 相關(guān)專欄推薦: C語言初階系列 、 C語言進(jìn)階系列 、 數(shù)據(jù)結(jié)構(gòu)與算法 、 Linu

    2024年02月08日
    瀏覽(24)
  • (浙大陳越版)數(shù)據(jù)結(jié)構(gòu) 第三章 樹(中) 二叉搜索樹和平衡二叉樹

    (浙大陳越版)數(shù)據(jù)結(jié)構(gòu) 第三章 樹(中) 二叉搜索樹和平衡二叉樹

    目錄 4.1.1 二叉搜索樹及查找 什么是二叉搜索樹 定義 二叉搜索樹特殊函數(shù)集: 查找操作:Find 算法思想 代碼實(shí)現(xiàn) 補(bǔ):查找最大和最小元素 4.1.2 二叉搜索樹的插入 插入操作:Insert 算法思想 代碼實(shí)現(xiàn) 例題 4.1.3 二叉搜索樹的刪除 刪除操作:delete 算法思想 情況1:刪除葉節(jié)點(diǎn)

    2024年02月08日
    瀏覽(26)
  • 數(shù)據(jù)結(jié)構(gòu)與算法之二叉樹: Leetcode 98. 驗(yàn)證二叉搜索樹 (Typescript版)

    驗(yàn)證二叉搜索樹 https://leetcode.cn/problems/validate-binary-search-tree/ 描述 給你一個(gè)二叉樹的根節(jié)點(diǎn) root ,判斷其是否是一個(gè)有效的二叉搜索樹 有效 二叉搜索樹定義如下: 節(jié)點(diǎn)的左子樹只包含 小于 當(dāng)前節(jié)點(diǎn)的數(shù)。 節(jié)點(diǎn)的右子樹只包含 大于 當(dāng)前節(jié)點(diǎn)的數(shù)。 所有左子樹和右子樹自身

    2024年02月16日
    瀏覽(22)
  • 數(shù)據(jù)結(jié)構(gòu)之進(jìn)階二叉樹(二叉搜索樹和AVL樹、紅黑樹的實(shí)現(xiàn))超詳細(xì)解析,附實(shí)操圖和搜索二叉樹的實(shí)現(xiàn)過程圖

    數(shù)據(jù)結(jié)構(gòu)之進(jìn)階二叉樹(二叉搜索樹和AVL樹、紅黑樹的實(shí)現(xiàn))超詳細(xì)解析,附實(shí)操圖和搜索二叉樹的實(shí)現(xiàn)過程圖

    緒論? “生命有如鐵砧,愈被敲打,愈能發(fā)出火花?!だ浴?;本章主要是數(shù)據(jù)結(jié)構(gòu) 二叉樹的進(jìn)階知識(shí),若之前沒學(xué)過二叉樹建議看看這篇文章一篇掌握二叉樹,本章的知識(shí)從淺到深的 對(duì)搜索二叉樹的使用進(jìn)行了介紹和對(duì)其底層邏輯的實(shí)現(xiàn)進(jìn)行了講解 ,希望能對(duì)你有所

    2024年02月04日
    瀏覽(28)
  • 數(shù)據(jù)結(jié)構(gòu)與算法(三):樹論(樹形結(jié)構(gòu)、二叉樹、二叉搜索樹、紅黑樹、Btree&B+Tree、赫夫曼樹、堆樹)

    數(shù)據(jù)結(jié)構(gòu)與算法(三):樹論(樹形結(jié)構(gòu)、二叉樹、二叉搜索樹、紅黑樹、Btree&B+Tree、赫夫曼樹、堆樹)

    樹論(樹形結(jié)構(gòu)、二叉樹、二叉搜索樹、紅黑樹、Btree、B+Tree、赫夫曼樹、堆樹) 在樹形結(jié)構(gòu)里面重要的術(shù)語: 結(jié)點(diǎn):樹里面的元素。 父子關(guān)系:結(jié)點(diǎn)之間相連的邊 子樹:當(dāng)結(jié)點(diǎn)大于1時(shí),其余的結(jié)點(diǎn)分為的互不相交的集合稱為子樹 度:一個(gè)結(jié)點(diǎn)擁有的子樹數(shù)量稱為結(jié)點(diǎn)的

    2024年02月01日
    瀏覽(26)
  • 數(shù)據(jù)結(jié)構(gòu)第十六天(二叉樹層序遍歷/廣度優(yōu)先搜索(BFS)/隊(duì)列使用)

    數(shù)據(jù)結(jié)構(gòu)第十六天(二叉樹層序遍歷/廣度優(yōu)先搜索(BFS)/隊(duì)列使用)

    目錄 前言 概述 接口 源碼 測試函數(shù) 運(yùn)行結(jié)果 往期精彩內(nèi)容 從前的日色變得慢,車,馬,郵件都慢,一生,只夠愛一個(gè)人。 二叉樹的層序遍歷可以使用廣度優(yōu)先搜索(BFS)來實(shí)現(xiàn)。具體步驟如下: 創(chuàng)建一個(gè)隊(duì)列 queue,并將根節(jié)點(diǎn)入隊(duì)。 當(dāng)隊(duì)列不為空時(shí),重復(fù)執(zhí)行以下步驟:

    2024年02月22日
    瀏覽(22)
  • 【Java 數(shù)據(jù)結(jié)構(gòu)】二叉樹

    【Java 數(shù)據(jù)結(jié)構(gòu)】二叉樹

    樹是一種 非線性 的數(shù)據(jù)結(jié)構(gòu),它是由n(n=0)個(gè)有限結(jié)點(diǎn)組成一個(gè)具有層次關(guān)系的集合。 把它叫做樹是因?yàn)樗雌饋硐褚豢玫箳斓臉?,也就是說它是根朝上,而葉朝下的 。 有一個(gè)特殊的結(jié)點(diǎn),稱為根結(jié)點(diǎn),根結(jié)點(diǎn)沒有前驅(qū)結(jié)點(diǎn) 除根結(jié)點(diǎn)外,其余結(jié)點(diǎn)被分成M(M 0)個(gè)互不相交的

    2024年02月20日
    瀏覽(35)
  • 【java數(shù)據(jù)結(jié)構(gòu)-二叉樹(上)】

    【java數(shù)據(jù)結(jié)構(gòu)-二叉樹(上)】

    ??個(gè)人主頁: 努力學(xué)編程’ ??內(nèi)容管理: java數(shù)據(jù)結(jié)構(gòu) hello,今天帶大家學(xué)習(xí) 數(shù)據(jù)結(jié)構(gòu) 中非常重要的一個(gè)知識(shí)點(diǎn) 二叉樹 ,二叉樹主體的實(shí)現(xiàn)使用的是遞歸的知識(shí),通過二叉樹我們可以更好的理解遞歸的應(yīng)用。今天就帶大家學(xué)習(xí)一下二叉樹的一些知識(shí)。 概念 : 樹是一種非

    2024年04月08日
    瀏覽(20)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包