二叉查找树建立,遍历,查找元素很容易实现。我主要写写删除过程。
二叉查找树结点的删除分几种情况:
如果结点是一片树叶,那么直接删除即可。如果结点有一个儿子,则该节点可以在其父节点调整指针绕过该节点后被删除。如果结点有两个儿子,一般的删除方法是用其右子树的最小的数据代替该节点,并删除那个结点。因为最小的那个结点不可能有左儿子,所以第二次删除很容易实现。
代码如下,写的不太好,见笑了
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef int DataType;
typedef struct node
{
DataType data;
struct node *lchild, *rchild;
}BinTree, *Tree;
// 添加结点
Tree Add_New_Node(DataType data)
{
Tree NewNode = (Tree)malloc(sizeof(BinTree));
memset(NewNode, 0, sizeof(BinTree));
NewNode->data = data;
return NewNode;
}
// 二叉查找树的插入操作
Tree Insert(Tree root, DataType num)
{
if (root == NULL)
{
root = Add_New_Node(num);
}
else if (num > root->data)
{
root->rchild = Insert(root->rchild, num);
}
else if (num < root->data)
{
root->lchild = Insert(root->lchild, num);
}
return root;
}
// 根据关键字找到该结点并返回该节点的地址
Tree Find(Tree root, DataType key)
{
if (root == NULL)
return NULL;
if (key < root->data)
return Find(root->lchild, key);
else if (key > root->data)
return Find(root->rchild, key);
else
return root;
}
// 在二叉查找树树中找到最小的结点的值(递归)
Tree FindMin(Tree root)
{
if (root == NULL)
return NULL;
if (root->lchild == NULL)
return root;
else
return FindMin(root->lchild);
}
// 在二叉查找树树中找到最大的结点的值(迭代)
Tree FindMax(Tree root)
{
if (root != NULL)
{
while (root->rchild != NULL)
root = root->rchild;
}
return root;
}
// 找到关键字的父节点并返回它本身的地址和父节点的地址,以及其左右子树对应关系
Tree FindNodeAndPos(Tree root, DataType key, Tree *flag,int *sign)
{
Tree p = root;
if (p == NULL)
return NULL;
while (p != NULL)
{
if (key < p->data)
{
*sign = 1;
*flag = p;
p = p->lchild;
}
else if (key > p->data)
{
*sign = 0;
*flag = p;
p = p->rchild;
}
else
return p;
}
return NULL;
}
// 删除的结点有1个或两个结点
void Delete_A_Node_With_One_Child(Tree Parent,Tree Dest,int Pos)
{
if (Parent == NULL || Dest == NULL)
return;
// 左子树为空右子树不为空
if (Dest->lchild == NULL && Dest->rchild != NULL)
{
if (1 == Pos)
Parent->lchild = Dest->rchild;
else
Parent->rchild = Dest->rchild;
}
// 左子树不为空右子树为空
else if (Dest->lchild != NULL && Dest->rchild == NULL)
{
if (1 == Pos)
Parent->lchild = Dest->lchild;
else
Parent->rchild = Dest->lchild;
}
// 左右子树均为空
else
{
if (1 == Pos)
Parent->lchild = NULL;
else
Parent->rchild = NULL;
}
free(Dest);
}
// 删除函数
void Delete_Node_With_Pos(Tree root, DataType key)
{
// Parent保存待删除结点的父节点的指针 Dest保存待删除节点的指针
Tree Parent = NULL, Dest = NULL;
// Pos标记待删除结点与它的父节点的左右关系,定义 '1'为左 '0'为右
int Pos = 0;
// 当待删除的结点为根节点时
if (root->data == key)
{
// Cur保存当前结点的地址 temp保存当前结点右子树中最小的结点的地址
Tree Cur = Dest, temp = FindMin(root->rchild);
// 右子树删完了再删左子树
if (root->rchild!=NULL)
temp = FindMin(root->rchild);
else
temp=FindMin(root->lchild);
int nData = temp->data;
Dest = FindNodeAndPos(root, nData, &Parent, &Pos);
Delete_A_Node_With_One_Child(Parent, Dest, Pos);
root->data = nData;
}
else
{
Parent = NULL, Dest = NULL;
Pos = 0;
Dest = FindNodeAndPos(root, key, &Parent, &Pos);
if (Dest == NULL)
{
printf("没有该结点,删除失败!\n");
return;
}
// 当待删除结点没有左右子树时
if (Dest->lchild == NULL && Dest->rchild == NULL)
Delete_A_Node_With_One_Child(Parent, Dest, Pos);
// 当待删除结点左右子树均存在时
else if (Dest->lchild!=NULL && Dest->rchild!=NULL)
{
Tree Cur = Dest, temp = FindMin(Dest->rchild);
int nData = temp->data;
Parent = NULL, Dest = NULL;
Pos = 0;
Dest = FindNodeAndPos(root, nData, &Parent, &Pos);
Delete_A_Node_With_One_Child(Parent, Dest, Pos);
Cur->data = nData;
}
// 当待删除结点只有一个子树时
else
Delete_A_Node_With_One_Child(Parent, Dest, Pos);
}
}
// 清空整个树
Tree MakeEmpty(Tree root)
{
if (root != NULL)
{
MakeEmpty(root->lchild);
MakeEmpty(root->rchild);
free(root);
}
return NULL;
}
// 前序遍历
void PreOrder(Tree root)
{
if (root != NULL)
{
printf("%d ", root->data);
PreOrder(root->lchild);
PreOrder(root->rchild);
}
}
// 中序遍历
void InOrder(Tree root)
{
if (root != NULL)
{
InOrder(root->lchild);
printf("%d ", root->data);
InOrder(root->rchild);
}
}
// 后序遍历
void PostOrder(Tree root)
{
if (root != NULL)
{
PostOrder(root->lchild);
PostOrder(root->rchild);
printf("%d ", root->data);
}
}
// 以三种遍历方式打印出所有结点
void Print(Tree root)
{
printf("前序遍历: ");
PreOrder(root);
printf("\n");
printf("中序遍历: ");
InOrder(root);
printf("\n");
printf("后序遍历: ");
PostOrder(root);
printf("\n");
}
int main()
{
Tree root = NULL;
for (int i = 0; i < 10; i++)
{
root = Insert(root, rand() % 100);
}
root = Insert(root, 45);
Print(root);
printf("\n删除一个结点后\n\n");
Delete_Node_With_Pos(root, 58);
Print(root);
printf("\n");
root = MakeEmpty(root);
system("pause");
return 0;
}