平衡二叉树的实现和前中后层次遍历代码实现

本文介绍了AVL树的实现,包括AVLTreeNode类的定义,非递归遍历方法(先序、中序、后序和层次),计算高度和平衡因子,以及节点失衡调节和插入节点的处理。
摘要由CSDN通过智能技术生成
public class AVLTreeNode<T>: IComparable<AVLTreeNode<T>>
{

    // 节点值
    public T value { get; set; }

    // 相对高度
    public int height {  get; set; }

    // 定义节点的平衡因子
    public int _bf { get; set; }
    // 左孩子
    public AVLTreeNode<T> leftChild { get; set; }

    // 右孩子
    public AVLTreeNode<T> rightChild { get; set; }

    // 旋转时的父节点

    public AVLTreeNode<T> _parent { get; set; }  

    public AVLTreeNode(T value)
    {
        this.value = value;
    }

    public int CompareTo(AVLTreeNode<T>? other)
    {
        throw new NotImplementedException();
    }
}


// 如何计算二叉树的高度
// 非递归 迭代方法
/// <summary>
/// 平衡二叉树
/// </summary>
public class AVLTree
{

    // 平衡二叉树的根节点
    public AVLTreeNode<int> _root = null;

    /// <summary>
    /// 二叉树的先序遍历
    /// </summary>
    /// <param name="node"></param>
    public void preOrder(AVLTreeNode<int> node)
    {
        if (node == null)
        {
            return;
        }
        Stack<AVLTreeNode<int>> stack = new Stack<AVLTreeNode<int>>();
        stack.Push(node);
        while (stack.Count != 0)
        {

            AVLTreeNode<int> node1 = stack.Pop();
            Console.WriteLine(node1.value);
            if (node1.rightChild != null)
            {
                stack.Push(node1.rightChild);
            }
            if (node1.leftChild != null)
            {
                stack.Push(node1.leftChild);
            }
        }
    }
    /// <summary>
    /// 二叉树中序遍历方法 非递归
    /// </summary>
    /// <param name="root"></param>
    public void inOrder(AVLTreeNode<int> root)
    {
        // 如果根节点为空,则退出函数调用
        if (root == null)
        {
            return;
        }
        // 如果根节点不为空
        // 声明并初始化一个空栈
        Stack<AVLTreeNode<int>> stack = new Stack<AVLTreeNode<int>>();
        // cur为当前遍历节点
        AVLTreeNode<int> cur = root;
        while (stack.Count != 0 || cur != null)
        {
            // 如果当前节点不为空,继续遍历其左孩子
            while (cur != null)
            {
                stack.Push(cur);
                cur = cur.leftChild;


            }
            // 如果当前节点为空,则弹出栈顶元素
            AVLTreeNode<int> node1 = stack.Pop();
            Console.WriteLine(node1.value);
            // 当前节点指栈顶的右孩子
            cur = node1.rightChild;

        }
    }


    /// <summary>
    /// 二叉树后序遍历  // 双循环 + 栈
    /// </summary>
    /// <param name="root"></param>
    public void postOrder(AVLTreeNode<int> root)
    {
        if (root == null)
        {
            return;
        }
        List<int> res = new List<int>();
        Stack<AVLTreeNode<int>> stack = new Stack<AVLTreeNode<int>>();
        AVLTreeNode<int> cur = root;
        AVLTreeNode<int> prev = null;
        while (stack.Count != 0 || cur != null)
        {

            while (cur != null)
            {
                stack.Push(cur);
                cur = cur.leftChild;
            }
            // 出栈
            cur = stack.Pop();
           // 记录一个追溯父节点
           if(cur.rightChild == null || cur.rightChild == prev)
            {
                res.Add(cur.value);
                prev = cur;
                cur = null;
            }
            else
            {
                stack.Push(cur);
                cur = cur.rightChild;

            }



        }
        foreach (var i in res)
        {
            Console.WriteLine($"{i}");
        }

    }

    /// <summary>
    /// 层次遍历 用来打印节点的值
    /// </summary>
    /// <param name="root"></param>

