核心思想: 首先要明确,插入的一定是叶子结点(不相等的时候一直往下递归,为空的之后才跳出)。因此,需要标记要插入的位置(p),所以在遍历的时候需要一个指针进行跟踪(f),通过f把位置传给p。
bool Search_Insert(BiTree &T,int key,BiTree f,BiTree &p){ if(!T){ p=f; return false; } else if(T->date==key){ p=f; cout<<"查找成功"<<endl; return true; } else if(T->date>key) return Search_Insert(T->lchild,key,T,p); else return Search_Insert(T->rchild,key,T,p); } bool Insert(BiTree &T,int key){ if(!Search_Insert(T,key,f,p)){ Node *s=new Node; s->date=key;//插入的结点一定是叶子结点 s->lchild=NULL; s->rchild=NULL; if(!p) //树为空 T=s; else if(key<p->date) p->lchild=s; else p->rchild=s; return true; } return false; } 动态查找: 找到时,进行删除。核心思想: 若删除的叶子结点,直接删除; 若删除的结点只有左孩子或者右孩子,直接它的左孩子或者右孩子代替该节点。 若删除结点左,右子树都不为空,则进行查找它的前驱,即它的左子树的右子树最右的一个结点。以这个结点替代删除的结点。 1>如果它的左子树的右子树为空时,直接用它的左孩子(s)替代删除的结点,然后将左孩子的接在该结点。 2>左孩子的右子树不为空的时候,用右子树的最后一个结点(s)代替删除结点,然后将该结点的后续接在该结点根节点(q)的右孩子。
bool Search_Delete(BiTree &T,int key){ if(!T){ cout<<"查找失败"<<endl; return false; } else{ if(T->date==key) return Delete(T); else if(T->date<key) return Search_Delete(T->rchild,key); else return Search_Delete(T->lchild,key); } } bool Delete(BiTree &p){ Node *q; if(!p->lchild){//删除结点只有右子树 q=p; p=p->rchild; delete(q); } else if(!p->rchild){//删除结点只有左子树 q=p; p=p->lchild; delete(q); } else{//左右子树均不为空 q=p;//s代表前驱,q是删除结点 Node *s=p->lchild;//找删除结点的前驱(左孩子的最后一个右孩子) while(!s->rchild){ q=p; s=s->rchild; } p->date=s->date; if(p==q)//左孩子没有右孩子的时候 q->lchild=s->lchild; else q->rchild=s->lchild;//此时,s没有右孩子 } return true; }