首页 > 编程语言 >C#数据结构之Tree

C#数据结构之Tree

时间:2023-09-03 14:34:13浏览次数:35  
标签:node null C# Tree 节点 BinaryTreeNode result 数据结构 public

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

namespace AlgorithmsDemo
{
    public class TreeNode<T>
    {
        public T Data { get; set; }
        public List<TreeNode<T>> Children { get; set; } 
        
    }
    public class Tree<T>
    {
        public TreeNode<T> Root { get; set; }
    }

    //
    public class BinaryTreeNode<T> : TreeNode<T>
    {
        public BinaryTreeNode()
        {
            Children = new List<TreeNode<T>>() { null, null };
        }
        public  BinaryTreeNode<T> Parent { get; set; }

        public BinaryTreeNode<T> Left
        {
            get
            {
                return (BinaryTreeNode<T>)Children[0];
            }
            set
            {
                Children[0] = value;
            }
        }
        public BinaryTreeNode<T> Right
        {
            get
            {
                return (BinaryTreeNode<T>)Children[1];
            }
            set
            {
                Children[1] = value;
            }
        }
        public int GetHeight()
        {
            int height = 1;
            BinaryTreeNode<T> current = this;
            while (current.Parent != null)
            {
                height++;
                current = current.Parent;
            }
            return height;
        }
    }
    /// <summary>
    /// 二叉树遍历类型
    /// </summary>
    public enum TranversalEnum
    {
        PREORDER,
        INORDER,
        POSTORDER,
    }

    public class BinaryTree<T>
    {
        public BinaryTreeNode<T> Root { get; set; }
        /// <summary>
        /// 二叉树所有节点数量
        /// </summary>
        public int Count { get; set; }

        private void TranversePreOrder(BinaryTreeNode<T> node,List<BinaryTreeNode<T>> result)
        {
            if(node != null)
            {
                result.Add(node);//前序遍历
                TranversePreOrder(node.Left, result);
                TranversePreOrder(node.Right, result);
            }
        }
        private void TranverseInOrder(BinaryTreeNode<T> node,List<BinaryTreeNode<T>> result)
        {
            if(node != null)
            {
                TranverseInOrder(node.Left, result);
                result.Add(node);
                TranverseInOrder(node.Right, result);
            }
        }
        private void TranversePostOrder(BinaryTreeNode<T>node,List<BinaryTreeNode<T>> result)
        {
            if(node != null)
            {
                TranversePostOrder(node.Left,result);
                TranversePostOrder(node.Right, result);
                result.Add(node);
            }
        }
        /// <summary>
        /// 遍历
        /// </summary>
        /// <param name="mode"></param>
        /// <returns></returns>
        public List<BinaryTreeNode<T>> Tranverse(TranversalEnum mode)
        {
            List<BinaryTreeNode<T>> nodes = new List<BinaryTreeNode<T>>();
            switch (mode)
            {
                case TranversalEnum.PREORDER:
                    TranversePreOrder(Root, nodes);
                    break;
                case TranversalEnum.INORDER:
                    TranverseInOrder(Root, nodes);
                    break;
                case TranversalEnum.POSTORDER:
                    TranversePostOrder(Root, nodes);
                    break;
            }
            return nodes;
        }
        public int GetHeight()
        {
            int height = 0;
            foreach(var node in Tranverse(TranversalEnum.PREORDER))
            {
                height = Math.Max(height, node.GetHeight());
            }
            return height;
        }

    }

    public class BinarySearchTree<T> : BinaryTree<T> where T:IComparable
    {
        public bool Contains(T data)
        {
            BinaryTreeNode<T> node = Root;
            while(node != null)
            {
                int result = data.CompareTo(node.Data);
                if (result == 0)
                {
                    return true;
                }
                else if (result < 0)
                {
                    node = node.Left;
                }
                else
                {
                    node = node.Right;
                }
            }
            return false;
        }
        private BinaryTreeNode<T> GetParentForNewNode(T data)
        {
            BinaryTreeNode<T> current = Root;
            BinaryTreeNode<T> parent = null;
            while(current != null)
            {
                parent = current;
                int result = data.CompareTo(current.Data);
                if (result == 0)
                {
                    throw new ArgumentException($"The node {data} already exists");
                }
                else if (result < 0)
                {
                    current = current.Left;
                }
                else
                {
                    current = current.Right;
                }
            }

            return parent;
        }
        public void Add(T data)
        {
            BinaryTreeNode<T> parent=GetParentForNewNode(data);
            BinaryTreeNode<T> node = new BinaryTreeNode<T>() { Data=data,Parent=parent};
            if (parent == null)
            {
                Root = node;
            }
            else if (data.CompareTo(parent.Data) < 0)
            {
                parent.Left = node;
            }
            else
            {
                parent.Right = node;
            }
            Count++;
        }
        public void Remove(T data)
        {

        }
        /// <summary>
        /// 从以根节点未node的树中,移除含有data的节点
        /// </summary>
        /// <param name="node"></param>
        /// <param name="data"></param>
        /// <exception cref="ArgumentException"></exception>
        private void Remove(BinaryTreeNode<T> node,T data)
        {
            if (node == null)
            {
                throw new ArgumentException($"The node {data} does not exist");
            }
            else if (data.CompareTo(node.Data) < 0)
            {
                Remove(node.Left, data);
            }
            else if (data.CompareTo(node.Data) > 0)
            {
                Remove(node.Right, data);
            }
            else //移除的节点找到了
            {
                if(node.Left==null && node.Right == null)
                {
                    //是叶节点,将该节点替换为null
                    ReplaceInParent(node, null);
                    Count--;
                }
                else if (node.Right == null)
                {
                    //右节点为空,用该节点的左节点替换该节点
                    ReplaceInParent(node,node.Left);
                    Count--;
                }
                else if (node.Left == null)
                {
                    //左节点为空,用改节点的右节点替换该节点
                    ReplaceInParent(node, node.Right);
                    Count--;

                }
                else
                {
                    //左右节点都不为空,找到以该节点的右节点为根节点的子树的最小节点,
                    //将上述最小节点的值替换到该节点的值,然后再移除最小节点上的数据。
                    BinaryTreeNode<T> succor = FindMininumInSubTree(node.Right);
                    //succor的左节点一定是null,后续Remove方法,一定进入左节点是空的分支。
                    node.Data=succor.Data;
                    Remove(succor, succor.Data);//
                }
            }
        }
        /// <summary>
        /// 替换节点,删除node,用newNode来替换node
        /// </summary>
        /// <param name="node"></param>
        /// <param name="newNode"></param>
        private void ReplaceInParent(BinaryTreeNode<T> node,BinaryTreeNode<T> newNode)
        {
            //首先变更node.Parent中含有的对node的信息
            if (node.Parent != null)
            {
                if (node.Parent.Left == node)
                {
                    node.Parent.Left = newNode;
                }
                else
                {
                    node.Parent.Right = newNode;
                }
            }
            else
            {
                Root = newNode;
            }
            //再变更newNode中有关Parent的信息
            if(newNode != null)
            {
                newNode.Parent = node.Parent;
            }
        }
        /// <summary>
        /// 找到以node为根节点的子树的最小节点
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        private BinaryTreeNode<T> FindMininumInSubTree(BinaryTreeNode<T> node)
        {
            while(node.Left != null)
            {
                node= node.Left;
            }
            return node;
        }

    }
    

}

