二叉排序树基础知识与代码实现

二叉排序树基础知识

二叉排序树

名称:二叉排序树、二叉搜索树
性质:1. 左子树 < 根节点
2. 右子树 > 根节点
二叉排序树的中序遍历是一个升序数组。
二叉排序树解决排名相关的检索需求。

二叉排序树的插入

依次将待插入节点和当前节点比较,比其大则接着和右子树比较,小则接着和左子树比较,直到左子树或右子树为空,则插入相应的位置。

二叉排序树的删除

删除度为0的节点(叶子节点)

直接删除即可。

删除度为1的节点

度为1的节点即该节点有一个孩子,将该节点删除,然后将孩子挂在爷爷节点(删除节点的父节点)下方即可。

删除度为2的节点

前驱:整个二叉树中小于该节点的最大节点。即左子树的最大值。
后继:整个二叉树中大于该节点的最小节点。即右子树的最小值。
某个节点的前驱或后继,一定是度为0或度为1的节点,不可能是度为2的节点。
要删除某个度为2的节点时,首先找到该节点的前驱或后继,将前驱或后继放到要删除节点的位置,然后删除掉前驱或后继原来的位置(该位置一定是度为0或度为1的节点)。
总结:删除度为2的节点,找到前驱或后继后转换为删除度为0或1的节点。

二叉树删除与插入操作代码演示

#include <iostream>
using namespace std;

//二叉树定义
struct Node {
	Node(int key = 0, Node *left = nullptr, Node *right = nullptr)
		: key(key), left(left), right(right){};
	int key;
	Node *left, *right;
};

//初始化二叉树
Node *getNewNode(int key) {
	return new Node(key);
}

//二叉树插入
Node *insert(Node *root, int key) {
	if (root == nullptr) return getNewNode(key);
	if (root->key == key) return root;
	if (key < root->key) root->left = insert(root->left, key);
	else root->right = insert(root->right, key);
	return root;
}

//寻找前驱节点
Node *getPrecursor(Node *root) {
	Node *node = root->left;
	while (node->right) node = node->right;
	return node;
}

//二叉树删除操作
Node *erase(Node *root, int key) {
	if (root == nullptr) return root; //递归边界
	if (key < root->key) root->left =  erase(root->left, key);
	else if (key > root->key) root->right =  erase(root->right, key);
	else {  //当前节点为要删除的节点
		if (root->left == nullptr || root->right == nullptr) { 
			//度为0和度为1的节点都可以用这个条件表示
			Node *temp = root->left ? root->left : root->right;
			delete root;
			return temp;
		}
		else {
			//要删除度为2的节点
			Node *pre = getPrecursor(root);
			root->key = pre->key;
			root->left = erase(root->left, pre->key);
		}
	}
	return root;
}

void clear(Node *root) {
	//要删除整棵树
	if (root == nullptr) return;
	clear(root->left);
	clear(root->right);
	delete root;
	return;
}

void output(Node *root) {
	//递归输出一棵树
	if (root == nullptr) return ;
	output(root->left);
	cout << root->key << " ";
	output(root->right);
	return;
}

int main() {
	int op, val;
	Node *root;
	while (cin >> op >> val) {
		switch (op) {
			case 0: root = insert(root, val); break;
			case 1: root = erase(root, val); break;
		}
		output(root); cout << endl;
	}
	return 0;
}

代码编程小技巧:1. 删除度为0和度为1的节点可以同时表示;2. 前驱节点直接从左子树一直向右找;3. 递归插入,递归删除。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值