数据结构之二叉查找树的建立遍历删除

来源:互联网 发布:淘宝电商是什么 编辑:程序博客网 时间:2024/05/24 05:02

二叉查找树建立,遍历,查找元素很容易实现。我主要写写删除过程。

二叉查找树结点的删除分几种情况:

如果结点是一片树叶,那么直接删除即可。如果结点有一个儿子,则该节点可以在其父节点调整指针绕过该节点后被删除。如果结点有两个儿子,一般的删除方法是用其右子树的最小的数据代替该节点,并删除那个结点。因为最小的那个结点不可能有左儿子,所以第二次删除很容易实现。

代码如下,写的不太好,见笑了敲打

#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);elsereturn root;}// 在二叉查找树树中找到最小的结点的值(递归)Tree FindMin(Tree root){if (root == NULL)return NULL;if (root->lchild == NULL)return root;elsereturn 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;}elsereturn 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;elseParent->rchild = Dest->rchild;}// 左子树不为空右子树为空else if (Dest->lchild != NULL && Dest->rchild == NULL){if (1 == Pos)Parent->lchild = Dest->lchild;elseParent->rchild = Dest->lchild;}// 左右子树均为空else{if (1 == Pos)Parent->lchild = NULL;elseParent->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);elsetemp=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;}// 当待删除结点只有一个子树时elseDelete_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;}

0 0
原创粉丝点击