c++实现搜索二叉树

Posted MicroDeLe

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c++实现搜索二叉树相关的知识,希望对你有一定的参考价值。

第一次接触树,各种递归搞得眼花,总算是按书上的代码,敲了下来,记录一下

/**
 * Created by admin on 2021/10/27.
 * 搜索二叉树实现
 */
#ifndef HELLOWORLD_BINARY_SEARCH_TREE_H
#define HELLOWORLD_BINARY_SEARCH_TREE_H
#include <istream>
template <typename Object>
class BinarySearchTree{
    struct TreeNode{
        Object object; // 数据
        TreeNode *left;  // 左子树指针
        TreeNode *right; // 右子树指针
    };  // 二进制树
    TreeNode *root; // 根节点
    void insert(const Object &, TreeNode *&);  // 插入元素
    void printTree(TreeNode *&);  // 打印树
    bool contain(const Object&, TreeNode *&);  // 查找树中是否有该元素
    TreeNode *findMax(TreeNode *&);  // 找最大值
    TreeNode *findMin(TreeNode *&);  // 找最小值
    void remove(const Object &object, TreeNode *&);
    void makeEmpty(TreeNode *&);
    TreeNode *clone(TreeNode *);
public:
    BinarySearchTree(): root(nullptr){};  // 普通构造函数
    ~BinarySearchTree(){ makeEmpty(root);}  // 析构函数
    BinarySearchTree(const BinarySearchTree &rhs): root(nullptr){root = clone(rhs.root);}
    void insert(const Object &object){ insert(object, root);} // 插入数据
    void printTree(){ printTree(root);};  // 打印树
    bool contain(const Object &object){ return contain(object, root);}
    const Object &findMax(){return findMax(root)->object;}  // 找最大值
    const Object &findMin(){return findMin(root)->object;}  // 找最小值
    void remove(const Object &object){remove(object, root);}  // 删除元素
};

template<typename Object>
void BinarySearchTree<Object>::insert(const Object &object, TreeNode *&treeNode) {
    if (treeNode == nullptr) treeNode = new TreeNode{object, nullptr, nullptr};  // 新建节点
    else if (object < treeNode->object) insert(object, treeNode->left);  // 向左递归插入
    else if (object > treeNode->object) insert(object, treeNode->right); // 向左递归插入
}

template<typename Object>
void BinarySearchTree<Object>::printTree(BinarySearchTree::TreeNode *&treeNode) {
    if (treeNode == nullptr) return;
    std::cout << treeNode->object;  // 前序打印
    if (treeNode->left != nullptr) printTree(treeNode->left);
    if (treeNode->right != nullptr) printTree(treeNode->right);
}

template<typename Object>
bool BinarySearchTree<Object>::contain(const Object &object, BinarySearchTree::TreeNode *&treeNode) {
    if (treeNode == nullptr) return false;
    else if (object < treeNode->object) contain(object, treeNode->left);
    else if (object > treeNode->object) contain(object, treeNode->right);
    else return true;  // 匹配
}

template<typename Object>
typename BinarySearchTree<Object>::TreeNode *BinarySearchTree<Object>::findMax(BinarySearchTree::TreeNode *&treeNode) {
    if (treeNode == nullptr) return nullptr;
    if (treeNode->right == nullptr) return treeNode;
    return findMax(treeNode->right);
}

template<typename Object>
typename BinarySearchTree<Object>::TreeNode *BinarySearchTree<Object>::findMin(BinarySearchTree::TreeNode *&treeNode) {
    if (treeNode == nullptr) return nullptr;
    if (treeNode->left == nullptr) return treeNode;
    return findMin(treeNode->left);
}

template<typename Object>
void BinarySearchTree<Object>::remove(const Object &object, BinarySearchTree::TreeNode *&treeNode) {
    if (treeNode == nullptr) return;
    else if (object < treeNode->object) remove(object, treeNode->left);
    else if (object > treeNode->object) remove(object, treeNode->right);
    else if (treeNode->left != nullptr && treeNode->right != nullptr){  // 双节点的情况
        treeNode->object = findMin(treeNode->right)->object;  // 值用右树最小值替换
        remove(treeNode->object, treeNode->right); // 找到替换的节点
    }else{
        TreeNode *oldTreeNode = treeNode;
        treeNode = treeNode->left != nullptr? treeNode->left: treeNode->right;
        delete oldTreeNode;
    }

}

template<typename Object>
void BinarySearchTree<Object>::makeEmpty(BinarySearchTree::TreeNode *&treeNode) {
    if (treeNode == nullptr) return;
    makeEmpty(treeNode->left);
    makeEmpty(treeNode->right);
    delete treeNode;
    treeNode = nullptr;
}

template<typename Object>
typename BinarySearchTree<Object>::TreeNode *BinarySearchTree<Object>::clone(BinarySearchTree::TreeNode *treeNode) {
    if (treeNode == nullptr) return nullptr;
    else return new TreeNode{treeNode->object, clone(treeNode->left), clone(treeNode->right)};
}


#endif //HELLOWORLD_BINARY_SEARCH_TREE_H

 

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();
}

技术分享

本文出自 “zgw285763054” 博客,请务必保留此出处http://zgw285763054.blog.51cto.com/11591804/1795294

以上是关于c++实现搜索二叉树的主要内容,如果未能解决你的问题,请参考以下文章

C++进阶第十七篇——二叉搜索树(概念+二叉搜索树实现+二叉搜索树的应用+二叉树性能分析)

怎么判断是不是是完全二叉树 用C++或C语言

C++二叉树进阶

二叉树的前序中序后序层次遍历的原理及C++代码实现

C++从青铜到王者第十九篇:C++二叉树进化之二叉搜索树

C++进阶:二叉树进阶二叉搜索树的操作和key模型key/value模型的实现 | 二叉搜索树的应用 | 二叉搜索树的性能分析