动态查找:集合是动态变化的 ,除查找,还可能发生插入和删除
以二叉搜索树为例:
//结构如下:
typedef struct binary_tree* tree;
struct binary_tree{
elementtype data;
tree left;
tree right;
};
二叉搜索树定义:一棵二叉树,可以为空;如果不为空,满足以下性质:
- 非空左子树的所有键值小于其根结点的键值。
- 非空右子树的所有键值大于其根结点的键值。
- 左、右子树都是二叉搜索树。
- 查找:(返回x节点,失败返回NULL)
------------------查找元素X的位置----------------
//尾递归:
tree find(elementtype x,tree bt)
{
if( !bt ) return NULL; /*查找失败*/
if( x > bt->data )
return find(x,bt->right); /*在右子树中继续查找*/
else if( x < bt->data )
return find(x,bt->left); /*在左子树中继续查找*/
else
return bt; /*查找成功,返回结点的地址*/
}
//由于非递归函数的执行效率高,下面将尾递归改为迭代:
tree find(elementtype x,tree bt){
while(bt){
if (x>bt->data) bt=bt->right; /*向右子树中移动,继续查找*/
else if (x<bt->data) bt=bt->left; /*向左子树中移动,继续查找*/
else return bt; /*查找成功,返回找到结点的地址*/
}
return NULL; /*查找失败*/
}
------------------查找最小元素的位置----------------
tree find_min(tree bt){
if (bt)
while (bt->left) bt=bt->left;
return bt;
}
------------------查找最大元素的位置----------------
tree find_max(tree bt){
if (bt)
while (bt->right) bt=bt->right; //沿右分支继续查找,直到最右叶结点
return bt;
}
- 插入:(返回结果树根节点)
tree insert(elementtype x,tree bt){
if (!bt){ /*若原树为空,生成并返回一个结点的二叉搜索树*/
bt=(tree)malloc(sizeof(struct binary_tree));
bt->data=x;
bt->left=bt->right=NULL;
return bt;
}
else{ /*开始找要插入元素的位置*/
tree top=bt;
int flag=0; //判断在left插入还是right插入
tree temp=NULL; //记录父节点
while (bt){
temp=bt;
if (x>bt->data){ //右子树寻找插入位置
bt=bt->right;
flag=1;
}
else if (x<bt->data){ //左子树寻找插入位置
bt=bt->left;
flag=0;
}
else return true; //x已存在,直接返回插入成功
}
if (flag){ //flag==1,在temp的right下新建节点
temp->right=(tree)malloc(sizeof(struct binary_tree));
temp->right->data=x;
temp->rigth->left=temp->right->right=NULL;
}
else{ //flag==0,在temp的left下新建节点
temp->left=(tree)malloc(sizeof(struct binary_tree));
temp->left->data=x;
temp->left->left=temp->left->right=NULL;
}
return top;
}
}
- 删除:(返回结果树根节点)
//递归:
tree delete(elementtype x,tree bt){
if (!bt) reeturn NULL; //空树
else if (x<bt->data) bt->left=delete(x,bt->left);//左子树递归删除
else if (x>bt->data) bt->right=delete(x,bt->right);//右子树递归删除
else{ //找到要删除的结点
tree temp=NULL;
if (bt->left && bt->right){ //待删除节点有左,右子树
//在右子树中找最小的元素填充删除结点
temp=find_min(bt->right);
bt->data=temp->data;
bt->right=delete(bt->data,bt->right);
}
else{ //待删除节点仅有左子树,或仅有右子树,或无子节点
temp=bt;
if (bt->left) //有左节点
bt=bt->left;
else //有右节点,或无子节点
bt=bt->right;
free(temp);
}
}
return bt;
}
//非递归:(稍微复杂一些)
tree delete(elementtype x,tree bt){
if (!bt) reeturn NULL; //空树
tree top=bt; //记录根节点
tree parent=bt; //记录父节点
while(bt){ //寻找x位置
if (x>bt->data){
parent=bt;
bt=bt->right;
}
else if (x<bt->data){
parent=bt;
bt=bt->left;
}
else break; //找到,退出循环
}
if (!bt) return top; //未找到
if (bt->left && bt->right){ //待删除节点有左,右子树
tree temp=bt->right; //在右子树中找最小的元素填充删除结点
while(temp->left){
parent=temp;
temp=temp->left;
}
bt->data=temp->data;
if (temp==parent->right)//说明待删除节点的右子树为斜右二叉树(包括一个节点情况)
parent->right=temp->right;
else
parent->left=temp->right;//待删除节点的右子节点有左子树
free(temp);
return top;
}
else{ //待删除节点仅有左子树,或仅有右子树,或无子节点
tree temp=bt;
if (parent==bt){ //删除根节点(包括最后一个节点情况)
if (bt->left) bt=bt->left;
else bt=bt->right;
free(temp);
return bt;
}
else{ //根节点不变
if (bt==parent->left){
if (bt->left) parent->left=bt->left;
else parent-left=bt->right;
}
else{
if (bt->left) parent->right=bt->left;
else parent->right=bt->right;
}
free(temp);
return top;
}
}
}