    public void levelOrder(AVLTreeNode<int> root)
    {
        if (root == null)
        {
            return;
        }
        Queue<AVLTreeNode<int>> queue = new Queue<AVLTreeNode<int>>();

        queue.Enqueue(root);
        while (queue.Count != 0)
        {
            AVLTreeNode<int> cur = queue.Dequeue();

            Console.WriteLine(cur.value);
            if (cur.leftChild != null)
            {
                queue.Enqueue(cur.leftChild);
            }

            if (cur.rightChild != null)
            {
                queue.Enqueue(cur.rightChild);
            }

        }

    }


    /// <summary>
    /// 使用队列计算二叉树的高度
    /// </summary>
    /// <param name="aVLTreeNode"></param>
    /// <returns></returns>
    public static int height(AVLTreeNode<int> root)
    {
        if (root == null)
        {
            return 0;
        }

        // 二叉树的深度
        int depth = 0;
        Queue<AVLTreeNode<int>> queue = new Queue<AVLTreeNode<int>>();
        queue.Enqueue(root);

        // 队列不为空
        while (queue.Count > 0)
        {
            int n = queue.Count();
            // 
            while (n > 0)
            {
                AVLTreeNode<int> node = queue.Dequeue();
                if (node.leftChild != null)
                {
                    queue.Enqueue(node.leftChild);
                }
                if (node.rightChild != null)
                {
                    queue.Enqueue(node.rightChild);
                }
                n--;

            }

            depth++;
        }
        return depth;
    }

    /// <summary>
    /// 计算平衡因子
    /// </summary>
    /// <param name="root"></param>
    /// <returns></returns>
    public int get_BF(AVLTreeNode<int> root)
    {
        if (root == null)
        {
            return 0;
        }
        if (root.leftChild == null && root.rightChild == null)
        {
            return 0;
        }
        else if (root.leftChild == null)
        {
            return -root.rightChild.height;
        }
        else if (root.rightChild == null)
        {

            return root.leftChild.height;
        }
        else
        {
            return root.leftChild.height - root.rightChild.height;
        }

    }

    /// <summary>
    /// 中序遍历来判断
    /// </summary>
    /// <param name="root"></param>
    /// <returns></returns>
    public bool isBalanced(AVLTreeNode<int> root)
    {
        if (root == null)
        {
            return true;
        }
        // 判断以二叉树的每个节点为根的二叉树是否符合平衡二叉树的条件
        // 这里遍历二叉树的每个节点使用的是中序遍历(非递归)
        Stack<AVLTreeNode<int>> stack = new Stack<AVLTreeNode<int>>();

        /*  while (root != null || !stack.isEmpty())
          {
              if (root != null)
              {
                  stack.add(root);
                  root = root.left;
              }
              else
              {
                  TreeNode cur = stack.pop();
                  if (Math.abs(maxDepth(cur.left) - maxDepth(cur.right)) > 1)
                  {
                      return false;
                  }
                  root = cur.right;
              }
          }*/
        return true;
    }

    // 计算节点的平衡因子 左子树的高度与右子树高度的绝对值 <= 1
    public static bool isBalanceFactor(AVLTreeNode<int> aVLTreeNode)
    {

        if (aVLTreeNode == null)
        {
            return true;
        }

        // 判断根节点是否平衡  以及每个子节点是否平衡?
        // 左子树的高度  非递归咋实现?
        int leftHeight = height(aVLTreeNode.leftChild);
        int rightHeight = height(aVLTreeNode.rightChild);

        return Math.Abs(leftHeight - rightHeight) <= 1 && isBalanceFactor(aVLTreeNode.leftChild) && isBalanceFactor(aVLTreeNode.rightChild);

    }


