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

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

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();}}/// <summary>/// 满二叉树/// </summary>/// <typeparam name="T">数据类型</typeparam>public static class FullBinaryTree{/// <summary>/// 创建深度为depth的满二叉树/// </summary>/// <param name="intial">初始值</param>/// <param name="depth">深度</param>/// <returns>满二叉树头结点</returns>public static BinaryTreeNode<int> CreateTree(int intial, int depth){BinaryTreeNode<int> header = new BinaryTreeNode<int>(intial);CreateSub(header, intial, 2, depth);return header;}/// <summary>/// 创建子树/// </summary>/// <param name="node">父节点</param>/// <param name="initial">根节点初始值</param>/// <param name="level">层级</param>/// <param name="depth">深度</param>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);}/// <summary>/// 打印二叉树/// </summary>/// <param name="header">节点</param>/// <returns>二叉树字符串</returns>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);}}/// <summary>/// 查找指定值的节点/// </summary>/// <param name="node">二叉树</param>/// <param name="value">要匹配的值</param>/// <returns>找到的节点</returns>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;}/// <summary>/// 定位根节点/// </summary>/// <param name="node">初始节点</param>/// <returns>根节点</returns>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;}/// <summary>/// 寻找节点A到节点B的最短路径/// </summary>/// <param name="nodeA">节点A</param>/// <param name="nodeB">节点B</param>/// <returns>最短路径</returns>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;}/// <summary>/// 获取到根节点的路径/// </summary>/// <param name="node">起始节点</param>/// <returns>到根节点路径</returns>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;}/// <summary>/// 快速寻找节点A到节点B的最短路径/// </summary>/// <param name="nodeA">节点A</param>/// <param name="nodeB">节点B</param>/// <returns>最短路径</returns>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;}            }/// <summary>/// 打印路径/// </summary>/// <param name="path">路径</param>/// <returns>路径字符串</returns>      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();}}/// <summary>/// 节点定义/// </summary>/// <typeparam name="T">节点数据类型:要求值类型</typeparam>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; }}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/677404.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python实现基数排序

如果在给不同的整形数组排序的时候,一般会这样做,也就是先看最高位,如果最高位数值大的话也就意味着它的数值是最大的,而如果两个数字的最高位的数值是一样的,则继续比较次高位,这样依次去比较可以决定数字的排序。而对于基数排序来说,其思想是与以上的思想是不同的,基…

Node版本管理 - nvm

简介 nvm 允许用户在同一台电脑上安装并管理多个 Node.js 版本并支持快速切换&#xff0c;对于需要在不同的项目中使用不同版本的 Node.js 的开发者来说非常有用。 使用 下载安装后&#xff0c;以管理员身份打开windows控制台。 # 设置下载node安装包&#xff0c;和npm安装…

linux系统非关系型数据库redis常见问题以及好处

redis常见问题以及好处 redis常见问题缓存穿透概念解决方案布隆过滤器缓存空对象 缓存雪崩概念解决方案redis高可用限流降级数据预热 redis好处redis常见性能问题解决方案为redis加密 redis常见问题 缓存穿透 概念 缓存穿透的概念很简单&#xff0c;用户想要查询一个数据&am…

02-实现方法多值返回-pair与truple

在实际的项目开发中&#xff0c;我们经常会遇到返回多个值&#xff0c;通常我们使用Map对象、自定义Class对象等方式封装返回结果。但是这种方式&#xff0c;需要定义大量中间类&#xff0c;影响代码的整体质量。 spring 为我们提供了pair 双值与 triple 三值返回对象。 1、p…

二级C语言笔试6

(总分100,考试时间90分钟) 一、选择题 1. 设有以下语句&#xff1a; charx3&#xff0c;y6&#xff0c;z&#xff1b; zx^y&#xff1c;&#xff1c;2&#xff1b; 则z的二进制值是( )。 A. 00010100 B. 00011011 C. 00011100 D. 00011000 …

从Unity到Three.js(画线组件line)

JavaScript 0基础&#xff0c;只是照着官方文档临摹了下&#xff0c;之后有时间再进行细节学习和功能封装。 import * as THREE from three; //引入threejsconst renderer new THREE.WebGLRenderer();//创建渲染器 //设置渲染范围&#xff0c;当前撑满全屏,屏幕左上角是&…

C++类型转化cast from pointer to smaller type ‘int‘ loses information

代码如下 #include <iostream>int main() {int a 10;std::cout << (int)&a << std::endl;return 0; }编译 这段代码是要将地址转化成整数类型&#xff0c;但是在编译时编译器告诉我们这是错的&#xff0c;因为在C中&#xff0c;将指针转换为int类型的…

Spring IoC容器详解

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 基本概念 Spring IoC容器是Spring框架的核心组件&#xff0c;它实现了控制反转&#xff08;Inversion of Control&#xff0c;IoC&#xff09;的设计原则。IoC是一种编程思…

