04-树5 Root of AVL Tree (25 分)
对方算法完全正确,不贴图了.
下面是我的算法的图.

04-树5 Root of AVL Tree (25 分)
An AVL tree is a self-balancing binary search tree. In an AVL tree, the heights of the two child subtrees of any node differ by at most one; if at any time they differ by more than one, rebalancing is done to restore this property. Figures 1-4 illustrate the rotation rules.
Input Specification:
Each input file contains one test case. For each case, the first line contains a positive integer N (≤20) which is the total number of keys to be inserted. Then N distinct integer keys are given in the next line. All the numbers in a line are separated by a space.
Output Specification:
For each test case, print the root of the resulting AVL tree in one line.
Sample Input 1:
5
88 70 61 96 120
Sample Output 1:
70
Sample Input 2:
7
88 70 61 96 120 90 65
Sample Output 2:
88
另外,我不认为 4,5没通过,就是我答案的错误.
也许是 生成的树变化了.导致根节点不一样而已.
并不能说我产生的树 就错误.
----------
另外,关于性能,这代码,是每次都从根部开始查找插入的位置,然后插入的.
其实可以这样,
1若是插入右侧,可以判定右侧是不是已经饱和了.添加新节点,必须增加深度.左侧也一样.
2,不要每次查询插入位置,都从根节点开始,而是第一次从根节点,以后,从发现者节点开始往下搜索.
平衡树这个,我觉得,若是右侧饱和,又必须插入右侧数据,不如把这个节点,与根节点并排,作为树根.也就是说,有两个根,双根总比单根来的有效率.
或者是说让他产生一个虚根.
虚根若有一个子节点,虚根就不存在.若是有两个子节点,虚根就存在.
----------------
2018年10月1日
自己的代码效率根人家 4中方案的效率差太多.折腾了好些天,至少对方的4中情况怎么弄.自己算是弄清楚了.
晚些时候再去看看,他是怎么判断 谁是发现者的.
我寻找发现者的方式,是从插入的节点,向上寻找父节点,判断父节点是不是发现者,若不是,继续找父节点的父节点.因为我做的节点里,有个 父node 如果 avl树 是通过树根往下 遍历寻找发现者的话,如果树很大, 会很慢.
(好像我想的不对).......我是从底部向上寻找,他是从顶部向下寻找.一样的.
以下代码是对方的算法
using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using System.Diagnostics; using System.Net; using System.Text; using System.Xml; public class MyNode { public MyNode(string s) { Value = int.Parse(s); } public MyNode(int s) { Value = s; } public MyNode Left; public MyNode Right; public int Value; public int 左右节点层级差值 { get { if (this == null) { return int.MaxValue; } else { int l = Left != null ? Left.最大层级 : 0; int r = Right != null ? Right.最大层级 : 0; return l - r; } } } /// <summary> /// 当前有多少子层,孙层 /// </summary> public int 最大层级 { get { if (this == null) { return 0; } else { int max = 1; if (Left != null && Right != null) { int l = Left.最大层级; int r = Right.最大层级; max += Math.Max(l, r); } else { if (Left != null) { max += Left.最大层级; } else if (Right != null) { max += Right.最大层级; } } return max; } } } #region 暂时无用的东西 public MyNode 最小的孙子 { get { var t = this; while (t.Left != null) { t = t.Left; } return t; } } public MyNode 最大的孙子 { get { var t = this; while (t.Right != null) { t = t.Right; } return t; } } public int 直接子节点数量 { get { int i = 0; if (Left != null) { i++; } if (Right != null) { i++; } return i; } } public MyNode Next { get { if (Left != null && Right == null) { return Left; } if (Left == null && Right != null) { return Right; } return null; } } #endregion /// <summary> /// 存放父node /// </summary> public MyNode Pnode; } class MyTree { public MyNode myNode; public MyTree(string v2) { var temp = v2.Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries); if (temp.Length > 0) { for (int i = 0; i < temp.Length; i++) { int v = int.Parse(temp[i]); 插入并调整平衡(v); } } } /// <summary> /// 插入节点并返回这个节点 /// </summary> /// <param name="v"></param> /// <returns></returns> MyNode Insert(int v) { if (myNode == null) { myNode = new MyNode(v); return myNode; } MyNode temp; temp = myNode; while (temp != null) { if (temp.Value > v) { var t2 = temp.Left; if (t2 != null) { t2.Pnode = temp; temp = t2; } else { temp.Left = new MyNode(v); temp.Left.Pnode = temp; return temp.Left; } } else { var t2 = temp.Right; if (t2 != null) { t2.Pnode = temp; temp = t2; } else { temp.Right = new MyNode(v); temp.Right.Pnode = temp; return temp.Right; } } } return null; } void 平衡插入弃用(int v) { var 麻烦节点 = Insert(v); if (麻烦节点.Pnode == null)//p为空,说明只有一个节点 { //无需操作,平衡着呢 return; } else { MyNode 发现者 = 获取不平衡节点(麻烦节点.Pnode); if (发现者 == null) { //平衡,结束操作 } else { //此时,只需要修改 发现者 以内的节点,即可做到平衡 //先把这个 麻烦节点,从树中移除掉 麻烦节点.Pnode.Left = 麻烦节点.Pnode.Right = null; if (v > 发现者.Value)//说明需要插入到根节点的右侧 { var p = 麻烦节点.Pnode; int newV = v; while (p != 发现者) { if (newV > p.Value) { int tempV = p.Value; p.Value = newV; newV = tempV; break; } else { p = p.Pnode; } } if (p == 发现者) { if (newV > p.Value) { int tempV = p.Value; p.Value = newV; newV = tempV; } } 平衡插入弃用(newV); } if (v < 发现者.Value)//说明需要插入到根节点的右侧 { var p = 麻烦节点.Pnode; int newV = v; while (p != 发现者) { if (newV < p.Value) { int tempV = p.Value; p.Value = newV; newV = tempV; break; } else { p = p.Pnode; } } if (p == 发现者) { if (newV < p.Value) { int tempV = p.Value; p.Value = newV; newV = tempV; } } 平衡插入弃用(newV); } } } } void 插入并调整平衡(int v) { var 麻烦节点 = Insert(v); if (麻烦节点.Pnode == null)//p为空,说明只有一个节点 { //无需操作,平衡着呢 return; } else { MyNode 发现者 = 获取不平衡节点(麻烦节点.Pnode); if (发现者 == null) { //平衡,结束操作 } else { if (v > 发现者.Value) {//右旋 if (v < 发现者.Right.Value) {//左旋RL var fxzP = 发现者.Pnode; var fxz = 发现者; var fxzR = 发现者.Right; var fxzRL = 发现者.Right.Left; if (fxzP != null) { if (fxzP.Left == fxz) { fxzP.Left = fxzRL; } else { fxzP.Right = fxzRL; } fxzRL.Pnode = fxz.Pnode; } fxz.Pnode = fxzRL; fxz.Right = fxzRL.Left; if (fxzRL.Left != null) { fxz.Right.Pnode = fxz; } fxzR.Left = fxzRL.Right; if (fxzRL.Right != null) { fxzR.Left.Pnode = fxzR; } fxzRL.Left = fxz; fxzRL.Right = fxzR; if (fxzP == null) { myNode = fxzRL; myNode.Pnode = null; } } else {//RR var fxzP = 发现者.Pnode; var fxz = 发现者; var fxzR = 发现者.Right; var fxzRL = 发现者.Right.Left; if (fxzP != null) { if (fxzP.Left == fxz) { fxzP.Left = fxzR; } else { fxzP.Right = fxzR; } fxzR.Pnode = fxzP; } fxz.Right = fxzRL; if(fxz.Right!=null) { fxz.Right.Pnode = fxz; } fxzR.Left = fxz; fxz.Pnode = fxzR; if (fxzP == null) { myNode = fxzR; myNode.Pnode = null; } } } else {//左旋 if (v > 发现者.Left.Value) {//左旋LR var fxzP = 发现者.Pnode; var fxz = 发现者; var fxzL = 发现者.Left; var fxzLR = 发现者.Left.Right; if (fxzP != null) { if (fxzP.Left == fxz) { fxzP.Left = fxzLR; } else { fxzP.Right = fxzLR; } fxzLR.Pnode = fxz.Pnode; } fxz.Pnode = fxzLR; fxz.Left = fxzLR.Right; if (fxzLR.Right != null) { fxz.Left.Pnode = fxz; } fxzL.Right = fxzLR.Left; if (fxzLR.Left != null) { fxzL.Right.Pnode = fxzL; } fxzLR.Left = fxzL; fxzLR.Right = fxz; if (fxzP == null) { myNode = fxzLR; myNode.Pnode = null; } } else {//LL var fxzP = 发现者.Pnode; var fxz = 发现者; var fxzL = 发现者.Left; var fxzLR = 发现者.Left.Right; if (fxzP != null) { if (fxzP.Left == fxz) { fxzP.Left = fxzL; } else { fxzP.Right = fxzL; } fxzL.Pnode = fxz.Pnode; } fxz.Left = fxzLR; if (fxz.Left != null) { fxzLR.Pnode = fxz; } fxz.Pnode = fxzL; fxzL.Right = fxz; if (fxzP == null) { myNode = fxzL; myNode.Pnode = null; } } } } } } /// <summary> /// 由插入的新节点,向上追溯,找到发现者 /// </summary> /// <param name="p"></param> /// <returns></returns> private MyNode 获取不平衡节点(MyNode p) { var 发现者 = p; while (发现者 != null) { if (Math.Abs(发现者.左右节点层级差值) > 1) { return 发现者; } else { 发现者 = 发现者.Pnode;//一直找父节点,知道根,根没有父节点,退出循环 } } return null; } } class T { static void Main(string[] args) { int vvv = int.Parse(Console.ReadLine()); var v = Console.ReadLine(); MyTree tree = new MyTree(v); Console.WriteLine(tree.myNode.Value); } }
以下代码是自己的算法
using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using System.Diagnostics; using System.Net; using System.Text; using System.Xml; public class MyNode { public MyNode(string s) { Value = int.Parse(s); } public MyNode(int s) { Value = s; } public MyNode Left; public MyNode Right; public int Value; public int 左右节点层级差值 { get { if (this == null) { return int.MaxValue; } else { int l = Left != null ? Left.最大层级 : 0; int r = Right != null ? Right.最大层级 : 0; return l - r; } } } /// <summary> /// 当前有多少子层,孙层 /// </summary> public int 最大层级 { get { if (this == null) { return 0; } else { int max = 1; if (Left != null && Right != null) { int l = Left.最大层级; int r = Right.最大层级; max += Math.Max(l, r); } else { if(Left!=null) { max+=Left.最大层级; } else if(Right!=null) { max+=Right.最大层级; } } return max; } } } #region 暂时无用的东西 public MyNode 最小的孙子 { get { var t = this; while (t.Left != null) { t = t.Left; } return t; } } public MyNode 最大的孙子 { get { var t = this; while (t.Right != null) { t = t.Right; } return t; } } public int 直接子节点数量 { get { int i = 0; if (Left != null) { i++; } if (Right != null) { i++; } return i; } } public MyNode Next { get { if (Left != null && Right == null) { return Left; } if (Left == null && Right != null) { return Right; } return null; } } #endregion /// <summary> /// 存放父node /// </summary> public MyNode Pnode; } class MyTree { public MyNode myNode; public MyTree(string v2) { var temp = v2.Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries); if (temp.Length > 0) { for (int i = 0; i < temp.Length; i++) { int v = int.Parse(temp[i]); 平衡插入(v); } } } /// <summary> /// 插入节点并返回这个节点 /// </summary> /// <param name="v"></param> /// <returns></returns> MyNode Insert(int v) { if (myNode == null) { myNode = new MyNode(v); return myNode; } MyNode temp; temp = myNode; while (temp != null) { if (temp.Value > v) { var t2 = temp.Left; if (t2 != null) { t2.Pnode = temp; temp = t2; } else { temp.Left = new MyNode(v); temp.Left.Pnode = temp; return temp.Left; } } else { var t2 = temp.Right; if (t2 != null) { t2.Pnode = temp; temp = t2; } else { temp.Right = new MyNode(v); temp.Right.Pnode = temp; return temp.Right; } } } return null; } void 平衡插入(int v) { var 麻烦节点 = Insert(v); if (麻烦节点.Pnode == null)//p为空,说明只有一个节点 { //无需操作,平衡着呢 return; } else { MyNode 发现者 = 获取不平衡节点(麻烦节点.Pnode); if (发现者 == null) { //平衡,结束操作 } else { //此时,只需要修改 发现者 以内的节点,即可做到平衡 //先把这个 麻烦节点,从树中移除掉 麻烦节点.Pnode.Left = 麻烦节点.Pnode.Right = null; if (v > 发现者.Value)//说明需要插入到根节点的右侧 { var p = 麻烦节点.Pnode; int newV = v; while (p != 发现者) { if (newV > p.Value) { int tempV = p.Value; p.Value = newV; newV = tempV; break; } else { p = p.Pnode; } } if (p == 发现者) { if (newV > p.Value) { int tempV = p.Value; p.Value = newV; newV = tempV; } } 平衡插入(newV); } if (v < 发现者.Value)//说明需要插入到根节点的右侧 { var p = 麻烦节点.Pnode; int newV = v; while (p != 发现者) { if (newV < p.Value) { int tempV = p.Value; p.Value = newV; newV = tempV; break; } else { p = p.Pnode; } } if (p == 发现者) { if (newV < p.Value) { int tempV = p.Value; p.Value = newV; newV = tempV; } } 平衡插入(newV); } } } } private MyNode 获取不平衡节点(MyNode p) { var 发现者 = p; while (发现者 != null) { if (Math.Abs(发现者.左右节点层级差值) > 1) { return 发现者; } else { 发现者 = 发现者.Pnode;//一直找父节点,知道根,根没有父节点,退出循环 } } return null; } } class T { static void Main(string[] args) { Console.ReadLine(); var v = Console.ReadLine(); MyTree tree = new MyTree(v); Console.WriteLine(tree.myNode.Value); return; } }
浙公网安备 33010602011771号