数据结构---树(二叉搜索树)

二叉树特点:

最多只有两个节点,左边的分支称之为左节点,右边的分支称之为右节点。
(1) 在非空二叉树中,第 i-1 层的结点总数不超过 , i>=1;
(2) 深度为 h-1 的二叉树最多有 个结点(h>=1),最少有 h 个结点;
(3) 对于任意一棵二叉树,如果其叶结点数为
N0,而度数为 2 的结点总数为 N2,则 N0=N2+1;

二叉搜索树特点:

又称二叉查找树、二叉排序树。它是一颗空树或是满足下列性质的二叉树:
1)若左子树不空,则左子树上所有节点的值均小于或等于它的根节点的值;
2)若右子树不空,则右子树上所有节点的值均大于或等于它的根节点的值;
3)左、右子树也分别为二叉排序树。

创建二叉搜索树的节点:
节点由三部分组成,数据,指向左右节点的指针。

#define IsLess(a,b) (a<b)
#define IsEqual(a,b)(a==b)
using namespace std;
typedef int ElemType;
typedef struct Btree {
    
    
	ElemType data;
	struct Btree* lchild, *rchild;
}Bnode;

插入节点:

	核心思想:先判断要插入的节点是否为空,不空的话把两个指针赋值为NULL。
	再判断是否有根节点,没有的话直接该节点设置为根节点并返回,有的话定义两个临时变量 tmp,parent先让tmp指向根节点。
	与要插入的节点进行比较,根据二叉搜索树的规则,判断该往那边走,直到走到空,并走之前先将这个tmp赋值parent因为最后tmp最指向空,所以插入节点还得靠parent。
bool InsertBtree(Bnode** tree, Bnode* node) {
    
    
	if (!node) {
    
    
		cout << "节点为空" << endl;
		return false;
	}
	else {
    
    
		node->lchild = NULL;
		node->rchild = NULL;
	}
	if (!(*tree)) {
    
    
		(*tree) = node;
		return true;
	}
	Bnode* parent = NULL;
	Bnode* tmp = *(tree);
	while (tmp) {
    
    
		parent = tmp;
		if (IsLess(node->data, tmp->data)) {
    
    
			tmp = tmp->lchild;
		}
		else {
    
    
			tmp = tmp->rchild;
		}
	}
	if (IsLess(node->data, parent->data)) {
    
    
		parent->lchild = node;
	}
	else {
    
    
		parent->rchild = node;
	}
	return true;
}

删除:

	先通过遍历寻找目标,找到节点后,删除,删除有4种情况
	1.该节点没有子节点,那么直接删除
	2.该节点仅有左子节点,那么让上一个节点直接指向左子节点
	3.该节点仅有右 子节点,那么让上一个节点直接指向右子节点
	4.如果该节点1左右子节点都有,那么找到该节点左子节点中最大值,
	也就是说找到该节点1左子节点中最右边的值,这个值比该节点1的左边其他值都要大,将该值赋给节点1,然后通过删除函数,将赋值节点去掉
Bnode* DeleteNode(Bnode* root, int key,Bnode * &Deletenode) {
    
    
	
	if (root == NULL) return root;
 	if (root->data > key) {
    
    //比该节点大,去左边找
		root->lchild = DeleteNode(root->lchild, key,Deletenode);
		return root;
	}
	if (root->data < key) {
    
    //比该节点小,去右边找
		root->rchild = DeleteNode(root->rchild, key,Deletenode);
		return root;
	}
	Deletenode = root;
	//删除节点不存在左右子节点,即为叶子节点,直接删除
	if (root->lchild == NULL && root->rchild == NULL) return NULL;
	//删除节点只存在右子节点,直接用右子节点取代删除节点
	if (root->lchild == NULL && root->rchild != NULL) return root->rchild;
	//删除节点只存在左子节点,直接用左子节点取代删除节点
	if (root->lchild != NULL && root->rchild == NULL) return root->lchild;
	删除节点存在左右子节点,直接用左子节点最大值取代删除节点
	int value = FindMax(root->lchild);
	root->data = value;
	root->lchild = DeleteNode(root->lchild,value,Deletenode);
	return root;

}
int FindMax(Bnode* root) {
    
     //用来找到最大的值
	while (root->rchild) {
    
    
		root = root->rchild;
	}
	return root->data;
}

