动态查找表的特点是:表结构在查找过程中动态生成的,即对于给定值key,若表中存在等于key的记录,则查找成功,否则插入关键字key的记录。
1、二叉排序树
(1)、可以是空树
(2)、满足下列条件:若左子树不空,则所有的左子树值小于根节点值。
若右子树不空,则所有的右子树值大于根节点值。
他的左右子树也分别是二叉排序树。
如:这样的一个二叉排序树,A为空格先序遍历:45 12 3 A A 37 24 A A A 53 A 100 61 A 90 78 A A A
int search(bitree T,key k){ if(!T||k==T->data) return T; else if(k<T->data) return (search(T->lchild,k)); else return (search(T->rchild,k)); }二叉排序树是在查找中形成的,每次插入的值必为树的叶子节点。为了找到查找不成功时访问的最后一个节点,需改进到以下算法。
int search(bitree T,key k,bitree f,bitree &p){ //p记录位置 if(!T){ p=f;//f为T的双亲 return false; } else if(k==T->data){ p=T; return true; } else if(k<T->data){ return search(T->lchild,k,T,p); } else{ return search(T->rchild,k,T,p); } }插入算法:
int insert(bitree &T,int e){ if(!search(T,e,NULL,p)){ s=(bitree)malloc(sizeof(bitree)); s->data=e; s->lchild=NULL; s->rchild=NULL; if(!s)T=s; else if(e<p->data)p->lchild=s; else p->rchild=s; return true; } else return false; }进行删除操作时,有可能会破坏树,所以要修正树:
删除叶子时,不用调整。
删除的结点只有左子树时,直接将左子树向上移动。
删除的结点只有右子树时,直接将右子树当做删除结点的前驱的左子树。
删除的结点有左右子树时,需要找到该节点的左子树a的右子树b的最后一个右子树结点c,将c的值赋给删除结点的值,然后若找到删除结点的左子树有右子树的话,
需将该节点的右子树的前驱的右子树赋值为该节点的左子树。否则,直接将删除结点的左子树上移。
int delete(bitree &T){ if(!p->rchild){ q=p;p=p->lchild;free(q); } else if(!p->lchild){ q=p; p=p->rchild; free(q); } else{ q=p;s=p->lchild; while(s->rchild){ q=s; s=s->rchild; } p->data=s->data; if(p!=q){ q->rchild=s-lchild; } else{ q->lchild=s->lchild; } } }