二叉排序树C++实现

二叉排序树定义

二叉排序树又称二叉查找树,它或者是一棵空的二叉树,或者是具有下列性质的二叉树:
(1)若它的左子树不空,则左子树上所有结点的值均小于根结点的值;

(2)若它的右子树不空,则右子树上所有结点的值均大于根结点的值;

(3)它的左右子树也都是二叉排序树。

树节点类定义

//树节点类
class TNode {
public:
	int data;
	TNode* left, * right;
	TNode(int d) :left(nullptr), right(nullptr), data(d) {}
	TNode() :left(nullptr), right(nullptr) {}
};

二叉排序树类定义

实现了树的生成,新节点插入,旧结点删除的功能。

//二叉排序树
class BinarySortTree
{
public:
	BinarySortTree(int a[],int n);//构造函数
	~BinarySortTree();//析构

	void Insert(int value);//插入新节点
	void Delete(int value);//删除节点

	void PreOrder();//前序遍历
	void InOrder();//中序遍历,这两个遍历是为了确定树的形状是否正确
private:
	void _del(TNode* cur);
	void _pre(TNode* cur);
	void _in(TNode* cur);
	TNode* root;//根结点
};

树的生成和析构

//构造函数
BinarySortTree::BinarySortTree(int a[], int n)
{
	for (int i = 0; i < n; i++)
		Insert(a[i]);
}
//析构
BinarySortTree::~BinarySortTree()
{
	if(root!=nullptr)
		_del(root);
}