前序遍历:


先输出父节点,再输出左子节点,再输出右子节点。

void PreNode(Bnode* root) {
    
    
	if (root == NULL)
		return;
	printf("- %d -\n",root->data);
	PreNode(root->lchild);
	PreNode(root->rchild);
}

全部代码:::

#include<iostream>
#include<Windows.h>
#define IsLess(a,b) (a<b)
#define IsEqual(a,b)(a==b)
using namespace std;
typedef int ElemType;
typedef struct Btree {
    
    
	ElemType data;
	struct Btree* lchild, *rchild;
}Bnode;
bool InsertBtree(Bnode** tree, Bnode* node);
Bnode* DeleteNode(Bnode *root,int key,Bnode*& Deletenode);
Bnode* query(Bnode* root, int key);
int FindMax(Bnode* root);
void PreNode(Bnode *root);
int main() {
    
    
	int arry[] = {
    
     19,7,25,5,11,15,21,26};
	Bnode* tree = NULL, * node = NULL;
	Bnode* del = NULL;
	for (int i = 0;i < 8;i++) {
    
    
		node = new Bnode;
		node->data = arry[i];
		InsertBtree(&tree, node);
	}
	Bnode* n = query(tree,21);
	printf("21查找%s\n", n ? "成功":"失败");
	tree = DeleteNode(tree,25, del);
	printf("25删除%s\n", del ? "成功" : "失败");
	delete del;
	printf("前序遍历结果:\n");
	PreNode(tree);

	system("pause");
	return 0;
}
bool InsertBtree(Bnode** tree, Bnode* node) {
    
    
	if (!node) {
    
    
		cout << "节点为空" << endl;
		return false;
	}
	else {
    
    
		node->lchild = NULL;
		node->rchild = NULL;
	}
	if (!(*tree)) {
    
    
		(*tree) = node;
		return true;
	}
	Bnode* parent = NULL;
	Bnode* tmp = *(tree);
	while (tmp) {
    
    
		parent = tmp;
		if (IsLess(node->data, tmp->data)) {
    
    
			tmp = tmp->lchild;
		}
		else {
    
    
			tmp = tmp->rchild;
		}
	}
	if (IsLess(node->data, parent->data)) {
    
    
		parent->lchild = node;
	}
	else {
    
    
		parent->rchild = node;
	}
	return true;
}
Bnode* DeleteNode(Bnode* root, int key,Bnode * &Deletenode) {
    
    
	if (root == NULL) return root;
 	if (root->data > key) {
    
    //比该节点大,去左边找
		root->lchild = DeleteNode(root->lchild, key,Deletenode);
		return root;
	}
	if (root->data < key) {
    
    //比该节点小,去右边找
		root->rchild = DeleteNode(root->rchild, key,Deletenode);
		return root;
	}
	Deletenode = root;
	//删除节点不存在左右子节点,即为叶子节点,直接删除
	if (root->lchild == NULL && root->rchild == NULL) return NULL;
	//删除节点只存在右子节点,直接用右子节点取代删除节点
	if (root->lchild == NULL && root->rchild != NULL) return root->rchild;
	//删除节点只存在左子节点,直接用左子节点取代删除节点
	if (root->lchild != NULL && root->rchild == NULL) return root->lchild;
	删除节点存在左右子节点,直接用左子节点最大值取代删除节点
	int value = FindMax(root->lchild);
	root->data = value;
	root->lchild = DeleteNode(root->lchild,value,Deletenode);
	return root;

}	
int FindMax(Bnode* root) {
    
    
	while (root->rchild) {
    
    
		root = root->rchild;
	}
	return root->data;
}
Bnode* query(Bnode* root, int key) {
    
    
	while (root != NULL && (root->data != key)) {
    
    
		if (root->data > key) {
    
    
			root = root->lchild;
		}
		else {
    
    
			root = root->rchild;
		}
	}
	return root;
}
void PreNode(Bnode* root) {
    
    
	if (root == NULL)
		return;
	printf("- %d -\n",root->data);
	PreNode(root->lchild);
	PreNode(root->rchild);
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_49324123/article/details/114693657
今日推荐