求满二叉树两个节点之间的最短距离

求满二叉树两个节点之间的最短距离

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FirstSolver
{
    internal class Program
    {
        static void Main(string[] args)
        {
            BinaryTreeNode<int> root1 = FullBinaryTree.CreateTree(1, 4);
            Console.WriteLine(FullBinaryTree.PrintTree(root1));
            Console.WriteLine();

            BinaryTreeNode<int> root2 = FullBinaryTree.CreateTree(101, 4);
            Console.WriteLine(FullBinaryTree.PrintTree(root2));
            Console.WriteLine();

            BinaryTreeNode<int> root3 = FullBinaryTree.CreateTree(201, 4);
            Console.WriteLine(FullBinaryTree.PrintTree(root3));
            Console.WriteLine();

            root1.ParentNode = root2;
            root2.ParentNode = root3;
            root3.ParentNode = root1;

            BinaryTreeNode<int> nodeA = FullBinaryTree.FindNode(root1, 5);
            BinaryTreeNode<int> nodeB = FullBinaryTree.FindNode(root1, 7);
            Console.WriteLine($"[A({nodeA.Value})]->[B({nodeB.Value})]");
            Stack<BinaryTreeNode<int>> path = FullBinaryTree.FindPath(nodeA, nodeB);
            Console.WriteLine(FullBinaryTree.PrintPath(path));
            Console.WriteLine(FullBinaryTree.PrintPath(FullBinaryTree.QuickFindPath(nodeA, nodeB)));
            Console.WriteLine();

            nodeB = FullBinaryTree.FindNode(root2, 107);
            Console.WriteLine($"[A({nodeA.Value})]->[B({nodeB.Value})]");
            path = FullBinaryTree.FindPath(nodeA, nodeB);
            Console.WriteLine(FullBinaryTree.PrintPath(path));
            Console.WriteLine(FullBinaryTree.PrintPath(FullBinaryTree.QuickFindPath(nodeA, nodeB)));
            Console.WriteLine();

            nodeB = FullBinaryTree.FindNode(root3, 207);
            Console.WriteLine($"[A({nodeA.Value})]->[B({nodeB.Value})]");
            path = FullBinaryTree.FindPath(nodeA, nodeB);
            Console.WriteLine(FullBinaryTree.PrintPath(path));
            Console.WriteLine(FullBinaryTree.PrintPath(FullBinaryTree.QuickFindPath(nodeA, nodeB)));
            Console.WriteLine();

            // 测试是否死循环
            nodeB = new BinaryTreeNode<int>(301);
            Console.WriteLine($"[A({nodeA.Value})]->[B({nodeB.Value})]");
            path = FullBinaryTree.FindPath(nodeA, nodeB);
            Console.WriteLine(FullBinaryTree.PrintPath(path));
            Console.WriteLine(FullBinaryTree.PrintPath(FullBinaryTree.QuickFindPath(nodeA, nodeB)));
            Console.WriteLine();

            Console.ReadKey();
        }
    }

    /// 
    /// 满二叉树
    /// 
    /// 数据类型
    public static class FullBinaryTree
    {
        /// 
        /// 创建深度为depth的满二叉树
        /// 
        /// 初始值
        /// 深度
        /// 满二叉树头结点
        public static BinaryTreeNode<int> CreateTree(int intial, int depth)
        {
            BinaryTreeNode<int> header = new BinaryTreeNode<int>(intial);
            CreateSub(header, intial, 2, depth);
            return header;
        }

        /// 
        /// 创建子树
        /// 
        /// 父节点
        /// 根节点初始值
        /// 层级
        /// 深度
        private static void CreateSub(BinaryTreeNode<int> node, int initial, int level, int depth)
        {
            if (level > depth) return;
            int value = (node.Value << 1) - (initial - 1);
            BinaryTreeNode<int> leftChildNode = new BinaryTreeNode<int>(value);
            BinaryTreeNode<int> rightChildNode = new BinaryTreeNode<int>(value + 1);
            node.LeftChildNode = leftChildNode;
            node.RightChildNode = rightChildNode;
            leftChildNode.ParentNode = node;
            rightChildNode.ParentNode = node;
            CreateSub(leftChildNode, initial, level + 1, depth);
            CreateSub(rightChildNode, initial, level + 1, depth);
        }

        /// 
        /// 打印二叉树
        /// 
        /// 节点
        /// 二叉树字符串
        public static string PrintTree(BinaryTreeNode<int> header)
        {
            StringBuilder sb = new StringBuilder($"{header.Value}");
            if (header.LeftChildNode != null)
            {
                sb.Append($"({header.LeftChildNode.Value},{header.RightChildNode.Value})");
                PrintTreeSub(header.LeftChildNode, sb);
                PrintTreeSub(header.RightChildNode, sb);
            }
            return sb.ToString();
        }

        private static void PrintTreeSub(BinaryTreeNode<int> node, StringBuilder sb)
        {
            sb.Append($" {node.Value}");
            if (node.LeftChildNode != null)
            {
                sb.Append($"({node.LeftChildNode.Value},{node.RightChildNode.Value})");
                PrintTreeSub(node.LeftChildNode, sb);
                PrintTreeSub(node.RightChildNode, sb);
            }
        }

        /// 
        /// 查找指定值的节点
        /// 
        /// 二叉树
        /// 要匹配的值
        /// 找到的节点
        public static BinaryTreeNode<int> FindNode(BinaryTreeNode<int> node, int value)
        {
            if (Equals(node.Value, value)) return node;
            if (node.LeftChildNode != null)
            {
                return FindNode(node.LeftChildNode, value) ?? FindNode(node.RightChildNode, value);
            }
            return null;
        }

        /// 
        /// 定位根节点
        /// 
        /// 初始节点
        /// 根节点
        public static BinaryTreeNode<int> GetRootNode(BinaryTreeNode<int> node)
        {
            while (true)
            {
                if (node.ParentNode == null) break;
                if (node.ParentNode.LeftChildNode != node && node.ParentNode.RightChildNode != node) break;
                node = node.ParentNode;
            }
            return node;
        }

        /// 
        /// 寻找节点A到节点B的最短路径
        /// 
        /// 节点A
        /// 节点B
        /// 最短路径
        public static Stack<BinaryTreeNode<int>> FindPath(BinaryTreeNode<int> nodeA, BinaryTreeNode<int> nodeB)
        {
            BinaryTreeNode<int> rootA = GetRootNode(nodeA);

            Stack<BinaryTreeNode<int>> path = new Stack<BinaryTreeNode<int>>();

            BinaryTreeNode<int> node = nodeA;
            path.Push(node);
            bool find = FindPathSub(node, nodeB, path);
            if (!find)
            {
                while (!find)
                {
                    if (node.ParentNode == null) break;

                    // 避免死循环
                    if (node.ParentNode == rootA && (node != rootA.LeftChildNode && node != rootA.RightChildNode)) break;

                    path.Push(node.ParentNode);

                    int state = 0; // 进入另一颗二叉树
                    if (node.ParentNode.LeftChildNode == node)
                        state = 1;
                    else if (node.ParentNode.RightChildNode == node)
                        state = 2;

                    if (state == 0 || state == 1)
                    {
                        find = FindPathSub(node.ParentNode.RightChildNode, nodeB, path);
                        if (find) break;
                    }

                    if (state == 0 || state == 2)
                    {
                        find = FindPathSub(node.ParentNode.LeftChildNode, nodeB, path);
                        if (find) break;
                    }
                    node = node.ParentNode;
                }
            }
            return find ? path : null;
        }

        private static bool FindPathSub(BinaryTreeNode<int> node, BinaryTreeNode<int> search, Stack<BinaryTreeNode<int>> path)
        {
            path.Push(node);
            if (node == search) return true;
            if (node.LeftChildNode != null)
            {
                if (FindPathSub(node.LeftChildNode, search, path)) return true;
                if (FindPathSub(node.RightChildNode, search, path)) return true;
            }
            path.Pop();
            return false;
        }

        /// 
        /// 获取到根节点的路径
        /// 
        /// 起始节点
        /// 到根节点路径
        public static List<BinaryTreeNode<int>> GetRootNodePath(BinaryTreeNode<int> node)
        {
            List<BinaryTreeNode<int>> path = new List<BinaryTreeNode<int>>();
            path.Add(node);
            while (true)
            {
                if (node.ParentNode == null) break;
                if (node.ParentNode.LeftChildNode != node && node.ParentNode.RightChildNode != node) break;
                node = node.ParentNode;
                path.Add(node);
            }
            return path;
        }

        /// 
        /// 快速寻找节点A到节点B的最短路径
        /// 
        /// 节点A
        /// 节点B
        /// 最短路径
        public static List<BinaryTreeNode<int>> QuickFindPath(BinaryTreeNode<int> nodeA, BinaryTreeNode<int> nodeB)
        {
            List<BinaryTreeNode<int>> pathA = GetRootNodePath(nodeA);
            List<BinaryTreeNode<int>> pathB = GetRootNodePath(nodeB);
            BinaryTreeNode<int> rootA = pathA[pathA.Count - 1];
            BinaryTreeNode<int> rootB = pathB[pathB.Count - 1];
            if (rootA == rootB)
            {
                int i = pathA.Count - 2;
                int j = pathB.Count - 2;
                for (; i >= 0 && j >= 0; i--, j--)
                {
                    if (pathA[i] != pathB[j]) break;
                }

                if (pathA.Count - 2 > i) pathA.RemoveRange(i + 2, pathA.Count - i - 2);
                pathB.RemoveRange(j + 1, pathB.Count - j - 1);
                pathB.Reverse();
                pathA.AddRange(pathB);
                return pathA;
            }
            else
            {
                BinaryTreeNode<int> node = rootA;
                while (node.ParentNode != null)
                {
                    node = node.ParentNode;
                    if (node == rootB)
                    {
                        pathB.Reverse();
                        pathA.AddRange(pathB);
                        return pathA;
                    }
                    else if (node == rootA)
                    {   // 避免死循环
                        break;
                    }
                    pathA.Add(node);
                }
                return null;
            }            
        }

        /// 
        /// 打印路径
        /// 
        /// 路径
        /// 路径字符串      
        public static string PrintPath(IEnumerable<BinaryTreeNode<int>> path)
        {
            if (path == null) return "No Path!"; // 没有路径到达
            IEnumerable<BinaryTreeNode<int>> p = path;
            if (path is Stack<BinaryTreeNode<int>>)
            {
                p = p.Reverse();
            }            
            StringBuilder sb = new StringBuilder();
            foreach (var item in p)
            {
                sb.Append($"{item.Value}->");
            }
            sb.Remove(sb.Length - 2, 2);
            return sb.ToString();
        }
    }

    /// 
    /// 节点定义
    /// 
    /// 节点数据类型:要求值类型
    public class BinaryTreeNode<T> where T : struct
    {
        public T Value { get; set; }
        public BinaryTreeNode<T> ParentNode { get; set; }
        public BinaryTreeNode<T> LeftChildNode { get; set; }
        public BinaryTreeNode<T> RightChildNode { get; set; }

        public BinaryTreeNode() { Value = default; }
        public BinaryTreeNode(T value) { Value = value; }
    }
}

你可能感兴趣的:(c#,开发语言)