二叉搜索树的概念

如果左子树不为空,则左子树上所有结点的权值都要小于该点的权值

如果右子树不为空,则右子树上所有的结点的权值都要大于该点的权值

二叉查找树上的结点的权值唯一,且结点左右子树都是二叉查找树,并且左子树的权值都要小于右子树的权值

数据结构 二叉搜索树_权值

相应操作的实现:

插入操作:

1.根节点为空则新元素直接作为根节点插入,否则传入的参数与根结点进行比较

2.value等于当前结点的话直接返回,小于当前结点跳第3步,大于当前结点跳第4步

3.判断当前结点是否存在左子,如果存在左子,则递归左子,否则直接插入

4.判断当前结点是否存在右子,如果存在右子,则递归右子,否则直接插入

相应实现代码如下:

void insert(Type value) {
		if (data == value) {   //已存在元素的话,就退出
			return;   
		}
		else if (data < value) {  //向右子树插入
			if (rchild == nullptr) {
				rchild = new Node<Type>(value);
			}
			else {
				rchild->insert(value);
			}
		}
		else {             //向左子树插入
			if (lchild == nullptr) {
				lchild = new Node<Type>(value);
			}
			else {
				lchild->insert(value);
			}

搜索操作和插入操作算法是一致的

Node* search(Type value) {
		if (data == value) {   //如果就是的话,返回当前对象
			return this;
		}
		else if(data < value){
			if (rchild == nullptr) {
				return nullptr;
			}
			else {
				rchild->search(value);
			}
		}
		else {
			if (lchild == nullptr) {
				return nullptr;
			}
			else {
				lchild->search(value);
			}
		}
	}

删除操作:

二叉搜索树的删除操作较为繁琐

首先需要找到删除结点的前驱或是后继,

前驱是指值比它小的节点中最大的一个节点

后继是指值比它大的节点中最小的一个节点

找前驱的步骤:

1.找到当前节点的左孩子,如果左孩子不存在,则无前驱

2.若存在左子,则在左子上向右遍历,遍历到最后一个右子就是节点的前驱

找后继的步骤:

1.找到当前节点的右孩子,如果右孩子不存在,则无后继

2.若存在右孩子,则在右子上不断向左遍历,遍历到最后一个左子就是节点的后继

相关的代码如下:

Node<Type>* predecessor() {
		Node<Type>* temp = lchild;
		while (temp != nullptr && temp->rchild != nullptr) {
			temp = temp->rchild;
		}
		return temp;  //前驱
	}
	Node<Type>* successor() {
		Node<Type>* temp = rchild;
		while (temp != nullptr && temp->lchild != nullptr) {
			temp = temp->lchild;
		}
		return temp;  //后继
	}

有了前驱和后继,就可以执行删除操作了

删除节点分成两种情况:

1.删除度为1或0的节点(只有一个孩子或者它是叶子节点)

2.删除度超过1的节点

删除度为0或1的节点的操作比较简单

1.如果是左子,将被删除节点的左子的父亲节点更新为被删除节点的父亲节点

2.如果是右子,将被删除节点的右子的父亲节点更新为被删除节点的父亲节点

3.将被删节点的父亲节点的(左子或右子)更新为被删节点的(左子或右子)

4,删除被删节点

//删除度为1或0的节点
void remove_node(Node<Type>* delete_node) {  
		Node<Type>* temp = nullptr;
		if (delete_node->lchild != nullptr) {
			temp = delete_node->lchild;
			temp->father = delete_node->father;
		}
		if (delete_node->rchild != nullptr) {
			temp = delete_node->rchild;
			temp->father = delete_node->father;
		}

		if (delete_node->father->lchild == delete_node) {
			delete_node->father->lchild = temp;
		}
		else {
			delete_node->father->rchild = temp;
		}

		delete_node->lchild = nullptr;
		delete_node->rchild = nullptr;
		delete delete_node;
	}

有了以上叶子节点的删除法,我们就可以删除度为2以上的节点,方法如下:

1.通过搜索函数定位到要被删除的节点,如果节点不存在,直接返回null

2.寻找这个被删结点的前驱或后继,如果前驱或后继存在,则将当前的值与前驱或后继的值进行交换,如果不存在,则直接删除当前结点。

3.交换后,删除前驱或后继结点

代码如下:

bool delete_tree(Type value) {
		Node<Type>*current_node = nullptr, *delete_node = nullptr;
		current_node = search(value);
		if (current_node == nullptr) {
			return false;      //直接返回错误
		}
		if (current_node->lchild != nullptr) {
			delete_node = current_node->predecessor();
		}
		else if (current_node->rchild != nullptr) {
			delete_node = current_node->successor();
		}
		else {
			delete_node = current_node;
		}
		//删除结点
		current_node->data = delete_node->data;
		remove_node(delete_node);
		return true;
	}

整颗二叉搜索树的完整代码如下:

#include<iostream>
using std::cin;
using std::cout;
using std::endl;
template <typename Type> class Node {
public:
	Type data;
	Node<Type> *lchild, *rchild, *father;
	Node(Type _data, Node<Type> *_father = NULL) {
		data = _data;
		lchild = NULL;
		rchild = NULL;
		father = _father;
	}
	~Node() {
		if (lchild != NULL) {
			delete lchild;
		}
		if (rchild != NULL) {
			delete rchild;
		}
	}
	void insert(Type value) {
		if (value == data) {
			return;
		}
		else if (value > data) {
			if (rchild == NULL) {
				rchild = new Node<Type>(value, this);
			}
			else {
				rchild->insert(value);
			}
		}
		else {
			if (lchild == NULL) {
				lchild = new Node<Type>(value, this);
			}
			else {
				lchild->insert(value);
			}
		}
	}
	Node<Type>* search(Type value) {
		if (data == value) {
			return this;
		}
		else if (value > data) {
			if (rchild == NULL) {
				return NULL;
			}
			else {
				return rchild->search(value);
			}
		}
		else {
			if (lchild == NULL) {
				return NULL;
			}
			else {
				return lchild->search(value);
			}
		}
	}
	Node<Type>* predecessor() {
		Node<Type>* temp = lchild;
		while (temp != nullptr && temp->rchild != nullptr) {
			temp = temp->rchild;
		}
		return temp;  //前驱
	}
	Node<Type>* successor() {
		Node<Type>* temp = rchild;
		while (temp != nullptr && temp->lchild != nullptr) {
			temp = temp->lchild;
		}
		return temp;  //后继
	}
	void remove_node(Node<Type>* delete_node) {  //度为1或0
		Node<Type>* temp = nullptr;
		if (delete_node->lchild != nullptr) {
			temp = delete_node->lchild;
			temp->father = delete_node->father;
		}
		if (delete_node->rchild != nullptr) {
			temp = delete_node->rchild;
			temp->father = delete_node->father;
		}

		if (delete_node->father->lchild == delete_node) {
			delete_node->father->lchild = temp;
		}
		else {
			delete_node->father->rchild = temp;
		}

		delete_node->lchild = nullptr;
		delete_node->rchild = nullptr;
		delete delete_node;
	}
	bool delete_tree(Type value) {
		Node<Type>*current_node = nullptr, *delete_node = nullptr;
		current_node = search(value);
		if (current_node == nullptr) {
			return false;      //直接返回错误
		}
		if (current_node->lchild != nullptr) {
			delete_node = current_node->predecessor();
		}
		else if (current_node->rchild != nullptr) {
			delete_node = current_node->successor();
		}
		else {
			delete_node = current_node;
		}
		//删除结点
		current_node->data = delete_node->data;
		remove_node(delete_node);
		return true;
	}

	void print() {
		if (lchild != nullptr) {
			lchild->print();
		}
		cout << data << " ";
		if (rchild != nullptr) {
			rchild->print();
		}
	}
};
template <typename Type> class BinaryTree {
private:
	Node<Type> *root;
public:
	BinaryTree() {
		root = NULL;
	}
	~BinaryTree() {
		delete root;
	}
	void insert(Type value) {
		if (root == NULL) {
			root = new Node<Type>(value);
		}
		else {
			root->insert(value);
		}
	}
	bool find(Type value) {
		if (root == NULL) {
			return false;
		}
		if (root->search(value) == NULL) {
			return false;
		}
		else {
			return true;
		}
	}
	bool delete_tree(Type value) {
		if (root == nullptr) {
			return false;
		}
		return root->delete_tree(value);
	}

	void print() {
		if (root != nullptr) {
			root->print();
		}
	}
};
int main() {
	BinaryTree<int> binarytree;
	int m;
	cin >> m;
	for (int i = 0; i < m; ++i) {
		int n;
		cin >> n;
		binarytree.insert(n);
	}
	
	int c;
	cin >> c;
	for (int i = 0; i < c; ++i) {
		int cl;
		cin >> cl;
		binarytree.delete_tree(cl);
	}
	binarytree.print();

	system("PAUSE");
	return 0;
}