C++ 模板实现二叉搜索树

二叉搜索树的增删该查操作实现

 插入操作:借助辅助递归函数Node* insert(Node *node, Key key, Value value),像根节点为node的二叉搜索树插入一个数据,返回值为根节点,如果node==NULL,那么新建一个节点返回,如果key<node->key, 则插入到左子树,当前返回的根节点为左子数。反之则到右子数

查找操作可以不用递归实现,直接使用while循环,根据大小到左右子树查询,这里的递归比较容易理解,其中查找返回的Value的指针,来处理Value不存在的情况。

遍历操作包括基本的三种DFS遍历,和层序遍历BFS遍历。

删除操作包括删除最小值,删除最大值,删除任意值

最小值一定没有左孩子,所以借助一个辅助的递归函数,Node* removeMin(Node* node),删除以node为根节点的最小值,返回值为当前的根节点,如果node->left==NULL(node为最小值),根节点为node->right,否则递归的到左子树中进行删除,根节点为node->left

最大值一定没有右孩子,同样可以借助一个辅助的递归函数,Node* removeMax(Node* node),  删除以node为根节点的最大值,返回值为当前的根节点,如果node->right==NULL(node为最大值),根节点为node->left,否则递归的到右子数中进行删除,根节点为node->right

删除任意节点操作用同样的递归方式实现,首先通过递归删除找到要删除的节点。如果左儿子为空或者右儿子为空,那么用前面的方法删除就行。如果不是,那么寻找左子数的最大值,或者右子数的最小值,删除右子数的最小值,返回的根节点为拷贝的右子数的最小值,拷贝的右子数的最小值的左耳子为前面节点的左儿子,然后删除要删除的节点。

#include <iostream>
#include <cassert>
#include <queue>
using namespace std;

template<typename Key, typename Value>
class BST {

private:
	struct Node {
		Key key;
		Value value;
		Node *left;
		Node *right;

		Node(Key key, Value value) {
			this->key = key;
			this->value = value;
			this->left = this->right = NULL;

		}

		Node(Node *node) {
			this->key = node->key;
			this->value = node->value;
			this->left = node->left;
			this->right = node->right;
		}
	};
	Node *root;
	int count;

public:
	BST() {
		root = NULL;
		count = 0;
	}
	~BST() {
		destory(root);
	}

	int size() {
		return count;
	}

	bool isEmpty() {
		return count == 0;
	}

	void insert(Key key, Value value) {
		root = insert(root, key, value);
	}

	bool contain(Key key) {
		return contain(root, key);
	}

	Value* search(Key key) {
		return search(root, key);
	}

	void preOrder() {
		preOrder(root);
	}

	void destory() {
		destory(root);
	}

	void levelOrder() {

		queue<Node*> q;
		q.push(root);
		while (!q.empty()) {

			Node* node = q.front();
			q.pop();
			cout << node->key << endl;
			if (node->left)
				q.push(node->left);
			if (node->right)
				q.push(node->right);
		}
	}
	
	// 寻找最小的键值
	Key minimum() {
		assert(count != 0);
		Node* minNode = minimum(root);
		return minNode->key;

	}

	// 寻找最大的键值
	Key maximun() {
		assert(count != 0);
		Node* maxNode = maximun(root);
		return maxNode->key;
	}

	// 从二叉树删除最小值
	void removeMin() {
		if (root)
			root = removeMin(root);
	}

	void removeMax() {
		if (root)
			root = removeMax(root);
	}


private:
	// 向node为根的二叉搜索树中,插入节点(key, value)
	// 返回插入新节点的二叉搜索树的根
	Node* insert(Node *node, Key key, Value value) {

		if (node == NULL) {
			count++;
			return new Node(key, value);
		}

		if (key == node->key)
			node->value = value;
		else if (key < node->key)
			node->left = insert(node->left, key, value);
		else
			node->right = insert(node->right, key, value);

		return node;

	}

	bool contain(Node* node, Key key) {
		if (node == NULL)
			return false;
		if (key == node->key)
			return true;
		else if (key < node->key)
			return contain(node->left, key);
		else
			return contain(node->right, key);
	}

	Value* search(Node* node, Key key) {

		if (node == NULL)
			return NULL;

		if (key == node->key) {
			return &(node->value);
		}
		else if (key < node->key) {
			return search(node->left, key);
		}
		else
			return search(node->right, key);
	}

	void preOrder(Node* node) {
		if (node != NULL) {
			cout << node->key << endl;
			preOrder(node->left);
			preOrder(node->right);
		}
	}

	void destory(Node* node) {

		if (node != NULL) {
			destory(node->left);
			destory(node->right);

			delete node;
			count--;
		}
	}

	Node* minimum(Node* node) {
		if (node->left == NULL)
			return node;
		
		return minimum(node->left);
	}

	Node* maximum(Node* node) {
		if (node->right == NULL)
			return node;

		return maximum(node->right);
	}

	void remove(Key key) {
		remove(root, key);

	}

	// 删除掉以node为根的二分搜索树中的最小节点
	// 返回删除节点后新的二分搜索树的根
	Node* removeMin(Node* node) {
		if (node->left == NULL) {
			Node* rightNode = node ->right;
			delete node;
			count--;
			return rightNode;
		}

		node->left = removeMin(node->left);
	}
	
	// 删除掉以node为根的二分搜索树中的最大节点
	// 返回删除节点后新的二分搜索树的根
	Node* removeMax(Node* node) {
		if (node->right == NULL) {
			Node* leftNode = node->left;
			delete node;
			count--;
			return leftNode;
		}
		node->right = removeMax(node->right);
	}

	// 删除掉以node为根的二分搜索树中键值为key的节点
	// 返回删除节点后新的二分搜索树的根
	Node* remove(Node* node, Key key) {
		if (node == NULL)
			return NULL;
		if (key < node->key) {
			node->left = remove(node->left, key);
			return node;
		}
		else if (key > node->key) {
			node->right = remove(node->right, key);
			return node;
		}
		else {
			// key == node->key
			if (node->left == NULL) {
				Node *rightNode = node->right;
				delete node;
				count--;
				return rightNode;
			}

			if (node->right == NULL) {
				Node *leftNode = node->left;
				delete node;
				count--;
				return leftNode;
			}

			Node *successor = new Node(minimum(node->right)); //右子树的最小值
			count++;
			successor->right = removeMin(node->right);
			successor->left = node->left;

			delete node;
			count--;

			return successor;
		}
	}
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值