C/C++二叉排序树基操,亲测有效无Bug!包含删除操作代码实现!!!

这篇博客面向已了解什么是二叉排序树、二叉树的应用场景是什么、二叉树基本操作的实现原理。

该博客不适合系统的去学习二叉排序树!!!主要是帮助急需代码实现的读者~

博客的内容主要分析了删除操作的一些细节问题,亲测有效无Bug!因为没有语言描述,可能有些晦涩,但是只要顺着把代码敲一遍,一定能够保证掌握二叉排序树的这些基本操作!!!

如果这篇博客有帮助你,点个赞呗~,话不多说,上代码。

二叉排序树的基本操作

// 头文件
#include <iostream>
#include <vector> // 容器,相当于数组
using namespace std;

1 二叉排序树结构体、创建新的节点

// 1.1 定义二叉排序树的存储结构
typedef int DataType;
typedef struct TreeNode {
	DataType data;
	struct TreeNode* left;
	struct TreeNode* right;
}TreeNode, * ASLTree;
// 1.2 创建新的节点
ASLTree CreateNode(DataType x) {
	ASLTree node = (ASLTree)malloc(sizeof(TreeNode));
	if (!node) exit(-1);
	node->data = x;
	node->left = NULL;
	node->right = NULL;
	return node;
}

2 二叉排序树的创建

// 2.1.1 插入节点(解决方案1)

void InsertNode(ASLTree& root, DataType val) {
	if (root == NULL) {
		root = CreateNode(val); // 这把钥匙配这扇门
	}
	else {
		if (val < root->data) {
			InsertNode(root->left, val); // root->left为NULL
		}
		else {
			InsertNode(root->right, val); // root->right为NULL
		}
	}
}
// (1) ASLTree root = NULL;    这个是一把钥匙,而不是门!!!
// (2) CreateNode(DatatType x) 创建了一个门
// (3) 如果直接是 ASLTree root,表示克隆了一把钥匙,去打开门,而不是使用原配的钥匙去打开的门

// (4) 加上 & ,则是将原配的钥匙携带到门旁,打开它
// 2.1.2 插入节点(解决方案2)
ASLTree InsertNode2(ASLTree root, DataType val) {
	if (root == NULL) {
		root = CreateNode(val);
	}
	else {
		if (val < root->data) {
			root->left = InsertNode2(root->left, val); // root->left为NULL
		}
		else {
			root->right = InsertNode2(root->right, val); // root->right为NULL
		}
	}
	return root;
}
// 2.2 通过数组构造二次排序树
ASLTree CreateSearchTree(vector<int>& vec) {
	ASLTree root = NULL; // (1)这个是一把钥匙,而不是门!!!
	for (int i = 0; i < vec.size(); i++) {
		//InsertNode(root, vec[i]);
		root = InsertNode2(root, vec[i]);
	}
	return root;
}

3 查找指定的节点

// 3.1 查找节点是否存在
bool SearchNode(ASLTree root, DataType val) {
	if (root == NULL) return false; // 最后指向空,没找到该节点
	if (val < root->data) {
		SearchNode(root->left, val);
	}
	else if (val > root->data) {
		SearchNode(root->right, val);
	}
	else { // 值相等,找到了
		return true;
	}
}

4 删除指定的节点

// 4.1 删除的指定的节点
ASLTree DeleteNode(ASLTree root, DataType val) {
	ASLTree p = NULL;  // 遍历指针
	ASLTree fp = NULL; // 遍历指针的父指针
	p = root;
	while (p != NULL) {
		fp = p; // 首次都是从根节点出发(根节点没有父节点)
		if (val < p->data) { // 三个分别为if 、else if、if!!!
			p = p->left;
		}
		else if (val > p->data) {
			p = p->right;
		}

		if (val == p->data) { // 特殊情况下,删除的节点是根节点
			break;
		}
	}
	if (p == NULL) {
		cout << "未找到你要删除的节点,删除失败!" << endl;
		return NULL;
	}
	// 接下来分四种情况
	// (1)左孩子右孩子都有(根节点和其他节点一样)
	if (p->left && p->right) {
		ASLTree q = p;
		fp = p; // 因为p下一步要更新到p->right,则需要更新fp=p                                      
		p = p->right; // 我们寻找右子树最小值
		while (p->left) {
			fp = p;
			p = p->left;
		}
		q->data = p->data; // 交换数据
		// 右子树的最小值所在节点可能是叶子结点,可能是只有右子树的节点
		if (fp->left == p) {
			fp->left = p->right; // 可能为空,不影响
		}
		else if (fp->right == p) {
			fp->right = p->right;
		}
		free(p); // 释放空间
		return root;
	}
	// (2)左孩子右孩子都没有(根节点和其他叶子节点不一样!)
	if (p->left == NULL && p->right == NULL) {
		if (p == root) {
			free(root);
			return NULL;
		}
		if (fp->left == p) {
			fp->left = NULL;
		}
		else if (fp->right == p) {
			fp->right = NULL;
		}
		free(p);
		return root;
	}
	// (3) 只有左孩子没有右孩子(根节点不同于其他节点)
	if (p->left != NULL && p->right == NULL) {
		if (p == root) {
			root = p->left;
			p->left = NULL; // 孤立要删除的根节点
			free(p);
			return root;
		}
		if (fp->left == p) {
			fp->left = p->left;
			p->left = NULL;
		}
		else if (fp->right == p) {
			fp->right = p->left;
			p->left = NULL;
		}
		free(p);
		return root;
	}
	// (4) 只有右孩子没有左孩子(根节点不同于其他节点)
	if (p->left == NULL && p->right != NULL) {
		if (p == root) {
			root = p->right;
			p->right = NULL; // 孤立要删除的根节点
			free(p);
			return root;
		}
		if (fp->left == p) {
			fp->left = p->right;
			p->right = NULL;
		}
		else if (fp->right == p) {
			fp->right = p->right;
			p->right = NULL;
		}
		free(p);
		return root;
	}
}

5 中序遍历二叉排序树

// 5.1 中序遍历二叉树
void InOrder(ASLTree root) {
	if (root == NULL) return;
	InOrder(root->left);
	cout << root->data << " ";
	InOrder(root->right);
}

6 主函数

int main(void) {
	DataType node;
	vector<int> vec{ 4,2,3,6,8,7,5,1,9,10 };

	cout << "通过容器生成二叉排序树:" << endl;
	ASLTree tree = CreateSearchTree(vec);

	cout << "该二叉排序树中序遍历如下:" << endl;
	InOrder(tree);
	cout << endl;

	cout << "请输入要查找的节点:" << endl;
	cin >> node;
	if (SearchNode(tree, node)) {
		cout << "找到了!" << endl;
	}
	else {
		cout << "该排序树中没有这个结点!" << endl;
	}

	cout << "请输入要删除的节点:" << endl;
	cin >> node;
	tree = DeleteNode(tree, node);
	cout << "删除后的二叉排序树中序遍历如下:" << endl;
	InOrder(tree);

	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值