二叉搜索树 的实现

什么是二叉搜索树?二叉搜索树有什么特性?二叉搜索树是怎样实现的?

1:二叉搜索树 又称二叉查找树、二叉排序树,顾名思义二叉搜索树的查找效率非常的高,而且二叉搜索树要满足二叉树的结构特性故每个根节点最多只有两个叶子节点。这的二叉搜索树和前面学的堆的结构也是相似的。

树的图像结构:

 2:二叉搜索树的特性:由上面的二叉树结构图像可以看出左子节点的值要比根节点小而右子节点的值要比根节点大,每一棵子树都是这样,这就是搜索二叉树的特性。

1)若左子树不空,则左子树上所有节点的值均小于或等于它的根节点的值;

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

3)左、右子树也分别为二叉排序树

3:二叉搜索树的实现

二叉搜索树的构建也是跟据其特性构建的,构建的二叉搜索树要将每个子节点连接在父节点上,所以要定义两指针一个为右子节点指针指向右字节点,另一个为左子节点指针指向左子节点。

代码实现:

typedef struct binaryTree {
	elemStyle date;
	struct binaryTree* leftChild;
	struct binaryTree* rightChild;
}Btree;

表示树的结构体定义完以后我们要做的是构建一颗二叉搜索树

//在二叉搜索树中插入节点
bool insertBinaryTree(Btree** root, Btree* node) {
	Btree* tmp, * father = NULL;
	if (!node) {
		return false;//节点没有分配内存
	}
	else {
		node->leftChild = NULL;
		node->rightChild = NULL;
	}

	if (*root) {
		tmp = *root;
	}
	else {
		*root = node;
		return true;
	}

	while (tmp) {
		father = tmp;
		if (compare(tmp->date, node->date)) {
			tmp = tmp->rightChild;
		}
		else {
			tmp = tmp->leftChild;
		}
	}
	if (compare(father->date, node->date)) {
		father->rightChild = node;
	}
	else {
		father->leftChild = node;
	}
	return true;
}

构建的思路:跟据二叉搜索树的特性,左字节点一定小于等于根节点,右字节点一定大于等于根节点。如果没有根节点那么就将第一个节点作为根节点并返回,如果有根节点那么就判断根节点和入树的节点哪个的值要大,如果根节点的值大于当前的值那么就锁定到右字节点上否则就锁定到左子节点上,继续循环比较直到根节点指向的子节点为空,将当前节点连接到根节点上,新入树的节点也是这样操作。

树构建好以后要左的是遍历树,前序遍历树的实现我们用栈实现

//前序遍历二叉树
void ergodicBinaryTree(Btree* root) {
	if (!root)return;
	Stack stack;
	initStack(stack);
	Btree tmp;
	enterStack(stack, *root);
	cout << "树中的元素有:";

	while (stack.top != stack.base) {
		outStack(stack, tmp);
		cout << tmp.date << "  ";
		if (tmp.rightChild) {
			enterStack(stack, *tmp.rightChild);
		}
		if (tmp.leftChild) {
			enterStack(stack, *tmp.leftChild);
		}
	}
	destoryStack(stack);
}

实现的具体思路:

在之前已经将树构建好了,所以第一步要做的就是将第一个节点入栈,判断它两个子节点是否为空,将不为空的节点入栈,进行了依次循环后将最后入栈的节点出栈,再判断该节点的子节点是否为空不为空则继续入栈,连续进行此操作就可以实现树种元素的打印

删除树中的节点,递归实现,所以如果要想看懂这操作要看得懂递归

//删除树的节点
Btree* deleteBinaryTree(Btree* root, elemStyle index, Btree*& node) {
	//树中没有这个节点
	if (root == NULL)return NULL;
	if (compare(root->date, index)) {
		root->rightChild = deleteBinaryTree(root->rightChild, index, node);
		return root;
	}
	if (compare(index, root->date)) {
		root->leftChild = deleteBinaryTree(root->leftChild, index, node);
		return root;
	}
	node = root;
	//左右子节点都为空
	if (!root->leftChild && !root->rightChild)return NULL;
	//左节点为空右节点不为空
	if (!root->leftChild && root->rightChild)return root->rightChild;
	//右节点为空左节点不为空
	if (!root->rightChild && root->leftChild)return root->leftChild;
	//左右节点都不为空
	root->date = findBinaryTree(root->leftChild);
	root->leftChild = deleteBinaryTree(root->leftChild, root->date, node);
	return root;
}