void BinarySortTree::_del(TNode* cur)
{
	if (cur->left == nullptr && cur->right == nullptr) return;
	if (cur->left) _del(cur->left);
	if (cur->right) _del(cur->right);

节点插入

主要思路就是寻找需要插入的位置的指针cur

//插入新节点
void BinarySortTree::Insert(int value)
{
	if (root==nullptr){//当为空树时
		root = new TNode(value);
		return;
	}
	TNode* cur = root;//记录当前指针位置
	TNode* prev = nullptr;//记录当前指针的前继,初始为空指针
	TNode* newNode = new TNode(value);//创建新节点
	while (cur) {//使cur位移到空指针处,那么它的前继就是我们需要插入新节点的地方
		if (cur->data > value) {
			if (cur->left) {
				prev = cur;
				cur = cur->left;
			}
			else {//这种情况应该只存在在初始化时,根结点的左右孩子节点至少存在一个为空时可能会跳转进来
				cur->left = newNode;
				return;
			}
		}
		if (cur->data <= value) {
			if (cur->right) {
				prev = cur;
				cur = cur->right;
			}
			else {
				cur->right = newNode;
				return;
			}
		}
	}
	//当当前结点为空时,在前继结点处插入
	if (prev->data > value)
		prev->left = newNode;
	else
		prev->right = newNode;
}

节点删除

分为两部分变成,第一部分,寻找与value值相等的cur指针,第二部分执行删除操作。

删除的方法是:

从某个子树中找出一个结点s,其值能代替cur的值,这样,就可以用点s的值去替换结点cur的值,再删除结点s。

这个值应该是大于结点cur的最小者(或者小于结点cur的最大者)。

伪代码

1,若结点cur是叶子,则直接删除结点cur;
2,若结点cur只有左子树,则只需重接cur的左子树;若结点cur只有右子树,则只需重接cur的右子树;
3,若结点cur的左右子树均不空,则
      3.1 查找结点cur的右子树上的最左下结点cur以及结点cur的双亲结点temp;
      3.2 将结点s数据域替换到被删结点cur的数据域;
      3.3若结点cur的右孩子无左子树,则将cur的右子树接到par的右子树上否则,将s的右子树接到结点cur的左子树上;
      3.4 删除结点s;

该伪代码仅仅举了一种情况,即cur节点的前继节点prev的左孩子节点的情况,而下面的程序都考虑到了所有情况。其实删除的操作比较麻烦的部分是当cur节点的左右子树都不为空时的情况,需要找到一个值应大于结点cur的最小者(或者小于结点cur的最大者)来代替cur的值。

 

//删除节点,假定一定存在这个节点
void BinarySortTree::Delete(int value)
{
	if (root == nullptr) return;
	TNode* cur = root;//记录当前指针位置
	TNode* prev = nullptr;//记录当前指针的前继,初始为空指针
	while (cur){//使cur位移到cur->data=value处
		if (cur->data > value) {
			if (cur->left) {
				prev = cur;
				cur = cur->left;
			}
		}
		else if (cur->data < value) {
			if (cur->right) {
				prev = cur;
				cur = cur->right;
			}
		}
		else if (cur->data == value)
			break;
	}



	if (prev == nullptr) { delete root; return; }//说明此时只有根结点符合要求
	if (cur->left == nullptr && cur->right == nullptr) {//当cur为叶子结点时
		if (prev->left == cur)
			prev->left = nullptr;
		else if (prev->right == cur)
			prev->right = nullptr;
		delete cur;
		return;
	}
	else if (cur->left && cur->right == nullptr) {//当cur的左孩子存在,右孩子不存在时
		if (prev->left == cur)
			prev->left = cur->left;
		else if (prev->right == cur)
			prev->right = cur->left;
		delete cur;
		return;
	}
	else if (cur->left == nullptr && cur->right) {//当cur的左孩子不存在,右孩子存在时
		if (prev->left == cur)
			prev->left = cur->right;
		else if (prev->right == cur)
			prev->right = cur->right;
		delete cur;
		return;
	}
	else if (cur->left && cur->right) {//左右孩子都存在时
		if (prev->left == cur) {//当cur为prev的左子树时,寻找cur右孩子节点中最左边的叶节点
			TNode* temp = cur;
			TNode* s = cur->right;
			while (s->left != nullptr) {
				temp = s;
				s = s->left;
			}
			cur->data = s->data;
			if (temp == cur) temp->right = s->right;//当temp未发生移动时,此时即cur的右孩子为叶子结点
			else temp->left = s->right;//temp发生了移动,此时要删除s节点
			delete s;
			return;
		}
		else if (prev->right == cur) {//当cur为prev的右子树时,寻找cur左孩子节点中最右边的叶节点
			TNode* temp = cur;
			TNode* s = cur->left;
			while (s->right!=nullptr)
			{
				temp = s;
				s = s->right;
			}
			cur->data = s->data;
			if (temp == cur) temp->left = s->left;
			else temp->right = s->left;
			delete s;
			return;
		}
	}
}

全部代码

BinarySortTree.h

#pragma once
#ifndef BINARYSORTTREE_H
#define BINARYSORTTREE_H
#include<iostream>
using std::cout;
using std::endl;
//树节点类
class TNode {
public:
	int data;
	TNode* left, * right;
	TNode(int d) :left(nullptr), right(nullptr), data(d) {}
	TNode() :left(nullptr), right(nullptr) {}
};

//二叉排序树
class BinarySortTree
{
public:
	BinarySortTree(int a[],int n);//构造函数
	~BinarySortTree();//析构

	void Insert(int value);//插入新节点
	void Delete(int value);//删除节点

	void PreOrder();//前序遍历
	void InOrder();//中序遍历,这两个遍历是为了确定树的形状是否正确
private:
	void _del(TNode* cur);
	void _pre(TNode* cur);
	void _in(TNode* cur);
	TNode* root;//根结点
};

//构造函数
BinarySortTree::BinarySortTree(int a[], int n)
{
	for (int i = 0; i < n; i++)
		Insert(a[i]);
}
//析构
BinarySortTree::~BinarySortTree()
{
	if(root!=nullptr)
		_del(root);
}

//插入新节点
void BinarySortTree::Insert(int value)
{
	if (root==nullptr){//当为空树时
		root = new TNode(value);
		return;
	}
	TNode* cur = root;//记录当前指针位置
	TNode* prev = nullptr;//记录当前指针的前继,初始为空指针
	TNode* newNode = new TNode(value);//创建新节点
	while (cur) {//使cur位移到空指针处,那么它的前继就是我们需要插入新节点的地方
		if (cur->data > value) {
			if (cur->left) {
				prev = cur;
				cur = cur->left;
			}
			else {//这种情况应该只存在在初始化时,根结点的左右孩子节点至少存在一个为空时可能会跳转进来
				cur->left = newNode;
				return;
			}
		}
		if (cur->data <= value) {
			if (cur->right) {
				prev = cur;
				cur = cur->right;
			}
			else {
				cur->right = newNode;
				return;
			}
		}
	}
	//当当前结点为空时,在前继结点处插入
	if (prev->data > value)
		prev->left = newNode;
	else
		prev->right = newNode;
}

//删除节点,假定一定存在这个节点
void BinarySortTree::Delete(int value)
{
	if (root == nullptr) return;
	TNode* cur = root;//记录当前指针位置
	TNode* prev = nullptr;//记录当前指针的前继,初始为空指针
	while (cur){//使cur位移到cur->data=value处
		if (cur->data > value) {
			if (cur->left) {
				prev = cur;
				cur = cur->left;
			}
		}
		else if (cur->data < value) {
			if (cur->right) {
				prev = cur;
				cur = cur->right;
			}
		}
		else if (cur->data == value)
			break;
	}
	if (prev == nullptr) { delete root; return; }//说明此时只有根结点符合要求
	if (cur->left == nullptr && cur->right == nullptr) {//当cur为叶子结点时
		if (prev->left == cur)
			prev->left = nullptr;
		else if (prev->right == cur)
			prev->right = nullptr;
		delete cur;
		return;
	}
	else if (cur->left && cur->right == nullptr) {//当cur的左孩子存在,右孩子不存在时
		if (prev->left == cur)
			prev->left = cur->left;
		else if (prev->right == cur)
			prev->right = cur->left;
		delete cur;
		return;
	}
	else if (cur->left == nullptr && cur->right) {//当cur的左孩子不存在,右孩子存在时
		if (prev->left == cur)
			prev->left = cur->right;
		else if (prev->right == cur)
			prev->right = cur->right;
		delete cur;
		return;
	}
	else if (cur->left && cur->right) {//左右孩子都存在时
		if (prev->left == cur) {//当cur为prev的左子树时,寻找cur右孩子节点中最左边的叶节点
			TNode* temp = cur;
			TNode* s = cur->right;
			while (s->left != nullptr) {
				temp = s;
				s = s->left;
			}
			cur->data = s->data;
			if (temp == cur) temp->right = s->right;//当temp未发生移动时,此时即cur的右孩子为叶子结点
			else temp->left = s->right;//temp发生了移动,此时要删除s节点
			delete s;
			return;
		}
		else if (prev->right == cur) {//当cur为prev的右子树时,寻找cur左孩子节点中最右边的叶节点
			TNode* temp = cur;
			TNode* s = cur->left;
			while (s->right!=nullptr)
			{
				temp = s;
				s = s->right;
			}
			cur->data = s->data;
			if (temp == cur) temp->left = s->left;
			else temp->right = s->left;
			delete s;
			return;
		}
	}
}

void BinarySortTree::PreOrder()
{
	if (root) _pre(root);
}

void BinarySortTree::InOrder()
{
	if (root) _in(root);
}

void BinarySortTree::_del(TNode* cur)
{
	if (cur->left == nullptr && cur->right == nullptr) return;
	if (cur->left) _del(cur->left);
	if (cur->right) _del(cur->right);
}

void BinarySortTree::_pre(TNode* cur)
{
	if (cur == nullptr) return;
	cout << cur->data << " ";
	_pre(cur->left);
	_pre(cur->right);
}

void BinarySortTree::_in(TNode* cur)
{
	if (cur == nullptr) return;
	_in(cur->left);
	cout << cur->data << " ";
	_in(cur->right);
}

#endif // !BINARYSORTTREE_H

main.cpp

#include"BinarySortTree.h"


int main()
{

	int a[] = { 1,23,2,4,12,0,3,6 };
	BinarySortTree mytree(a, 8);
	mytree.PreOrder();
	cout << endl;
	mytree.InOrder();
	cout << endl;
	
	mytree.Delete(0);
	mytree.PreOrder();
	cout << endl;
	mytree.InOrder();
	cout << endl;
	return 1;
}

 

  • 0
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
二叉链表是一种常用的数据结构,可以用来实现二叉排序树二叉排序树是一种特殊的二叉树,它满足以下两个条件: 1. 左子树上所有节点的值都小于根节点的值; 2. 右子树上所有节点的值都大于根节点的值。 在C++中,我们可以通过定义一个二叉树结构体来实现二叉排序树。具体实现步骤如下: 1. 定义二叉树结构体: ``` struct TreeNode { int val; TreeNode *left; TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) {} }; ``` 2. 实现插入操作: ``` void insert(TreeNode*& root, int val) { if (!root) { root = new TreeNode(val); return; } if (val < root->val) { insert(root->left, val); } else if (val > root->val) { insert(root->right, val); } } ``` 3. 实现查找操作: ``` bool search(TreeNode* root, int val) { if (!root) { return false; } if (root->val == val) { return true; } else if (val < root->val) { return search(root->left, val); } else { return search(root->right, val); } } ``` 4. 实现删除操作: ``` void remove(TreeNode*& root, int val) { if (!root) { return; } if (root->val == val) { if (!root->left && !root->right) { delete root; root = NULL; } else if (!root->left) { TreeNode* temp = root; root = root->right; delete temp; } else if (!root->right) { TreeNode* temp = root; root = root->left; delete temp; } else { TreeNode* temp = root->right; while (temp->left) { temp = temp->left; } root->val = temp->val; remove(root->right, temp->val); } } else if (val < root->val) { remove(root->left, val); } else { remove(root->right, val); } } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值