大家好,这里是国中之林!
❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看←
一.二叉树的结构
树的形式多种多样,但是我们最常用的还是二叉树.在二叉树中最长用的又数二叉搜索树.
这就是一个二叉搜索树,可以看到每个节点的左边都小于右边.
对于二叉树的实现,我们采用的链式结构
就是两个指针一个数据,跟双向链表差不多,但是两个节点之间不是双向连接.
左右指针都是指向的新的节点.
二.二叉树的插入
插入就要符合我们的规律,左边的的小于右边的.
1.根的插入
对要插入的节点,我们做防御性编程,同时对左右孩子设置为空.
当姚插入的是根节点是空,我们直接将新姚插入的节点设置为根节点.
如果不为空,先用变量进行保存,因为我们要进行遍历.
2.其他的插入
姚找到插入的位置就需姚遍历,找到要插入节点的父节点.
如果要插入的数据小于根节点的数据,就往左边遍历,否则右边遍历,直到tmp为空,那么parent就是要删除节点的父节点.
找到位置后然后进行插入:
如果要插入的数据小于父节点的数据,就插入在左边,否则右边.
三.二叉树的删除
对于删除稍稍有点复杂,有好几种情况如下.
1.找到删除节点
还是需要遍历到要删除节点:
如果当前节点不为空,同时当前节点的数据不是我们要删除的数据,那么我们一直遍历.
如果要删除节点的数据小于当前节点就往左边遍历,否则右边.
如果最后遍历为空,那么就是没有找到姚删除的节点.
2.删除节点的子节点只有一个或没有
当找到要删除的节点后,如果要删除节点的左边为空,就将姚删除节点的右边节点连接到要删除节点的位置,同理姚删除节点的右边为空的时候,就将要删除节点的左边连接到要删除的节点.
如果姚删除节点没有左右子节点了,那么连接的就是空.
如果父节点为空,那么就是要删除根节点,直接将刚刚子节点作为根节点.
要删除节点的父节点直接将原来的孩子改变成为原来孩子的孩子.
3.删除节点的子节点有两个
我们这里选择找右子树的最小值,先将要删除节点的右孩子找到,然后根据二叉搜索树的性质,我们需要一直找其左子节点,能够找到最小的值.
找到最小的值后,然后将其赋值给要删除的节点.
然后对刚刚找到的最小值位置进行删除,其父节点等于其要删除节点的孩子节点.
四.完整代码
#include <stdio.h>
#include <iostream>
#include <assert.h>
typedef int ElemType;
#define isLess(a,b)(a<b)
#define isEqual(a,b)(a==b)
typedef struct _Bnode
{
ElemType data;
struct _Bnode* lchild, * rchild;
}Bnode,Btree;
bool InsertBtree(Btree** root, Bnode* node)
{
Bnode* tmp = NULL;
Bnode* parent = NULL;
if (!node)
{
return false;
}
else
{
node->lchild = NULL;
node->rchild = NULL;
}
if (*root)
{
tmp = *root;
}
else
{
*root = node;
return true;
}
while (tmp!=NULL)
{
parent = tmp;
printf("父节点: %d\n", parent->data);
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;
}
int findMax(Btree* root)
{
assert(root != NULL);
/*if (root->rchild == NULL)
{
return root->data;
}
return findMax(root->rchild);*/
while (root->rchild)
{
root = root->rchild;
}
return root->data;
}
Btree* DeleteNode(Btree* root, int key)
{
if (root == NULL)return NULL;
if (root->data > key)
{
root->lchild = DeleteNode(root->lchild, key);
return root;
}
if (root->data < key)
{
root->rchild = DeleteNode(root->rchild, key);
return 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 val = findMax(root->lchild);
root->data = val;
root->lchild = DeleteNode(root->lchild, val);
return root;
}
Btree* DeleteNodeNonRecursive(Btree* root, int key) {
Btree* current = root;
Btree* parent = NULL;
while (current != NULL && current->data != key) {
parent = current;
if (key < current->data) {
current = current->lchild;
}
else {
current = current->rchild;
}
}
if (current == NULL) {
return root; // 未找到节点
}
// 处理叶子节点或只有一个子节点的情况
if (current->lchild == NULL || current->rchild == NULL) {
Btree* newCurrent;
if (current->lchild == NULL) {
newCurrent = current->rchild;
}
else {
newCurrent = current->lchild;
}
if (parent == NULL) {
root = newCurrent;
}
else if (parent->lchild == current) {
parent->lchild = newCurrent;
}
else {
parent->rchild = newCurrent;
}
}
else { // 有两个子节点的情况
Btree* successor = current->rchild;
Btree* successorParent = current;
while (successor->lchild != NULL) {
successorParent = successor;
successor = successor->lchild;
}
current->data = successor->data;
if (successorParent->lchild == successor) {
successorParent->lchild = successor->rchild;
}
else {
successorParent->rchild = successor->rchild;
}
}
return root;
}
int main()
{
int test[] = { 19,7,25,5,11,15,21,61 };
Bnode* root = NULL, * node = NULL;
for (int i = 0; i < sizeof(test) / sizeof(test[0]); i++)
{
node = new Bnode;
node->data = test[i];
InsertBtree(&root, node);
}
DeleteNode(root, 5);
system("pause");
return 0;
}
当然也可以用递归函数来实现.