1. 程式人生 > >資料結構:二叉搜尋樹

資料結構:二叉搜尋樹

實現的操作

1.0 插入:找待插入的節點的位置(data<_root->_data左子樹,data>_root->_data 右子樹)data為待插入節點的值。

2.0 尋找:找節點的位置(data<_root->_data左子樹,data>_root->_data 右子樹)data為待插入節點的值。

注意:尋找的時候先考慮等於的情況,插入則最後考慮,以上返回值都為bool型別

3.0 刪除:先找到待刪除節點的位置-->分情況刪除(如圖)


具體的二叉樹:


遞迴程式碼如下:

bstree.h

#pragma once
#include<iostream>
using namespace std;
template<class T>
class bstreeNode
{
public:
	bstreeNode(const T& data)
		: _data(data)
		, _left(NULL)
		, _right(NULL)
	{}
	 bstreeNode(bstreeNode<T>& node)
		: _root->_data(node->data)
		, _root->_left(node->_left)
		, _root->_right(node->_right)
	{}
	bstreeNode<T>* _left;
	bstreeNode<T>* _right;
	T _data;
};
template<class T>
class bstree
{
	typedef bstreeNode<T> Node;
	typedef Node* PNode;
public:
	bstree()
		:_root(NULL)
	{}
	//中序遍歷
	void InOrderTraverse()
	{
		_InOrderTraverse(_root);
	}
	bool Insert(const T& data)
	{
		return _Insert(_root, data);
	}
	//查詢
	bool Find(const T& data)
	{
		return _Find(_root,data);
	}
	//刪除
	bool Delete(const T& data)
	{
		return _Delete(_root, data);
	}
	~bstree()
	{
		_clear(_root);
	}
protected:
	////插入(遞迴實現)
	//bool _Insert(PNode& _root, const T& data)  //傳引用,修改了_root的值
	//{
	//	if (NULL == _root)//樹為空
	//	{
	//		_root = new Node(data);
	//		if (NULL == _root) //new失敗
	//			return false;
	//		return true;
	//	}
	//	else //非空
	//	{
	//		if (data < _root->_data)
	//			_Insert(_root->_left, data);
	//		else if (_root->_data)
	//		     _Insert(_root->_right, data);
	//		else  //相等的情況
	//			return false;
	//	}
	//}
	//插入(迴圈實現)
	bool _Insert(PNode& _root, const T& data)  //傳引用,修改了_root的值
	{
		if (NULL == _root)//樹為空
		{
			_root = new Node(data);
			if (NULL == _root) //new失敗
				return false;
			return true;
		}
		else //非空
		{
			PNode PCur = _root;
			PNode parent = NULL;
			while (PCur)
			{
				if (data < _root->_data)
				{
					parent = PCur;
					PCur = PCur->_left;
				}
				else if (data> _root->_data)
				{
					parent = PCur;
					PCur = PCur->_right;
				}
				else  //相等的情況
					return false;
			}
			PCur = new Node(data);
			if (data > parent->_data)
				parent->_right = PCur;
			else
				parent->_left = PCur;
		}
	}
	//尋找(遞迴實現)
	/*bool _Find(PNode _root, const T& data)
	{
		if (NULL == _root)
			return false;
		if (_root->_data == data)
			return true;
		else if (data< _root->_data)
			_Find(_root->_left, data);
		else
			_Find(_root->_right, data);
	}*/
	//尋找(迴圈實現)
	bool _Find(PNode _root, const T& data)
	{
		if (NULL == _root)
			return false;
		PNode PCur = _root;
		while (PCur)
		{
			if (PCur->_data == data)
				return true;
			else if (data < PCur->_data)
				PCur = PCur->_left;
			else
				PCur = PCur->_right;
		}
		if (NULL == PCur)
			return false;
		else
			return true;
	}
	//刪除(遞迴實現)
	//bool _Delete(PNode& _root,const T& data)
	//{
	//	if (NULL == _root)
	//		return false;
	//	if (data< _root->_data)
	//		return _Delete(_root->_left, data);
	//	else if (data> _root->_data)
	//		return _Delete(_root->_right, data);
	//	else  //找到了待刪除的節點
	//	{
	//		PNode PCur = _root;
	//		if (PCur->_right ==NULL)
	//		{
	//			_root = PCur->_left;
	//			delete PCur;
	//			PCur = NULL;
	//		}
	//		else if (PCur->_left == NULL)
	//		{
	//			_root = PCur->_right;
	//			delete PCur;
	//			PCur = NULL;
	//		}
	//		else
	//		{
	//			PCur = PCur->_right;
	//			while (PCur->_left)  //確定待刪除節點的右子樹的最左側節點
	//			{
	//				PCur = PCur->_left;
	//			}
	//			 _root->_data = PCur->_data;
	//			_Delete(_root->_right, PCur->_data);
	//		}
	//		return true;
	//	}

