C#数据结构-二叉树-链式存储结构

对比上一篇文章“顺序存储二叉树”,链式存储二叉树的优点是节省空间。

 

二叉树的性质:

1、在二叉树的第i层上至多有2i-1个节点(i>=1)。

2、深度为k的二叉树至多有2k-1个节点(k>=1)。

 

3、对任何一棵二叉树T,如果其终结点数为n0,度为2的节点数为n2,则n0=n2+1。

4、具有n个节点的完全二叉树的深度为log2n+1。

5、对于一棵有n个节点的完全二叉树的节点按层序编号,若完全二叉树中的某节点编号为i,则若有左孩子编号为2i,若有右孩子编号为2i+1,母亲节点为i/2。

 

在此记录下链式二叉树的实现方式 :

/// <summary>
    /// 树节点
    </summary>
    <typeparam name="T"></typeparam>
    public class TreeNode<T>
    {
        <summary>
         节点数据
        </summary>
        public T data { get; set; }
         左节点
        public TreeNode<T> leftChild {  右节点
        public TreeNode<T> rightChild { ; }

        public TreeNode()
        {
            data = default(T);
            leftChild = null;
            rightChild = ;
        }

         TreeNode(T item)
        {
            data = item;
            leftChild = ;
        }
    }
     二叉树 链表存储结构
    class LinkStorageBinaryTree<T> 树根节
        private TreeNode<T> head {  LinkStorageBinaryTree()
        {
            head =  LinkStorageBinaryTree(T val)
        {
            head = new TreeNode<T>(val);
        }
         获取左节点
        </summary>
        <param name="treeNode"></param>
        <returns></returns>
        public TreeNode<T> GetLeftNode(TreeNode<T> treeNode)
        {
            if (treeNode == )
                return ;
            return treeNode.leftChild;
        }
         获取右节点
        public TreeNode<T> GetRightNode(TreeNode<T> treeNode.rightChild;
        }
         获取根节点
        public TreeNode<T> GetRoot()
        {
             head;
        }
         插入左节点
        <param name="val"></param>
        <param name="node"></param>
        public TreeNode<T> AddLeftNode(T val,TreeNode<T> node)
        {
            if (node == throw new ArgumentNullException("参数错误");
            TreeNode<T> treeNode = (val);
            TreeNode<T> childNode = node.leftChild;
            treeNode.leftChild = childNode;
            node.leftChild = treeNode;
             treeNode;
        }

         插入右节点
        public TreeNode<T> AddRightNode(T val,1)"> node.rightChild;
            treeNode.rightChild = childNode;
            node.rightChild = treeNode;
        }
         删除当前节点的 左节点
        public TreeNode<T> DeleteLeftNode(TreeNode<T>null || node.leftChild == );
            TreeNode<T> leftChild = node.leftChild;
            node.leftChild =  leftChild;
        }

         删除当前节点的 右节点
        public TreeNode<T> DeleteRightNode(TreeNode<T>);
            TreeNode<T> rightChild = node.rightChild;
            node.rightChild =  rightChild;
        }

         先序遍历
        <param name="index"></param>
        void PreorderTraversal(TreeNode<T>//递归的终止条件
            if (head == )
            {
                Console.WriteLine(当前树为空);
                ;
            }
            if (node != )
            {
                Console.Write(node.data+ " );
                PreorderTraversal(node.leftChild);
                PreorderTraversal(node.rightChild);
            }
        }

         中序遍历
        void MiddlePrefaceTraversal(TreeNode<T>)
            {
                MiddlePrefaceTraversal(node.leftChild);

                Console.Write(node.data + );

                MiddlePrefaceTraversal(node.rightChild);
            }
        }

         后序遍历
        void AfterwordTraversal(TreeNode<T>)
            {
                AfterwordTraversal(node.leftChild);
                AfterwordTraversal(node.rightChild);
                Console.Write(node.data + );
            }
        }


        void LevelTraversal()
        {
            使用队列先入先出
            Queue<TreeNode<T>> queue = new Queue<TreeNode<T>>();
            queue.Enqueue(head);

            while (queue.Any())
            {
                TreeNode<T> item = queue.Dequeue();
                Console.Write(item.data +if (item.leftChild != )
                    queue.Enqueue(item.leftChild);
                if (item.rightChild != )
                    queue.Enqueue(item.rightChild);
            }
        }
         校验节点是否是叶子节点
        bool ValidLeafNode(TreeNode<T>);
            if (node.leftChild != null && node.rightChild != )
            {
                Console.WriteLine($节点 {node.data} 不是叶子节点false;
            }
            Console.WriteLine($节点 {node.data} 是叶子节点true;
        }
    }

遍历方式在顺序存储一文中已经用图表示过,在此不做重复说明。

现在测试下:

LinkStorageBinaryTree<string> linkStorageBinary = new LinkStorageBinaryTree<string>(A);
TreeNode<string> tree1 = linkStorageBinary.AddLeftNode(B,linkStorageBinary.GetRoot());
TreeNode<string> tree2 = linkStorageBinary.AddRightNode(Cstring> tree3 =linkStorageBinary.AddLeftNode(DEFG先序遍历
Console.Write(先序遍历:);
linkStorageBinary.PreorderTraversal(linkStorageBinary.GetRoot());
Console.WriteLine();

中序遍历
Console.Write(中序遍历:);
linkStorageBinary.MiddlePrefaceTraversal(linkStorageBinary.GetRoot());
Console.WriteLine();

后序遍历:);
linkStorageBinary.AfterwordTraversal(linkStorageBinary.GetRoot());
Console.WriteLine();

层次遍历
Console.Write(层次遍历:);
linkStorageBinary.LevelTraversal();

linkStorageBinary.ValidLeafNode(tree1);
linkStorageBinary.ValidLeafNode(tree3);
Console.ReadKey();

输出:

先序遍历:A B D E C F G
中序遍历:D B E A F C G
后序遍历:D E B F G C A
层次遍历:A B C D E F G 节点 B 不是叶子节点
节点 D 是叶子节点

 

相关文章

项目中经常遇到CSV文件的读写需求,其中的难点主要是CSV文件...
简介 本文的初衷是希望帮助那些有其它平台视觉算法开发经验的...
这篇文章主要简单记录一下C#项目的dll文件管理方法,以便后期...
在C#中的使用JSON序列化及反序列化时,推荐使用Json.NET——...
事件总线是对发布-订阅模式的一种实现,是一种集中式事件处理...
通用翻译API的HTTPS 地址为https://fanyi-api.baidu.com/api...