值得一说的是删除操作,删除操作我们分为三种情况:
1.要删的节点有两个孩子:
找到左子树中的最大值或者右子树中的最小值所对应的节点,记为node,并把node的值赋给要删除的节点del,然后删除node
实际上真正删除的是node,del只是发生了一次值的替换。
为了方便理解和操作,我们把两个孩子的情况放在最前面,这样经过以上处理后,该节点就会变成情况2或者情况3 ,接下爱这行这两种情况的代码。
2.要删的节点有一个孩子
r判断要删除的节点del是其父亲father的左孩子还是右孩子,以是father的左孩子为例,del是father的左孩子,接下来判断del是否有左孩子,
如果有,则father的左孩子变成del的左孩子,如果没有,则father的左孩子变成del的右孩子。
3.要删的节点没有孩子
即为当情况2 del的左孩子右孩子为空的时候
#include<stdio.h> #include<stdlib.h> typedef struct Tree { int data; Tree*right; Tree*left; }BinaryTree; void insert(BinaryTree **p,int e) { BinaryTree *temp=(BinaryTree*)malloc(sizeof(BinaryTree)); temp->data=e; temp->left=NULL; temp->right=NULL; if(*p==NULL) { *p=temp; return ; } BinaryTree*root=*p; while(1) { if(e<root->data) { if(root->left) { root=root->left; } else { root->left=temp; break;//完成插入操作了 } } else if(e>root->data) { if(root->right) { root=root->right; } else { root->right=temp; break; } } } } void FindNode(BinaryTree* p,BinaryTree **del,BinaryTree**father, int e)//我们在删除操作中不仅需要知道要删除哪个节点,还要知道要删除节点的父亲 { //return无法返回两个值,要实现返回两个值,我们在这里采用二级指针 while(1) //实际上也可以通过结构体封装来完成同时返回两个值 { if(e<p->data) { *father=p;//每次都记录一下父亲 p=p->left; } else if(e>p->data) { *father=p; p=p->right; } else if(e==p->data) { *del=p;return ; } } } void deleteNode(BinaryTree **p,int e)// { if(*p==NULL) return ; BinaryTree *root=*p; BinaryTree *del=NULL; BinaryTree *father=NULL; BinaryTree *pmark=NULL; FindNode(root,&del,&father,e); if(del->left&&del->right) { pmark=del;//标记要删除的点 father=del; del=del->left; while(del->right) { father=del; del=del->right; } pmark->data=del->data; } //接下来分析有一个或者没有孩子的情况 //被删节点 是根 if(father==NULL)//?? { *p=del->left?del->left:del->right; free(del); return ; } else {//不用在写判断条件了,走到这说明就是一个或者没有孩子,只需要判断是哪边的孩子就可 if(del==father->left) father->left=del->left?del->left:del->right; else if(del==father->right) father->right=del->left?del->left:del->right; free(del); } } void inorder(BinaryTree *p) { if(p==NULL) return ; //递归要有结束条件 inorder(p->left); printf(" %d ",p->data); inorder(p->right); } void preorder(BinaryTree *p) { if(p==NULL) return ; //递归要有结束条件 printf(" %d ",p->data); preorder(p->left); preorder(p->right); } int main() { int m; BinaryTree *p=NULL; int a[10]; int i; scanf("%d",&m); for(i=0;i<m;i++) { scanf("%d",&a[i]); } for(i=0;i<m;i++) { insert(&p,a[i]); } preorder(p); printf("\n"); inorder(p); deleteNode(&p,9); preorder(p); printf("\n"); inorder(p); return 0; }