铜仁市论坛

首页 » 分类 » 定义 » 数据结构的实践心得二叉查找树AVL绝对
TUhjnbcbe - 2021/3/10 0:28:00
中科治白癜风疗效更显著 http://pf.39.net/xwdt/190625/7245241.html
工作久了,人总会有种忘记初心的感觉。相信每个人小时候都想过成为一名科学家,只不过到后来,连自己都忘了。当一名科学家确实不容易,学术研究难,薪酬待遇还不高,如果不是真的热爱,很难走下去。但在腾讯,你可以把学术当成工作,工作就是做学术,而且两者都可以做得很好。是的,你没有听错。今天,腾讯云两项数据库内核技术的研究成果再次入选SIGMOD和ICDE的收录论文。其中,SIGMOD、ICDE、VLDB并称为国际数据库三大顶级会议。另外,据说在学术圈,一篇SIGMOD或者ICDE就能当副教授了?这么看的话,那我们这至少有两个副教授了其实腾讯云数据库也是各大顶会的常客了,之前我们「AI调参的技术优化数据库」的研究成果被SIGMOD收录,同时,还在MySQL社区上提交各种patch,总量位列前茅,年,我们荣幸举办MySQL之父本年第一次中国区见面会,得到了MySQL之父的赞许,年末还收到了MariaDB社区的官方感谢信(现在都还在
TUhjnbcbe - 2021/3/10 0:28:00

头文件(searchTree.h):

#pragmaonce

#include"binaryTree.h"

//通过Key值查找节点

binaryNode*findNodeByKey(binaryNode*T,intkey);

//取得节点平衡因子

intgetBalanceFactor(binaryNode*T);

//平衡左旋转

binaryNode*leftRotate(binaryNode*T);

//平衡右旋转

binaryNode*rightRotate(binaryNode*T);

//插入节点(平衡二叉查找树),返回新增节点

binaryNode*insertSearchTree(binaryNode*T,intkey,binaryElemType*data);

//删除节点(平衡二叉查找树),返回删除调整后的替换节点

binaryNode*deleteSearchTree(binaryNode*T,intkey);

程序文件(searchTree.c):

#includestdlib.h

#include"searchTree.h"

//通过Key值查找节点

binaryNode*findNodeByKey(binaryNode*T,intkey)

{

  if(!T)returnNULL;

  binaryNode*p=T;

  //遍历查找

  while(p)

  {

    if(p-key==key)

    {

      returnp;

    }

    elseif(p-keykey)

    {

      p=p-left;

    }

    else

    {

      p=p-right;

    }

  }

  returnNULL;

}

//取得节点平衡因子

intgetBalanceFactor(binaryNode*T)

{

  if(!T)return0;

  

  intleftHeight=0,rightHeight=0;

  //取得左子树的高度

  binaryNode*p=T-left;

  if(p)leftHeight=heightBinaryList(p);

  //取得右子树的高度

  p=T-right;

  if(p)rightHeight=heightBinaryList(p);

  //计算平衡因子

  return(leftHeight-rightHeight);

}

//平衡左旋转

binaryNode*leftRotate(binaryNode*T)

{

  if((!T)

(!T-right))returnNULL;

  //定义待调整的临时节点

  binaryNode*bn=T,*parent=bn-parent,*right,*rightChildLeft;

  //取得原先的节点位置

  intisRight=bn-isRight;

  //移除原先的父级节点关系

  if(parent)removeBinaryNode(parent,bn);

  right=bn-right;

  //移除原先的右子树关系

  removeBinaryNode(bn,right);

  //取得原先右子树的左节点

  rightChildLeft=right-left;

  if(rightChildLeft)

  {

    //移除原先右子树的左节点关系

    removeBinaryNode(right,rightChildLeft);

    //判断原先右子树的右节点是否存在

    if(right-right)

    {

      //建立和原先右子树的左节点之间的关系(右子节点)

      addBinaryNode(bn,1,rightChildLeft);

      //重新添加为原先右子树的左子节点

      addBinaryNode(right,0,bn);

      //建立原先父级节点和原先右子树之间的关系

      if(parent)addBinaryNode(parent,isRight,right);

      returnright;

    }

    else

    {

      //重新建立原先右子树的左节点和原先右子树的关系(右子节点)

      addBinaryNode(rightChildLeft,1,right);

      //重新添加为原先右子树的左节点的左子节点

      addBinaryNode(rightChildLeft,0,bn);

      //建立原先父级节点和原先右子树的左节点之间的关系

      if(parent)addBinaryNode(parent,isRight,rightChildLeft);

      returnrightChildLeft;

    }

  }

  else

  {

    //重新添加为原先右子树的左子节点

    addBinaryNode(right,0,bn);

    //建立原先父级节点和原先左子树之间的关系

    if(parent)addBinaryNode(parent,isRight,right);

    returnright;

  }

}

//平衡右旋转

binaryNode*rightRotate(binaryNode*T)

{

  if((!T)

(!T-left))returnNULL;

  //定义待调整的临时节点

  binaryNode*bn=T,*parent=bn-parent,*left,*leftChildRight;

  //取得原先的节点位置

  intisRight=bn-isRight;

  //移除原先的父级节点关系

  if(parent)removeBinaryNode(parent,bn);

  left=bn-left;

  //移除原先的左子树关系

  removeBinaryNode(bn,left);

  //取得原先左子树的右节点

  leftChildRight=left-right;

  if(leftChildRight)

  {

    //移除原先左子树的右节点关系

    removeBinaryNode(left,leftChildRight);

    //判断原先左子树的左节点是否存在

    if(left-left)

    {

      //建立和原先左子树的右节点之间的关系(左子节点)

      addBinaryNode(bn,0,leftChildRight);

      //重新添加为原先左子树的右子节点

      addBinaryNode(left,1,bn);

      //建立原先父级节点和原先左子树之间的关系

      if(parent)addBinaryNode(parent,isRight,left);

      returnleft;

    }

    else

    {

      //重新建立原先左子树的右节点和原先左子树的关系(左子节点)

      addBinaryNode(leftChildRight,0,left);

      //重新添加为原先左子树的右节点的右子节点

      addBinaryNode(leftChildRight,1,bn);

      //建立原先父级节点和原先左子树的右节点之间的关系

      if(parent)addBinaryNode(parent,isRight,leftChildRight);

      returnleftChildRight;

    }

  }

  else

  {

    //重新添加为原先左子树的右子节点

    addBinaryNode(left,1,bn);

    //建立原先父级节点和原先左子树之间的关系

    if(parent)addBinaryNode(parent,isRight,left);

    returnleft;

  }

}

//插入节点(平衡二叉查找树),返回新增节点

binaryNode*insertSearchTree(binaryNode*T,intkey,binaryElemType*data)

{

  if(!T)returnNULL;

  //取得二叉树节点的根节点(必须从根节点开始,才能保证平衡)

  binaryNode*bn=getBinaryRoot(T),*parent=NULL;

  intisRight=0;

  //遍历查找

  while(bn)

  {

    parent=bn;

    //查找插入位置

    if(bn-key==key)

    {

      //更新二叉树节点的数据内容

      setBinaryNodeData(bn,data);

      returnbn;

    }

    elseif(bn-keykey)

    {

      bn=bn-left;

      isRight=0;

    }

    else

    {

      bn=bn-right;

      isRight=1;

    }

  }

  //插入二叉树的子节点(右:1;左:0)

  binaryNode*child=insertBinaryNode(parent,isRight,key);

  //设置二叉树节点的数据内容

  setBinaryNodeData(child,data);

  //定位父级节点

  bn=parent;

  intfactor;

  //遍历平衡因子

  while(bn)

  {

    //取得节点平衡因子

    factor=getBalanceFactor(bn);

    //父级节点平衡因子变为0,则表示高度不变,结束向上传导

    if(factor==0)break;

    //父级节点平衡因子变为1或-1,则继续向上传导

    if((factor==1)

(factor==-1))

    {

      bn=bn-parent;

    }

    elseif(factor1)

    {

      //取得左子节点平衡因子

      factor=getBalanceFactor(bn-left);

      //右旋转之前,如果左子节点平衡因子小于0,则需要先对左子树进行左旋转

      if(factor0)leftRotate(bn-left);

      //平衡右旋转

      rightRotate(bn);

      //完成调整,则结束向上传导

      break;

    }

    elseif(factor-1)

    {

      //取得右子节点平衡因子

      factor=getBalanceFactor(bn-right);

      //左旋转之前,如果右子节点平衡因子大于0,则需要先对右子树进行右旋转

      if(factor0)rightRotate(bn-right);

      //平衡左旋转

      leftRotate(bn);

      //完成调整,则结束向上传导

      break;

    }

  }

  returnchild;

}

//删除节点(平衡二叉查找树),返回删除调整后的父级替换节点

binaryNode*deleteSearchTree(binaryNode*T,intkey)

{

  if(!T)returnT;

  //取得二叉树节点的根节点(必须从根节点开始,才能保证平衡)

  binaryNode*bn=getBinaryRoot(T);

  //遍历查找

  while(bn)

  {

    //查找删除位置

    if(bn-key==key)break;

    if(bn-keykey)

    {

      bn=bn-left;

    }

    else

    {

      bn=bn-right;

    }

  }

  //没有找到待删除Key值,则退出

  if(!bn)returnT;

  //取得节点平衡因子、是否为右节点标记

  intfactor=getBalanceFactor(bn),isRight=bn-isRight;

  //取得父级节点

  binaryNode*parent=bn-parent;

  //移除原先的父级节点关系

  if(parent)removeBinaryNode(parent,bn);

  //取得节点的左子树和右子树

  binaryNode*left=bn-left,*right=bn-right;

  //定义替换节点

  binaryNode*replaceNode,*replaceParent,*replaceChild;

  //判断待删除节点的平衡因子

  if(factor==0)

  {

    //取得右子树最小节点

    replaceNode=getMinBinaryNode(right);

  }

  elseif(factor0)

  {

    //取得左子树最大节点

    replaceNode=getMaxBinaryNode(left);

  }

  else

  {

    //取得右子树最小节点

    replaceNode=getMinBinaryNode(right);

  }

  //移除原先的左子树关系

  removeBinaryNode(bn,left);

  //移除原先的右子树关系

  removeBinaryNode(bn,right);

  binaryNode*result;

  //进行删除节点替换

  if(replaceNode)

  {

    intreplaceIsRight=replaceNode-isRight;

    //取得替换节点的父级节点

    replaceParent=replaceNode-parent;

    //取得替换节点的子级节点

    if(replaceIsRight0)

    {

      replaceChild=replaceNode-left;

    }

    else

    {

      replaceChild=replaceNode-right;

    }

    //移除替换节点的父级关系

    removeBinaryNode(replaceParent,replaceNode);

    //移除替换节点的子级关系

    removeBinaryNode(replaceNode,replaceChild);

    //重新建立替换节点原先的父子级关系

    addBinaryNode(replaceParent,replaceIsRight,replaceChild);

    //建立替换节点和原先的左子树和右子树的关系

    addBinaryNode(replaceNode,0,left);

    addBinaryNode(replaceNode,1,right);

    //建立原先父级节点和旋转后的父级节点的关系

    if(parent)addBinaryNode(parent,isRight,replaceNode);

    //替换节点之前的父级节点

    result=replaceParent;

  }

  else

  {

    //无需替换,重新连接后直接删除

    if(left)

    {

      //重新建立原先父级节点和左子树的关系

      if(parent)addBinaryNode(parent,isRight,left);

    }

    elseif(right)

    {

      //重新建立原先父级节点和右子树的关系

      if(parent)addBinaryNode(parent,isRight,right);

    }

    //父级节点

    result=parent;

  }

  //释放二叉树节点

  clearBinaryList(bn);

  bn=result;

  //遍历平衡因子

  while(bn)

  {

    //取得节点平衡因子

    factor=getBalanceFactor(bn);

    //父级节点平衡因子变为1或-1,则表示高度不变,结束向上传导

    if((factor==1)

(factor==-1))break;

    if(factor1)

    {

      //取得左子节点平衡因子

      factor=getBalanceFactor(bn-left);

      //右旋转之前,如果左子节点平衡因子小于0,则需要先对左子树进行左旋转

      if(factor0)leftRotate(bn-left);

      //平衡右旋转

      rightRotate(bn);

    }

    elseif(factor-1)

    {

      //取得右子节点平衡因子

      factor=getBalanceFactor(bn-right);

      //左旋转之前,如果右子节点平衡因子大于0,则需要先对右子树进行右旋转

      if(factor0)rightRotate(bn-right);

      //平衡左旋转

      leftRotate(bn);

    }

    //删除节点需要继续向上传导

    bn=bn-parent;

  }

  //返回删除调整后的替换节点

  returnresult;

}

抽象结构优化(binaryTree.h、binaryTree.c):

#defineBinaryTreeOrderBUFFER

typedefdoublebinaryElemType;

typedefstruct

{

  intkey;          //二叉树节点关键字(优先数)

  binaryElemType*data;    //数据内容

  intdataSize;        //数据内容的空间大小

  structbinaryNode*parent;  //父节点

  structbinaryNode*left;  //左节点

  structbinaryNode*right;  //右节点

  intheight;          //二叉树的高度(包括根节点)

  intlength;          //二叉树的节点数量(包括所有子节点)

  intisRight;        //如果是子节点,则是否为右节点(右:1;左:0)

}binaryNode;

//创建二叉树节点

binaryNode*createBinaryNode(intdataSize);

//设置二叉树节点的数据内容

voidsetBinaryNodeData(binaryNode*T,binaryElemType*e);

//是否为叶子节点返回1,否则返回0

intisLeafBinaryNode(binaryNode*T);

//二叉树的高度

intheightBinaryList(binaryNode*T);

//二叉树的高度(递归)

intheightBinaryListRecursion(binaryNode*T);

//二叉树的节点数量

intlengthBinaryList(binaryNode*T);

//二叉树的节点数量(递归)

intlengthBinaryListRecursion(binaryNode*T);

//取得二叉树节点的层级

intlevelBinaryNode(binaryNode*T);

//取得子节点的相对层级

intlevelBinaryChildNode(binaryNode*T,binaryNode*child);

//取得二叉树节点的根节点

binaryNode*getBinaryRoot(binaryNode*T);

//取得二叉树的最大节点

binaryNode*getMaxBinaryNode(binaryNode*T);

//取得二叉树的最小节点

binaryNode*getMinBinaryNode(binaryNode*T);

//插入二叉树的子节点(右:1;左:0)

binaryNode*insertBinaryNode(binaryNode*T,intisRight,intkey);

//添加二叉树的子节点(右:1;左:0)

binaryNode*addBinaryNode(binaryNode*T,intisRight,binaryNode*child);

//移除二叉树的子节点

intremoveBinaryNode(binaryNode*T,binaryNode*child);

//清空二叉树列表(递归)

voidclearBinaryList(binaryNode*T);

#includestdlib.h

#include"mystring.h"

#include"linkQueue.h"

#include"linkStack.h"

#include"binaryTree.h"

//创建二叉树节点

binaryNode*createBinaryNode(intdataSize)

{

  //首先申请自己的内存空间

  binaryNode*bn=(binaryNode*)malloc(sizeof(binaryNode));

  if(!bn)returnNULL;

  if(dataSize0)

  {

    bn-data=(binaryElemType*)malloc(sizeof(binaryElemType)*dataSize);

    if(!bn-data)

    {

      //清空二叉树列表(递归)

      clearBinaryList(bn);

      returnNULL;

    }

    bn-dataSize=dataSize;

  }

  else

  {

    bn-data=NULL;

    bn-dataSize=0;

  }

  bn-key=0;

  bn-parent=NULL;

  bn-left=NULL;

  bn-right=NULL;

  bn-height=1;

  bn-length=1;

  bn-isRight=0;

  returnbn;

}

//设置二叉树节点的数据内容

voidsetBinaryNodeData(binaryNode*T,binaryElemType*data)

{

  if((!T)

(!data))return;

  //判断数据内容是否有效

  if(T-data)

  {

    //是否包含数据内容

    inti;

    //设置数据内容

    for(i=0;iT-dataSize;i++)

    {

      T-data=data;

    }

  }

}

//是否为叶子节点返回1,否则返回0

intisLeafBinaryNode(binaryNode*T)

{

  if(!T)return-1;

  return((!T-left)(!T-right));

}

//二叉树的高度

intheightBinaryList(binaryNode*T)

{

  if(!T)return0;

  //判断节点高度是否有效

  if(T-height0)

  {

    returnT-height;

  }

  else

  {

    //二叉树的高度(递归)

    returnheightBinaryListRecursion(T);

  }

}

//二叉树的高度(递归)

intheightBinaryListRecursion(binaryNode*T)

{

  if(!T)return0;

  //二叉树的节点高度

  intheight=1;

  //递归记录左子树高度

  intleftHeight=heightBinaryListRecursion(T-left);

  //递归记录右子树高度

  intrightHeight=heightBinaryListRecursion(T-right);

  if(leftHeightrightHeight)

  {

    height+=leftHeight;

  }

  else

  {

    height+=rightHeight;

  }

  //更新节点高度

  T-height=height;

  returnheight;

}

//二叉树的节点数量

intlengthBinaryList(binaryNode*T)

{

  if(!T)return0;

  //判断节点数量是否有效

  if(T-length0)

  {

    returnT-length;

  }

  else

  {

    //二叉树的节点数量(递归)

    returnlengthBinaryListRecursion(T);

  }

}

//二叉树的节点数量(递归)

intlengthBinaryListRecursion(binaryNode*T)

{

  if(!T)return0;

  //二叉树的节点数量

  intlen=1;

  //递归记录左子树数量

  len+=lengthBinaryListRecursion(T-left);

  //递归记录右子树数量

  len+=lengthBinaryListRecursion(T-right);

  //更新节点数量

  T-length=len;

  returnlen;

}

//取得二叉树节点的层级

intlevelBinaryNode(binaryNode*T)

{

  if(!T)return-1;

  //从0开始

  intlevel=0;

  binaryNode*bn=T;

  //遍历父级节点

  while(bn-parent)

  {

    level++;

    //递归父级节点

    bn=bn-parent;

  }

  returnlevel;

}

//取得子节点的相对层级

intlevelBinaryChildNode(binaryNode*T,binaryNode*child)

{

  if((!T)

(!child))return-1;

  //从0开始

  intlevel=0;

  binaryNode*bn=child;

  //遍历节点

  while(bn)

  {

    if(T==bn)returnlevel;

    level++;

    //递归父级节点

    bn=bn-parent;

  }

  return-1;

}

//取得二叉树节点的根节点

binaryNode*getBinaryRoot(binaryNode*T)

{

  if(!T)returnNULL;

  binaryNode*bn=T;

  //遍历父级节点

  while(bn-parent)

  {

    //递归父级节点

    bn=bn-parent;

  }

  returnbn;

}

//取得二叉树的最大节点

binaryNode*getMaxBinaryNode(binaryNode*T)

{

  if(!T)returnNULL;

  binaryNode*bn=T;

  //遍历右节点

  while(bn-right)

  {

    //递归右节点

    bn=bn-right;

  }

  returnbn;

}

//取得二叉树的最小节点

binaryNode*getMinBinaryNode(binaryNode*T)

{

  if(!T)returnNULL;

  binaryNode*bn=T;

  //遍历左节点

  while(bn-left)

  {

    //递归左节点

    bn=bn-left;

  }

  returnbn;

}

//重新设置节点高度

intresetHeightBinaryNode(binaryNode*T)

{

  if(!T)return0;

  //二叉树的节点高度

  intheight=1;

  //记录左子树高度

  intleftHeight=heightBinaryList(T-left);

  //记录右子树高度

  intrightHeight=heightBinaryList(T-right);

  if(leftHeightrightHeight)

  {

    height+=leftHeight;

  }

  else

  {

    height+=rightHeight;

  }

  //更新节点高度

  T-height=height;

  returnheight;

}

//插入二叉树的子节点(右:1;左:0)

binaryNode*insertBinaryNode(binaryNode*T,intisRight,intkey)

{

  if(!T)returnNULL;

  //判断是否已有左节点或右节点

  if(isRight0)

  {

    if(T-right)returnNULL;

  }

  else

  {

    if(T-left)returnNULL;

  }

  //创建二叉树节点

  binaryNode*child=createBinaryNode(T-dataSize);

  if(!child)returnNULL;

  //节点关键字(优先数)

  child-key=key;

  //父级节点

  child-parent=T;

  //判断插入左节点或右节点

  if(isRight0)

  {

    T-right=child;

    child-isRight=1;

  }

  else

  {

    T-left=child;

    child-isRight=0;

  }

  //维护节点数量和高度

  binaryNode*bn=T;

  //遍历节点

  while(bn)

  {

    bn-length++;

    //重新设置节点高度

    resetHeightBinaryNode(bn);

    //递归父级节点

    bn=bn-parent;

  }

  returnchild;

}

//添加二叉树的子节点(右:1;左:0)

binaryNode*addBinaryNode(binaryNode*T,intisRight,binaryNode*child)

{

  if((!T)

(!child))returnNULL;

  //判断是否已有左节点或右节点

  if(isRight0)

  {

    if(T-right)returnNULL;

  }

  else

  {

    if(T-left)returnNULL;

  }

  //避免嵌套死循环,相对层级=0,则表示嵌套子级节点

  if(levelBinaryChildNode(child,T)=0)returnNULL;

  //移除原有的父级关系

  removeBinaryNode(child-parent,child);

  //父级节点

  child-parent=T;

  //判断添加左节点或右节点

  if(isRight0)

  {

    T-right=child;

    child-isRight=1;

  }

  else

  {

    T-left=child;

    child-isRight=0;

  }

  //维护节点数量和高度

  binaryNode*bn=T;

  //遍历节点

  while(bn)

  {

    bn-length+=child-length;

    //重新设置节点高度

    resetHeightBinaryNode(bn);

    //递归父级节点

    bn=bn-parent;

  }

  returnchild;

}

//移除二叉树的子节点

intremoveBinaryNode(binaryNode*T,binaryNode*child)

{

  if((!T)

(!child))return-1;

  //判断父级关系是否匹配

  if(T!=child-parent)return-1;

  intresult=-1;

  //判断是否移除左节点

  if(T-left==child)

  {

    T-left=NULL;

    result=1;

  }

  //判断是否移除右节点

  if(T-right==child)

  {

    T-right=NULL;

    result=1;

  }

  if(result0)

  {

    child-parent=NULL;

    //维护节点数量和高度

    binaryNode*bn=T;

    //遍历节点

    while(bn)

    {

      bn-length-=child-length;

      //重新设置节点高度

      resetHeightBinaryNode(bn);

      //递归父级节点

      bn=bn-parent;

    }

  }

  returnresult;

}

//清空二叉树列表(递归)

voidclearBinaryList(binaryNode*T)

{

  if(!T)return;

  //递归清空左节点

  clearBinaryList(T-left);

  //递归清空右节点

  clearBinaryList(T-right);

  //释放数据空间

  if(T-data)free(T-data);

  //释放自己

  free(T);

}

预览时标签不可点收录于话题#个上一篇下一篇
1