[C语言实现]实现二叉查找树基本操作(迭代版)

实现二叉查找树基本操作
在这篇博客我们已经记录了二叉查找树插入查找删除的思路,使用递归很容易实现,因为树的定义都是递归实现的,所以相对于递归,使用迭代完成上述操作就比较复杂了.

插入的实现

需要手动记录该节点的父节点,因为要将父节点的子树指向新节点
插入的节点是该父节点的左子树还是右子树,通过比较大小就可以确定

void SearchTreeInsert_ByLooP(SearchTreeNode* root, SearchTreeType key)
{
  SearchTreeNode* pre_node = root;
  SearchTreeNode* node = root;
  for(node = root; node != NULL;  )
  {
    if(node->key > key)
    {
      pre_node = node;
      node = node->rchild;
    }
   else  if(node->key < key)
    {
      pre_node = node;
      node = node->lchild;
    }
   else if(node->key == key)
   {
     break;
   }
  }
  //为空 插入新元素
  if(node == NULL)
  {
    node  = (SearchTreeNode*)malloc(sizeof(SearchTreeNode));
    node->key = key;
    node->lchild = NULL;
    node->rchild = NULL;
      //父节点的左边或者右边插入节点
    if(pre_node->key < node->key)
    {
      pre_node->rchild = node;
    }
    else 
    {
      pre_node->lchild = node;
    }
  }
}

查找

查找就没什么了,和递归一样,比较大小,结束循环时node = NULL 就表示查找未命中

删除

递归版本的删除就很复杂了,对于迭代,就更难了.
不过思路还是记录两个节点,pre_node (父节点) node(当前节点),
需要根据大小比较 node是pre_node 的左子树还是右子树
然后分四类情况讨论,和递归一样
这里是删除四种情况的图示

void _SearchTreeRemove_ByLoop(SearchTreeNode** proot,SearchTreeType key)
{
  if( proot == NULL  )
    return;
  if( *proot == NULL )
    return;
  SearchTreeNode* root = *proot;
  SearchTreeNode* pre_root = NULL;
    //查找需要删除的节点
  while(root)
  {
    if(root->key > key)
    {
      pre_root = root;
      root = root->lchild;
    }
    else if(root->key < key)
    {
      pre_root = root;
      root = root->rchild;
    }
    else if(root->key == key)
    {
      break;
    }
  }
    //没找到 需要删除的节点
  if(root == NULL)
  {
    return;
  }
  // 如果删除的节点是根节点
  if(root == *proot)
  {
    free(*proot);
    *proot = NULL;
    return;
  }
  //删除节点 左右子树都为空 的情况
  if(root->lchild == NULL && root->rchild == NULL)
  {
    // 判断 当前节点 是 其父节点的左节点还是右节点
    if(pre_root->key > root->key)
    {
      pre_root->lchild = NULL;
    }
    else 
    {
      pre_root->rchild = NULL;
    }
    free(root);
    root = NULL;
  }
    //当前节点右空 左不空的情况
  else if(root->lchild != NULL && root->rchild == NULL)
  {
      // 判断 当前节点 是 其父节点的左节点还是右节点
    if(pre_root->key > root->key)
    {
      pre_root->lchild = root->lchild;
    }
    else 
    {
      pre_root->rchild = root->lchild;
    }
    free(root);
    root = NULL;
  }
    //上一个的镜像
  else if(root->rchild != NULL && root->lchild == NULL)
  {
    if(pre_root->key > root->key)
    {
      pre_root->lchild = root->rchild;
    }
    else 
    {
      pre_root->rchild = root->rchild;
    }
    free(root);
    root = NULL;
  }
  else if(root->rchild != NULL && root->lchild != NULL)
  {
    //在左子树中找最大的吧, 使用赋值法删除节点
    SearchTreeNode* max = root->lchild;
    SearchTreeNode* pre_max = NULL;
    while(max->rchild)
    {
      pre_max = max;
      max = max->rchild;
    }
    root->key = max->key;
    //左子树是根节点
    if(pre_max == NULL)
    {
     free(root->lchild);
     root->lchild = NULL;
    }
    else 
    {
      //左子树中最大的 ,不用比值
      free(pre_max->rchild);
      pre_max->rchild = NULL;
    }
  }
}
    原文作者:二叉查找树
    原文地址: https://blog.csdn.net/kwinway/article/details/80380990
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