//找到最大节点
elemStyle findBinaryTree(Btree* node) {
	while (node->rightChild) {
		node = node->rightChild;
	}
	return node->date;
}

由于该操做的逻辑比较复杂就不再讲解

据体代码实现

#pragma once
#include<iostream>

using namespace std;

typedef int elemStyle;
#define MAX_SIZE 28

typedef struct binaryTree {
	elemStyle date;
	struct binaryTree* leftChild;
	struct binaryTree* rightChild;
}Btree;

typedef struct _stack {
	Btree* top;
	Btree* base;
}Stack;

bool initStack(Stack& stack); //初始化栈
void enterStack(Stack& stack, Btree treeNode);//将元素入栈
void outStack(Stack& stack, Btree& tree);//将元素出栈
void destoryStack(Stack& stack);//销毁栈

//初始化栈
bool initStack(Stack& stack) {
	stack.base = new Btree[MAX_SIZE];
	if (!stack.base)return false;
	stack.top = stack.base;
	return true;
}

//将元素入栈
void enterStack(Stack& stack, Btree treeNode) {
	if (stack.top - stack.base == MAX_SIZE)return;
	*(stack.top++) = treeNode;
	return;
}

//将元素出栈
void outStack(Stack& stack, Btree& tree) {
	if (stack.top == stack.base)return;
	tree = *(--stack.top);
	return;
}

//销毁栈
void destoryStack(Stack& stack) {
	if (stack.base) {
		delete stack.base;
		stack.top = NULL;
		stack.base = NULL;
	}
}
#pragma once
#include"_stack.h"

#define compare(a,b) (a < b)
#define equal(a,b) (a == b)

bool insertBinaryTree(Btree** root, Btree* node);//在二叉搜索树中插入节点
void ergodicBinaryTree(Btree* root);//遍历二叉树
Btree* deleteBinaryTree(Btree* root, elemStyle index, Btree*& node);//删除树的节点
elemStyle findBinaryTree(Btree* node);//找到最大节点

//在二叉搜索树中插入节点
bool insertBinaryTree(Btree** root, Btree* node) {
	Btree* tmp, * father = NULL;
	if (!node) {
		return false;//节点没有分配内存
	}
	else {
		node->leftChild = NULL;
		node->rightChild = NULL;
	}

	if (*root) {
		tmp = *root;
	}
	else {
		*root = node;
		return true;
	}

	while (tmp) {
		father = tmp;
		if (compare(tmp->date, node->date)) {
			tmp = tmp->rightChild;
		}
		else {
			tmp = tmp->leftChild;
		}
	}
	if (compare(father->date, node->date)) {
		father->rightChild = node;
	}
	else {
		father->leftChild = node;
	}
	return true;
}

//前序遍历二叉树
void ergodicBinaryTree(Btree* root) {
	if (!root)return;
	Stack stack;
	initStack(stack);
	Btree tmp;
	enterStack(stack, *root);
	cout << "树中的元素有:";

	while (stack.top != stack.base) {
		outStack(stack, tmp);
		cout << tmp.date << "  ";
		if (tmp.rightChild) {
			enterStack(stack, *tmp.rightChild);
		}
		if (tmp.leftChild) {
			enterStack(stack, *tmp.leftChild);
		}
	}
	destoryStack(stack);
}

//删除树的节点
Btree* deleteBinaryTree(Btree* root, elemStyle index, Btree*& node) {
	//树中没有这个节点
	if (root == NULL)return NULL;
	if (compare(root->date, index)) {
		root->rightChild = deleteBinaryTree(root->rightChild, index, node);
		return root;
	}
	if (compare(index, root->date)) {
		root->leftChild = deleteBinaryTree(root->leftChild, index, node);
		return root;
	}
	node = root;
	//左右子节点都为空
	if (!root->leftChild && !root->rightChild)return NULL;
	//左节点为空右节点不为空
	if (!root->leftChild && root->rightChild)return root->rightChild;
	//右节点为空左节点不为空
	if (!root->rightChild && root->leftChild)return root->leftChild;
	//左右节点都不为空
	root->date = findBinaryTree(root->leftChild);
	root->leftChild = deleteBinaryTree(root->leftChild, root->date, node);
	return root;
}

//找到最大节点
elemStyle findBinaryTree(Btree* node) {
	while (node->rightChild) {
		node = node->rightChild;
	}
	return node->date;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值