二叉树特点:
最多只有两个节点,左边的分支称之为左节点,右边的分支称之为右节点。
(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);
}