标签:node,null,C#,Tree,节点,BinaryTreeNode,result,数据结构,public
From: https://www.cnblogs.com/johnyang/p/17674945.html

相关文章

  • Docker构建Jenkins
    拉取jenkins的docker镜像,这里用的是lts的长期支持版本,你可以到jenkins官网自由选择其他版本(下载速度慢,花了两个小时,如果中途出现超时再次运行该命令即可)dockerpulljenkins/jenkins:lts配置宿主机映射到容器的目录,之后jenkins的一些配置文件......
  • 无涯教程-JavaScript - QUARTILE函数
    QUARTILE函数取代了Excel2010中的QUARTILE.INC函数。描述该函数返回数据集的四分位数。四分位数通常用于销售和调查数据中,以将人群分为几类。语法QUARTILE(array,quart)争论Argument描述Required/OptionalArrayThearrayorcellrangeofnumericvaluesforwhi......
  • What's the best approach for generating a new API key?
    https://stackoverflow.com/questions/14412132/whats-the-best-approach-for-generating-a-new-api-keyEdit:I'vespoketoafewfriends(email/twitter)andtheyrecommendedjustusingaGUIDwiththedashesstripped.......
  • JS基础-初识JavaScript
    前面讲了前端开发必备的三种语言。其中的HTML、CSS我们基本上有了比较正确的认识。这里讲一下JavaScript。语言功能结构层HTML搭建结构、放置部件、描述定义样式层CSS美化页面、实现布局行为层JavaScript实现交互效果、数据收发、表单验证HTML构成了......
  • 安装archlinux 使用sway
    https://blog.csdn.net/xinxiaoyu_/article/details/129257241参考上述成功安装archlinux制作启动盘参考我上一篇文章下载archlinuxiso放置启动盘内进入启动盘,直接选择archlinuxiso选择第一个进入命令行建议插网线操作 方便些,可以直接联网规划盘(分区)用工具fdisk进行分......
  • 无涯教程-JavaScript - PERCENTRANK函数
    PERCENTRANK函数取代了Excel2010中的PERCENTRANK.INC函数。描述该函数以数据集的百分比形式返回数据集中的值的排名。此功能可用于判断数据集中值的相对位置。语法PERCENTRANK(array,x,[significance])争论Argument描述Required/OptionalArrayThearrayorrangeo......
  • Linux--安装部署Docker
    Docker介绍Docker理解Docker是基于Go语言实现的开源容器项目,专业的叫法是应用容器一次封装、到处运行对应用封装、分发、部署、运行的生命周期进行管理应用组件:Web应用、数据库平台、操作系统、集群为应用的开发、运行和部署提供一站式的使用解决方案Docker优势Docker容器好比一......
  • C语言自增++放前面还是后面?
    《STL标准程序》里边一直提到前置比后置效率更高。关于此的一点个人理解记录下来。a++:加的过程中要先产生一个临时变量temp,加1之后的值赋给temp,然后你可以使用a(在if、for、while..中),最后再把temp的值assign给a。++a:这个就是直接在a上加1了,然后改怎么用,就怎么用。归根结底:二者的......
  • 2018 ACM-ICPC 亚洲青岛区域网络赛
    A.LiveLove#include"bits/stdc++.h"usingnamespacestd;usingi64=longlong;voidsolve(){intn,m;cin>>n>>m;cout<<m<<''<<n/(n-m+1)<<'\n';}int......
  • C++算法之旅、05 基础篇 | 第二章 数据结构
    常用代码模板2——数据结构-AcWing笔试用数组模拟而不是结构体使用结构体指针,newNode()非常慢,创建10万个节点就超时了,做笔试题不会用这种方式(优化是提前初始化好数组,但这样跟数组模拟没区别了,而且代码量很长)单链表(数组)使用两个数组,e存储val,ne存储next。空节点next用-1表......