    // 左旋转 对应RR旋转
    // 右旋转 对应LL调整
    // 双旋转
    // 左右旋转 对应LR调整
    // 右左旋转 对应RL调整
    public void leftRotat(AVLTreeNode<int> root)
    {
        AVLTreeNode<int> newNode = root.rightChild;
        AVLTreeNode<int> q = newNode.leftChild;
        root.rightChild = q;
        if (q != null)
        {
            q._parent = root;
        }
        newNode._parent = root._parent;
        if (newNode._parent != null)
        {
            if (newNode._parent.leftChild == root)
            {
                newNode._parent.leftChild = newNode;
            }
            else
            {
                newNode._parent.rightChild = newNode;
            }
        }
        else
        {
            this._root = newNode;
        }
        root._parent = newNode;
        newNode.leftChild = root;

        // 旋转完成后更新节点高度
        root.height = height(root);
        newNode.height = height(newNode);

    }

    public void RRotat(AVLTreeNode<int> root)
    {

        AVLTreeNode<int> newNode = root.leftChild;
        AVLTreeNode<int> q = newNode.rightChild;
        root.leftChild = q;
        if (q != null)
        {
            q._parent = root;
        }
        newNode._parent = root._parent;
        if (newNode._parent != null)
        {
            if (newNode._parent.leftChild == root)
            {
                newNode._parent.leftChild = newNode;
            }
            else
            {
                newNode._parent.rightChild = newNode;
            }
        }
        else
        {
            this._root = newNode;
        }
        root._parent = newNode;
        newNode.rightChild = root;

        // 旋转完成后更新节点高度
        root.height = height(root);
        newNode.height = height(newNode);
    }

    /// <summary>
    /// 节点失衡调节
    /// </summary>
    /// <param name="node"></param>
    /// <returns></returns>
    private void refreshNodeBalance(AVLTreeNode<int> node)
    {
        // 重新设置结点高度
        node.height = height(node);
        // 判断平衡因子,如果 平衡因子 > 1,则失衡
        int tmpNodeBalance = get_BF(node);
        // LL型平衡旋转  (单右旋转)
        if (tmpNodeBalance > 1 && get_BF(node.leftChild) > 0)
        {
            RRotat(node);
        }
        // RR型平衡旋转  (单左旋转)
        if (tmpNodeBalance < -1 && get_BF(node.rightChild) < 0)
        {
            leftRotat(node);
        }
        // LR型平衡旋转  (先左后右双旋转)
        if (tmpNodeBalance > 1 && get_BF(node.leftChild) < 0)
        {
            leftRotat(node.leftChild);
            RRotat(node);
        }
        // RL型平衡旋转  (先右后左双旋转)
        if (tmpNodeBalance < -1 && get_BF(node.rightChild) > 0)
        {
            RRotat(node.rightChild);
            leftRotat(node);
        }
    }

    /// <summary>
    /// 插入节点 构造平衡二叉树
    /// </summary>
    /// <param name="data"></param>
    public void Insert(int data)
    {
        // 如果传入的节点是空
        if (_root == null)
        {
            _root = new AVLTreeNode<int>(data);
            _root.height = 1;
            return;
        }
        AVLTreeNode<int> cur = _root;
        AVLTreeNode<int> parent;
        Stack<AVLTreeNode<int>> stack = new Stack<AVLTreeNode<int>>();
        stack.Push(_root);

        while (cur != null)
        {
            if (data < cur.value)
            {
                if (cur.leftChild != null)
                {
                    stack.Push(cur.leftChild);
                    cur = cur.leftChild;
                }
                else
                {

                    AVLTreeNode<int> node1 = new AVLTreeNode<int>(data);
                    node1._parent = cur;
                    node1.height = 1;
                    cur.leftChild = node1;
                    break;
                }
            }
            if (data > cur.value)
            {
                if (cur.rightChild != null)
                {
                    stack.Push(cur.rightChild);
                    cur = cur.rightChild;
                }
                else
                {
                    AVLTreeNode<int> node1 = new AVLTreeNode<int>(data);
                    node1._parent = cur;
                    node1.height = 1;
                    cur.rightChild = node1;
                    //cur.rightChild = new AVLTreeNode<int>(data);
                    break;
                }
            }

        }

        // 插入一个节点后 该节点是平衡的,所以我们要判断他的祖先节点
        while (stack.Count > 0)
        {
            refreshNodeBalance(stack.Pop());
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值