美文网首页
树及二叉树

树及二叉树

作者: Carrism | 来源:发表于2017-03-30 14:35 被阅读9次

    树:

    1 概念

    • 定义:树是节点的有限集合
    • :当前双亲的直接孩子个数
    • 叶子:终端节点(度为0)就是叶子
    • :非终端节点
    • 有序树:树当中的节点之间位置不可以互换
    • 无序树:树当中节点之间位置可以互换
    • 深度之节点深度:当前节点所在第几层即为节点深度
    • 深度之树的深度:该树最大的节点深度

    2 二叉树:

    • 定义:所有结点的度都小于等于2

    3 二叉搜索树

    • 定义:所有结点的度都小于或等于2,并且当前结点值一定是大于左孩子结点值,小于右孩子结点值
    • 遍历:最后得到的遍历序列是一个有序序列

    4 二叉树的遍历:

    • 二叉树当中按照根的遍历顺序分为以下3种遍历方式
                 1(0)
                 
         3(1)           5(2)
            
            
    10(3)   26(4)  19(5)   27(6)
    
    • 前序遍历:根->左->右: 1->3->10->26->5->19->27
    • 中序遍历:左->根->右: 10->3->26->1->19->5->27
    • 后序遍历:左->右->根 10->26->3->19->27->5->1

    5 树的用途

    • 压缩软件-赫夫曼树
    • 人机对战

    6 二叉树的常用操作

    • 创建树
    • 销毁树
    • 根据下标搜索结点
    • 往某个结点某个孩子添加结点
    • 删除某个结点
    • 二叉树的深度
    • 二叉树结点个数

    7 二叉树双向链表代码实现

    • 1 创建结点类TreeNode
            //该结点所在的下标
            private int index;
            //该结点实际存储的数据
            private T data;
            //该结点下的左孩子
            private TreeNode<T> leftNode;
            //该结点下的右孩子
            private TreeNode<T> rightNode;
            //该结点对应的父结点
            private TreeNode<T> parentNode;
    
            //属性 
            public T Data{set{ data = value;
                }get{ return data;}}
    
            public TreeNode<T> LeftNode{
                set{ 
                    leftNode = value;
                }
                get{ 
                    return leftNode;
                }
            }
    
            public TreeNode<T> RightNode{
                set{ 
                    rightNode = value;
                }
                get{ 
                    return rightNode;
                }
            }
    
            public TreeNode<T> ParentNode{
                set{ 
                    parentNode = value;
                }
                get{ 
                    return parentNode;
                }
            }
    
            public int Index{
                set{ 
                    index = value;
                }
                get{ 
                    return index;
                }
            }
            //常用构造
            public TreeNode ()
            {
                index = 0;
                data = default(T);
                leftNode = null;
                rightNode = null;
                parentNode = null;
            }
    
            public TreeNode(int index,T data){
                this.index = index;
                this.data = data;
                leftNode = null;
                rightNode = null;
                parentNode = null;
            }
    
            //使用递归来判断该下标的结点是否存在于该结点之下
            public TreeNode<T> NodeAtIndex(int index){
                //(1)  首先判断是否为该结点
                if (index == this.index) {
                    return this;
                } 
                //(2)若不是则遍历该结点下的左右孩子,依次进行遍历下去
                TreeNode<T> temp = null;
                if (this.LeftNode != null) {
                    temp = this.LeftNode.NodeAtIndex (index);
                }
                if (temp == null) {
                    if(this.RightNode != null) {
                        temp = this.RightNode.NodeAtIndex (index);
                    }
                }
                return temp;
    
            }
    
            //删除本身结点以及该结点下的子结点
            public void DeleteNode(){
                //(1)判断该结点是否存在左右孩子,若有的话同样进行删除(使用递归)
                if(this.LeftNode != null){
                    this.LeftNode.DeleteNode ();
                }
                if (this.RightNode != null) {
                    this.RightNode.DeleteNode ();
                }
                //判断该结点是属于双亲结点的左孩子还是右孩子,删除掉双亲对应的孩子 
                if (this.ParentNode != null) {
                    if (this.ParentNode.LeftNode == this) {
                        this.ParentNode.LeftNode = null;
                    }
                    if (this.ParentNode.RightNode == this) {
                        this.ParentNode.RightNode = null;
                    }
                }
            }
    
            //使用递归该结点下的所有结点进行前序遍历
            public void PreordeTraversal(){
                    /*思路:遍历该结点下以及左右孩子(左右孩子存在的时候)
                            对于左右孩子则视为某些结点的双亲再进行前序遍历
                    */
                Console.WriteLine("index = {0},data = {1}  ",Index,Data);
                if (this.LeftNode != null) {
                    this.LeftNode.PreordeTraversal();
                }
                if (this.RightNode != null) {
                    this.RightNode.PreordeTraversal ();
                }
            }
    
            //该结点下的所有结点进行中序遍历
            public void InorderTraversal(){
                /*思路同前序遍历,顺序调整为中,左,右*/
                if (this.LeftNode != null) {
                    this.LeftNode.InorderTraversal();
                }
                Console.WriteLine("index = {0},data = {1}  ",Index,Data);
    
                if (this.RightNode != null) {
                    this.RightNode.InorderTraversal ();
                }
            }
            //该结点下的所有结点进行后序遍历
            public void PostorderTraversal(){
                /*思路同前序遍历,顺序调整为左,右,中*/
                if (this.LeftNode != null) {
                    this.LeftNode.PostorderTraversal ();
                }
                if (this.RightNode != null) {
                    this.RightNode.PostorderTraversal ();
                }
                Console.WriteLine("index = {0},data = {1}  ",Index,Data);
            }
    
            //该结点的子结点包括该结点总共有几个结点
            public int CountOFChildNode(){
                int count = 0;
                if(this.LeftNode != null){
                    count += this.LeftNode.CountOFChildNode ();
                }
                if (this.RightNode != null) {
                    count += this.RightNode.CountOFChildNode ();
                }
                //返回之前进行++操作是将本身添加进去
                return ++count;
            }
    
            //某个结点的最大深度
            public int Depth(){
                int leftDepth = 0,rightDepth = 0;
                if(this.LeftNode != null){
                    leftDepth = this.LeftNode.Depth ();
                }
                if (this.RightNode != null) {
                    rightDepth = this.RightNode.Depth ();
                }
                return (leftDepth > rightDepth ? leftDepth : rightDepth) + 1;
            }
    
    • 2 创建二叉树类BinaryTree<T>
            //根结点
            public TreeNode<T> rootNode;
            //构造方法,在创建树的时候对根结点进行初始化
            public BinaryTree ()
            {
                rootNode = new TreeNode<T> ();
            }
    
            //根据某个下标返回对应的结点 
            public TreeNode<T> NodeAtIndex(int index){
                return rootNode.NodeAtIndex(index);
            }
    
            //在下标为index添加一个结点node,direction为0表示左孩子,为1表示右孩子
            public bool AddNode(int index,int direction,TreeNode<T> node){
                //先判断index对应的结点是否存在,不存在则没法挂载
                TreeNode<T> temp = NodeAtIndex(index);
                if (temp == null) {
                    return false;
                }
                //若是该结点存在则将要挂载的结点拷贝一份出来
                TreeNode<T> newNode = new TreeNode<T>();
                newNode.Index = node.Index;
                newNode.Data = node.Data;
                newNode.ParentNode = temp;
                if (direction == 0) {
                    temp.LeftNode = newNode;
                }
                if (direction == 1) {
                    temp.RightNode = newNode;
                }
                return true;
            }
    
            //根据下标删除一个结点
            public bool DeleteNode(int index){
                TreeNode<T> temp = NodeAtIndex(index);
                if (temp == null) {
                    return false;
                }
    
                if (temp.ParentNode.LeftNode ==temp) {
                    temp.ParentNode.LeftNode = null;
                } else if (temp.ParentNode.RightNode == temp) {
                    temp.ParentNode.RightNode = null;
                }
                temp.DeleteNode ();
                return true;
            }
    
            //二叉树的深度
            public int DepthOfTree(){
                return rootNode.Depth();
            }
             
            //树的某个结点下子结点个数(包括该结点)
            public int CountOfNode(TreeNode<T> node){
                if (rootNode == null) {
                    return 0;
                } else {
                    return rootNode.CountOFChildNode ();
                }
            }
    
            //前序遍历
            public void PreordeTraversal(){
                rootNode.PreordeTraversal();
            }
            //中序遍历
            public void InorderTraversal(){
                rootNode.InorderTraversal();
            }
            //后序遍历
            public void PostorderTraversal(){
                rootNode.PostorderTraversal();
            }
    
    • 3 使用二叉树
                0
            1       2
        3    4  5     6
      7  8 9
                前序遍历:根左右: 0 1 3 7 8 4 9 2 5 6
                后序遍历:左右根:7 8 3 9 4 1 5 6 2 0
                中序遍历:左根右:7 3 8 1 9 4 0 5 2 6
    
    • 代码实现
    //创建结点
    BinaryTree<string> btTree = new BinaryTree<string> ();
                TreeNode<string> node0 = new TreeNode<string> (1, "node0");
                TreeNode<string> node1 = new TreeNode<string> (2, "node1");
                TreeNode<string> node2 = new TreeNode<string> (3, "node2");
                TreeNode<string> node3 = new TreeNode<string> (4, "node3");
                TreeNode<string> node4 = new TreeNode<string> (5, "node4");
                TreeNode<string> node5 = new TreeNode<string> (6, "node5");
                TreeNode<string> node6 = new TreeNode<string> (7, "node6");
                TreeNode<string> node7 = new TreeNode<string> (8, "node7");
                TreeNode<string> node8 = new TreeNode<string> (9, "node8");
                //添加结点
                btTree.AddNode (0, 0, node0);
                btTree.AddNode (0, 1, node1);
                btTree.AddNode (1, 0, node2);
                btTree.AddNode (1, 1, node3);
                btTree.AddNode (2, 0, node4);
                btTree.AddNode (2, 1, node5);
                btTree.AddNode (3, 0, node6);
                btTree.AddNode (3, 1, node7);
                btTree.AddNode (4, 0, node8);
                //删除结点
                btTree.DeleteNode (3);
                btTree.DeleteNode (4);
                //结点个数
                Console.WriteLine ("count = {0}", btTree.CountOfNode (btTree.rootNode));
                Console.WriteLine ("树的深度 = {0}", btTree.DepthOfTree ());
                //某个下标下的结点
                Console.WriteLine (btTree.NodeAtIndex (6).Data);
                //前序遍历
                btTree.PreordeTraversal ();
                //后序遍历
                btTree.PostorderTraversal();
                //中序遍历
                btTree.InorderTraversal();
    

    相关文章

      网友评论

          本文标题:树及二叉树

          本文链接:https://www.haomeiwen.com/subject/zitpottx.html