C语言之平衡二叉树详解

  //查找节点

  //找最大节点

  Node *maxNode(Node *curRoot)

  {

  if (curRoot == NULL)

  return NULL;

  //往右边找

  while (curRoot->RChild)

  curRoot = curRoot->RChild;

  return curRoot;

  }

  //找最小节点

  Node *minNode(Node *curRoot)

  {

  if (curRoot == NULL)

  return NULL;

  while (curRoot->LChild)

  curRoot = curRoot->LChild;

  return curRoot;

  }

  //删除数据

  Node *deleteNode(Node *curRoot, Ty data)

  {

  //删除数据有四个大情况

  if (curRoot == NULL) //当前节点是空的

  return NULL; //删除了个寂寞直接结束掉整个函数

  if (data < curRoot->data) //要删除的数据比当前节点的数据小

  {

  //往左边跑

  curRoot->LChild = deleteNode(curRoot->LChild, data);

  //获取新高度

  curRoot->height = GET_NEW_HEIGHT(curRoot);

  //判断需不需要调整

  if (HEIGHT(curRoot->RChild) - HEIGHT(curRoot->LChild) == 2)

  curRoot = HEIGHT(curRoot->RChild->LChild) > HEIGHT(curRoot->RChild->RChild) ? RL_Rotation(curRoot) : RR_Rotation(curRoot);

  }

  else if (data > curRoot->data) //要删除的数据比当前节点的数据大

  {

  //往右边跑

  curRoot->RChild = deleteNode(curRoot->RChild, data);

  curRoot->height = GET_NEW_HEIGHT(curRoot);

  if (HEIGHT(curRoot->LChild) - HEIGHT(curRoot->RChild) == 2)

  curRoot = HEIGHT(curRoot->LChild->RChild) > HEIGHT(curRoot->LChild->LChild) ? LR_Rotation(curRoot) : LL_Rotation(curRoot);

  }

  else

  { //要删除的数据和当前节点的数据一样大

  //针对于curRoot这个节点做删除操作

  //主要有两个主要的情况

  if (curRoot->LChild && curRoot->RChild) // curRoot有左子树和右子树

  {

  //先判断左右子树的高度,将高度比较高的子树的节点拿到上面来

  if (HEIGHT(curRoot->LChild) > HEIGHT(curRoot->RChild))

  { //左子树的高度比右子树的高度高

  //找到左子树的最大节点

  Node *max = maxNode(curRoot->LChild);

  //找到之后就将max的数据替换curRoot的数据

  curRoot->data = max->data;

  //赋值完成之后继续递归,然后释放掉max对应的节点,不能直接在这里释放,因为要调整树的高度

  curRoot->LChild = deleteNode(curRoot->LChild, max->data);

  }

  else

  { //左子树的高度小于等于右子树的高度

  //找到右子树的最小节点

  Node *min = minNode(curRoot->RChild);

  curRoot->data = min->data;

  curRoot->RChild = deleteNode(curRoot->RChild, min->data);

  }

  }

  else //上一种情况的否定,即curRoot没有子树或者只有一边

  {

  //释放内存

  Node *temp = curRoot;

  // curRoot拿到存在的子树

  curRoot = curRoot->LChild ? curRoot->LChild : curRoot->RChild;

  free(temp);

  }

  }

  return curRoot; //删除完成之后就返回当前节点

  }