【前端高频面试题--TypeScript篇】

&#x1f680; 作者 &#xff1a;“码上有前” &#x1f680; 文章简介 &#xff1a;前端高频面试题 &#x1f680; 欢迎小伙伴们 点赞&#x1f44d;、收藏⭐、留言&#x1f4ac; 高频前端面试题--Vue3.0篇 什么是TypeScript&#xff1f;TypeScript数据类型TypeScript中命名空…

最关键的十个图像特征

在计算机视觉中&#xff0c;图像特征是用来描述图像中视觉元素的一组属性&#xff0c;它们对于图像识别、分类、检测和分割等任务至关重要。以下是10个在计算机视觉中广泛使用的最重要的图像特征&#xff1a; 颜色直方图&#xff08;Color Histogram&#xff09;&#xff1a; 颜…

Days 27 ElfBoard 板 AltiumDesigner 相同电路快速布局布线

在进行设计开发的时候&#xff0c;总会遇到相同的电路&#xff0c;或者模块&#xff0c;这些电路可以使用相同的布局和走线&#xff0c;例如 DC-DC 电源、网口 PHY 电路部分。这类型的电路&#xff0c;我们可以采用AltiumDesigner 中的 Room 进行布局和布线的快速复制&#xff…

C#系列-并行处理+异步流(5)

一&#xff0c;C#并行处理 在C#中&#xff0c;并行处理指的是同时执行多个任务或操作&#xff0c;以利用多核或多处理器的优势&#xff0c;从而提高应用程序的性能。C#提供了多种工具和框架来帮助开发者实现并行处理。以下是一些在C#中实现并行处理的方法&#xff1a; Paralle…

VitePress-12-markdown中使用vue的语法

前言 VitePress 中&#xff0c;markdown文档最终都会转换成为 html文件&#xff0c;我们在访问的时候&#xff0c;也是直接访问的 xxx.html 文件。而且&#xff0c;markdown文档会被作为 [vue单文件] 进行处理&#xff0c;因此&#xff0c;我们我们可以在文档中使用 vue 语法&…

决策树之scikit-learn

实例 from sklearn.datasets import load_iris from sklearn import tree import matplotlib.pyplot as plt# Load iris dataset iris load_iris() X, y iris.data, iris.target# Fit the classifier clf tree.DecisionTreeClassifier() clf clf.fit(X, y)# Plot the deci…

Linux命令-batch命令(在系统不繁忙的时候执行定时任务)

说明 batch命令 用于在指定时间&#xff0c;当系统不繁忙时执行任务&#xff0c;用法与at相似。 语法 batch(选项)(参数)选项 -f&#xff1a;指定包含具体指令的任务文件&#xff1b; -q&#xff1a;指定新任务的队列名称&#xff1b; -m&#xff1a;任务执行完后向用户发送…

详细介绍Python网络编程模块

根据前面对网络分层棋型的介绍&#xff0c;我们知道实际的网络模型大致分为四层&#xff0c;这四层各有对应的网络协议提供支持&#xff0c; 网络层协议主要是 IP&#xff0c;它是所有互联网协议的基础&#xff0c;其中 ICMP&#xff08;Internet Control Message Protocol&…

烟雨要饭网带后台,附带搭建教程

直接上传访问即可&#xff0c;有安装向导&#xff0c;php环境不得低于7.0 后台地址/Admin&#xff0c;默认账号admin 默认密码123456 自带乞讨音乐&#xff0c;增加樱花特效

域内NAT:如何让内网client通过公网地址访问内网server?

第一步&#xff0c;实现任意公网用户访问内网server。按教育网规矩&#xff0c;公网过来的流量要访问校内网的server必须从教育专线&#xff08;路由器接口G0/0/1)进入。 第二步&#xff0c;实现内网主机通过公网地址210.43.2.3能够访问内网server192.168.1.2&#xff0c;图中①…

C++ 类和对象篇(九) 初始化列表

目录 一、什么是初始化列表&#xff1f; 二、为什么需要初始化列表&#xff1f; 三、初始化列表怎么使用&#xff1f; 3.1 在构造函数中使用初始化列表 3.2 注意 3.3 结论 3.4 应用场景 四、初始化列表的初始化顺序 五、另一种初始化成员变量的方法 【总结 一、什么是初始化列…

12.05 校招 实习 内推 面经

绿*泡*泡VX&#xff1a; neituijunsir 交流裙 &#xff0c;内推/实习/校招汇总表格 1、校招 | 吉利控股集团2024届全球校园招聘补招岗位发布&#xff08;内推&#xff09; 校招 | 吉利控股集团2024届全球校园招聘补招岗位发布&#xff08;内推&#xff09; 2、校招 | 浪潮科…