	//}
	//刪除(迴圈實現)
	bool _Delete(PNode& _root, const T& data)
	{
		PNode PCur = _root;
		PNode parent = NULL;
		if (NULL == _root)
			return false;
		while (PCur)
		{
			if (PCur->_data == data)
				break;
			else if (data < PCur->_data)
			{
				parent = PCur;
				PCur = PCur->_left;
			}
			else
			{
				parent = PCur;
				PCur = PCur->_right;
			}
		}
		if (NULL == PCur)
			return false;
		else
			//找到了待刪除的節點
		{
			if (PCur->_right == NULL)  //該節點沒有左孩子,或者該節點為葉子結點
			{
				if (PCur == _root) //待刪除節點為根節點
					_root = PCur->_left;
				else               //非根
				{ 
					if (parent->_left == PCur)   //待刪除節點為雙親節點的左孩子
						parent->_left = PCur->_left;
					else                         //待刪除節點為雙親節點的右孩子
						parent->_right = PCur->_left;
				}
			}
			else if (PCur->_left == NULL)
			{
				if (PCur == _root) //待刪除節點為根節點
					_root = PCur->_right;
				else               //非根
				{
					if (parent->_left == PCur)   //待刪除節點為雙親節點的左孩子
						parent->_left = PCur->_right;
					else                         //待刪除節點為雙親節點的右孩子
						parent->_right = PCur->_right;
				}
			}
			else
			{
				parent = NULL;
				PNode PDel = PCur->_right;
				while (PDel->_left)  //確定待刪除節點的右子樹的最左側節點
				{
					parent = PDel;
					PDel = PDel->_left;
				}
				PCur->_data = PDel->_data;
				if (parent->_left == PDel)     //待刪除d的替代節點為雙親節點的左孩子
					parent->_left = PDel->_right;
				if (parent->_right == PDel)    //待刪除d的替代節點為雙親節點的右孩子
					parent->_right = PDel->_right;
				PCur = PDel;
			}
			delete PCur;
			PCur = NULL;
			return true;
		}
	}
	void _clear(PNode& _Proot)
	{
		if (NULL == _Proot)
			return;
		_clear(_Proot->_left);
		_clear(_Proot->_right);
		delete _Proot;
		_Proot = NULL;
	}
	void _InOrderTraverse(PNode root)
	{
		if (NULL==root)
			return;
		_InOrderTraverse(root->_left);
		cout << root->_data << " ";
		_InOrderTraverse(root->_right);
	}
private:
	PNode _root;
};
void bstree_test()
{
	bstree<int> bst;
	int arr[] = { 3, 2, 0, 5, 8, 7 };
	int size = sizeof(arr) / sizeof(arr[0]);
	for (int i = 0; i < size; ++i)
	{
		bst.Insert(arr[i]);
	}
	bst.InOrderTraverse();
	cout << endl;
	cout<<bst.Find(6)<<endl;
	cout<<bst.Find(2)<<endl;
	cout << bst.Delete(5)<< endl;
	bst.InOrderTraverse();
	cout << endl;
	cout << bst.Delete(7) << endl;
	bst.InOrderTraverse();
	cout << endl;
	cout << bst.Delete(8) << endl;
	bst.InOrderTraverse();
	cout << endl;
	cout << bst.Delete(0) << endl;
	bst.InOrderTraverse();
	cout << endl;
	cout << bst.Delete(3) << endl;
	bst.InOrderTraverse();
	cout << endl;
	cout << bst.Delete(2) << endl;
	bst.InOrderTraverse();
}


main.cpp

#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include"bstree.h"
#include<iostream>
using namespace std;
int main()
{
	bstree_test();
	system("pause");
	return 0;
}


結果: