zoukankan      html  css  js  c++  java
  • Tree

    Tree:典型的数据结构属于一种阶层性非线性结,由一个或者一个之上节点组成有限集合,节点之间串联不会组成环,就叫树

    度:子树个数该节点的度,包括从自己开始到其所在的叶子节点。在树种不是二叉树的树,树中

    有些节点的子节点不一样的:为了极大化利用其存储空间,采用下列的存储格式,左边表示其子节点,右边表示其兄弟节点,儿子--兄弟表示方法,类似于二叉树结构。

    二叉树:二叉树最多只能有2个节点的树,是一种典型的树结构不同于其他的树,度不超过2的树.

    二叉树的性质:

    *.第I层有做多2^(I-1)个节点

    *。深度为K的二叉树的总节点(2^K)-1

    *。叶子节点数N0,度为2节点数N2,度为1节点数N1: 总的边数:N0+N1+N2-1=0*N0+1*N1+2*N2

    得出:N0=N2+1;

    二叉树常被用于实现二叉查找树和二叉堆。

    二叉排序树规则:大于父节点左右子树,左子树小于树根

    1.满二叉树:树高度为,节点数2^H-1,节点编号按照从左到右从上到下的编号排序

    2.完全二叉树:节点编号按照从左到右从上到下的编号排序,堆排序采用完全二叉树,堆采用完全二叉树,树按照大小排序。,中间没有阙短

    每一次堆被打破之后对堆进行调整,堆排序

    3.平衡二叉树AVL树:红黑树AVL树、Treap等;

    Problem:二叉排序树 Vs 堆

    二叉排序树:左子树值比根节点小,右子树比根节点大,右子比左子树大,二叉排序树 为了动态的数据查找设计一种数据结构,在二叉排序树中查找一个结点的平均时间复杂度是O(log n)。

    堆:父节点值大于(小于)子节点值,并没有规定左右节点值大小。为了排序设计一种数据结构,在堆中查找一个节点平均时间复杂度(o(n))

    一。二叉树的遍历(按照由左往右方式):按照树根的位置不同进行的命名,按照先左后右的结果

    前序遍历:树根---左子树----右子树

    中序遍历:左子树----树根---右子树,左--父--右---父的父节点

    后序遍历:左子树----右子树---树根

    最重要:Cout输出位置不同

    中序遍历:从树根开始一直往左子树行走到底,遍历顺序一样从根到叶子节点,最重要的是调节输出顺序。

    package BinaryTree;
    //采用链表建立二叉排序树
    
    public class binaryTree {
        public TreeNode rootNode;//二叉树的根节点
        //构造初始化
        public binaryTree(int [] data)
        {
            for(int i=0;i<data.length;i++)
            {
                Add_Node_to_Tree(data[i]);
            }
        }
        public void Add_Node_to_Tree(int value){
            //通过定义一个根节点对树进行记录
            TreeNode currentNode=rootNode;
            TreeNode tmp=new TreeNode(value);
            if(rootNode==null)
            {
                rootNode=new TreeNode(value);
                return;
            }
            //按照规则左子树值比根节点小,右子树比根节点大
            while(true)
            {
                //不断进行插入
                if(currentNode.value>value)
                {
                    //没有堆这样的严格,只需要子节点与父节点局部符合要求,并不是AVL树或者堆,堆必须要整体要求
                    //父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值,二叉树并没有这种要求
                    if(currentNode.LeftNode==null)
                    {
                        currentNode.LeftNode=tmp;
                        return;
                    }else
                        currentNode=currentNode.LeftNode;
                }
                else
                {
                    if(currentNode.RightNode==null)
                    {
                        currentNode.RightNode=tmp;
                        return;
                    }else
                        currentNode=currentNode.RightNode;
                }
                
            }
        }
        //前序遍历,递归调用顺序一样最重要的是输出的顺序不一样
        public void PreOrder(TreeNode node)
        {
            if(node!=null){
                //输出的结果
                System.out.print("["+node.value+"]");
                PreOrder(node.LeftNode);
                PreOrder(node.RightNode);
            }
        }
        //中序遍历
        public void InOrder(TreeNode node)
        {
            if(node!=null){
                //输出的结果
                
                InOrder(node.LeftNode);
                System.out.print("["+node.value+"]");
                InOrder(node.RightNode);
            }
        }
        public void PostOrder(TreeNode node)
        {
            if(node!=null){
                //输出的结果
                
                PostOrder(node.LeftNode);
                
                PostOrder(node.RightNode);
                System.out.print("["+node.value+"]");
            }
        }
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            int []arr={7,4,1,5,16,8,11,12,15,9,2};
            int i;
            
            binaryTree Tree=new binaryTree(arr);
            
            System.out.println("前序遍历结果");
            Tree.PreOrder(Tree.rootNode);
            System.out.println();
            
            System.out.println("中序遍历结果");
            Tree.InOrder(Tree.rootNode);
            System.out.println();
            
            System.out.println("后序遍历结果");
            Tree.PostOrder(Tree.rootNode);
            System.out.println();
        }
    
    }
    class TreeNode{
        int value;
        TreeNode LeftNode;
        TreeNode RightNode;
        
        //构造函数
        public TreeNode(int value)
        {
            this.value=value;
            this.LeftNode=null;
            this.RightNode=null;
        }
    }
    1 前序遍历结果
    2 [7][4][1][2][5][16][8][11][9][12][15]
    3 中序遍历结果
    4 [1][2][4][5][7][8][9][11][12][15][16]
    5 后序遍历结果
    6 [2][1][5][4][9][15][12][11][8][16][7]

     

     在C 语言中递归调用建立二叉树,此种递归的调用二叉树是前序遍历的方式:

    函数参数传替方式:采用引用传递,其他传递:按值传递(对实参没有影响),指针传递(地址传递)会修改实参的值果在函数中反复利用指针进行间接访问,会使程序容易产生错误且难以阅读。

    引用传递:,既可以使得对形参任何操作都能修改其相应的结构,同时调用方式自然。

    #include<cstdio>
    #include<iostream>
    #include<stack>
    #include<queue>
    using namespace std;
    #define  ElementType char
    
    //typedef struct TreeNode *BinTree;//为新的结构体TreeNode取新的名字BinTree
     typedef struct TreeNode {
        ElementType Data;
    
        struct TreeNode   *Left;
        struct TreeNode  * Right;
        //构造函数
    }*BinTree,BinTNode ;
    //建立二叉树有两种方式,一种建立struct,第二种采用的开辟一个内存,通过malloc看到其中指针变化
    void CreateBinaryTree(BinTree &T)
    {
        
        //终于把这种递归调用的形式理解了,此种方式将数据以前序遍历的方式进行
        //数据结构的递归存储,从树根一直往左到其左叶子节点,在从左叶子节点访问其右节点
        //明显的前序递归调用建立二叉树。
        
        char CH;
        cin>>CH;
        if (CH=='.')
            T=NULL;
        else
        {
            T=new BinTNode;
            ;
    
            T->Data=CH;
            CreateBinaryTree(T->Left);
            CreateBinaryTree(T->Right);
        }
    }
    
    void Pre_Order(BinTree &T){
    //    cout<<"前序遍历"<<endl;
        //这里不能用指针
        if(T!=NULL){
            cout<<(T)->Data;
            Pre_Order((T)->Left);
            Pre_Order((T)->Right);
        }
    }
    //采用非递归的形式对数据进行中序遍历,Stack 
    void Pre_Order_not(BinTree &T)
    {//建立一个BinTree模板类型的堆栈
        stack<BinTree>S;
        
    
        //从树根一直遍历到左子树
        while(! S.empty()|| T)
        {
            while(T)
            {
                S.push(T);
                T=T->Left;
            }
            //S 中会保存其中的BinTree类型的堆栈
            if(!S.empty())
            {
                T=S.top();
                S.pop();
                cout<<T->Data;
                T=T->Right;
            }
        }
    }
    //层次遍历,使用队列进行
    void Levelordertravel(BinTree &T)
    {
        queue<BinTree>Q;
        if(!T) return;//空树返回
        Q.push(T);
    
        while(T && !Q.empty())
        {
            T=Q.front() ; 
        
            
            cout<<T->Data<<endl;
            if(T->Left) Q.push(T->Left);
            if (T->Right) Q.push(T->Right);
            Q.pop();
        }
    
    }
    int main()
    {
        BinTree rootNode=new BinTNode;
        CreateBinaryTree( rootNode);
        //使用的是指针函数
        Pre_Order(rootNode);
        cout<<endl;
        BinTree tmp=rootNode;
        Pre_Order_not(rootNode);
        //使用的是引用递归在其中修改值会摆实参值进行修改
        cout<<endl;
        Levelordertravel(tmp);
        return 0;
    }

     采用递归先序遍历建立二叉树Java代码,Java中内存模型函数传递按值传递,栈内存存储的是对象在堆内存中地址

    rootNode1节点通过断点调试可以看出最后可以用先序递归建立二叉树

    package BinaryTree;
    //采用链表建立二叉排序树
    
    import java.io.IOException;
    import java.util.Scanner;
    
    public class binaryTree {
        public TreeNode rootNode;//二叉树的根节点
        //构造初始化
        public static TreeNode rootNode1;//递归调用建立一般二叉树
        public binaryTree(int [] data)
        {
            for(int i=0;i<data.length;i++)
            {
                Add_Node_to_Tree(data[i]);
            }
            System.out.println("递归调用建立二叉树");
            //这里递归建立二叉树运用的是用先序遍历方式建立二叉树,从树根到最左叶节点。
            rootNode1=REcord(rootNode1);
        }
        public static TreeNode REcord(TreeNode node)
        {
            
                int ch;
                Scanner sc=new Scanner(System.in);
                System.out.println("Enter a char");
                 ch=sc.nextInt();
                System.out.println("read the char is:"+ch);
            
            
            if(ch==-1)
                { node=null;
                    //return;
                }
            else
            {    
                node=new TreeNode(ch);
            node.LeftNode=REcord(node.LeftNode);
            node.RightNode=    REcord(node.RightNode);
            }
            
                return node;
        }
        
        public void Add_Node_to_Tree(int value){
            //通过定义一个根节点对树进行记录
            TreeNode currentNode=rootNode;
            TreeNode tmp=new TreeNode(value);
            if(rootNode==null)
            {
                rootNode=new TreeNode(value);
                return;
            }
            //按照规则左子树值比根节点小,右子树比根节点大
            while(true)
            {
                //不断进行插入
                if(currentNode.value>value)
                {
                    //没有堆这样的严格,只需要子节点与父节点局部符合要求,并不是AVL树或者堆,堆必须要整体要求
                    //父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值,二叉树并没有这种要求
                    if(currentNode.LeftNode==null)
                    {
                        currentNode.LeftNode=tmp;
                        return;
                    }else
                        currentNode=currentNode.LeftNode;
                }
                else
                {
                    if(currentNode.RightNode==null)
                    {
                        currentNode.RightNode=tmp;
                        return;
                    }else
                        currentNode=currentNode.RightNode;
                }
                
            }
        }
        //前序遍历,递归调用顺序一样最重要的是输出的顺序不一样
        public void PreOrder(TreeNode node)
        {
            if(node!=null){
                //输出的结果
                System.out.print("["+node.value+"]");
                PreOrder(node.LeftNode);
                PreOrder(node.RightNode);
            }
        }
        //中序遍历
        public void InOrder(TreeNode node)
        {
            if(node!=null){
                //输出的结果
                
                InOrder(node.LeftNode);
                System.out.print("["+node.value+"]");
                InOrder(node.RightNode);
            }
        }
        public void PostOrder(TreeNode node)
        {
            if(node!=null){
                //输出的结果
                
                PostOrder(node.LeftNode);
                
                PostOrder(node.RightNode);
                System.out.print("["+node.value+"]");
            }
        }
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            int []arr={7,4,1,5,16,8,11,12,15,9,2};
            int i;
            
            binaryTree Tree=new binaryTree(arr);
            
            /*System.out.println("前序遍历结果");
            Tree.PreOrder(Tree.rootNode);
            System.out.println();
            
            System.out.println("中序遍历结果");
            Tree.InOrder(Tree.rootNode);
            System.out.println();
            
            System.out.println("后序遍历结果");
            Tree.PostOrder(Tree.rootNode);
            System.out.println();*/
        }
    
    }
    class TreeNode{
        int value;
        TreeNode LeftNode;
        TreeNode RightNode;
        
        //构造函数
        public TreeNode(int value)
        {
            this.value=value;
            this.LeftNode=null;
            this.RightNode=null;
        }
    }

     采用泛型接口的方式递归构建二叉树:递归建立树的时候采用的是前序遍历的方式对树进行规则的输入。层次遍历过程中使用队列方式,一层层的进行遍历模拟

    package Tree;
    
    import java.util.Scanner;
    
    //运用递归建立二叉树,递归采用前序遍历方式输入数据
    public class BinaryTree<AnyType> {
    @SuppressWarnings("rawtypes")
    public static Node rootNode; 
        private static class Node<AnyType>
        {
            AnyType value;
            Node<AnyType>Left;
            Node<AnyType>Right;
            
            public Node(AnyType v)
            {
                this.value=v;
                this.Left=null;
                this.Right=null;
            }
        }
        
        public BinaryTree(AnyType []arr)
        {
            AnyType Val;
            
                //通过递归建立
                rootNode=AddNode(rootNode);
            //System.out.println(rootNode.value);
            PreOrder(rootNode);
        }
        public void PreOrder(Node P)
        {
            if(P!=null)
            {
                System.out.print("["+P.value+"]");
                PreOrder(P.Left);
                PreOrder(P.Right);
            }
        }
        private  Node <AnyType>AddNode(Node node)
        {
            int Val;
            @SuppressWarnings("resource")
            Scanner sc=new Scanner(System.in);
            System.out.println("Enter a char");
            Val=sc.nextInt();
            System.out.println("read the char is:"+Val);
            if((int)Val!=-1)
            {
                node=new Node<>(Val);
                node.Left=AddNode(node.Left);
                node.Right=AddNode(node.Right);
            }
            else
            {
                node=null;
            }
            return node;
            
            
        }
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            Integer [] Arr={7,4,1,5,16,8,11,12,15,9,2,-1};
            
            @SuppressWarnings("unused")
            BinaryTree <Integer>Tree=new BinaryTree<Integer>(Arr);
        }
    
    }
  • 相关阅读:
    Java 中几种常用的线程池
    阿里巴巴java工程师面试经验详情
    设计模式-备忘录模式
    设计模式-职责链模式
    设计模式-中介者模式
    设计模式-解释器模式
    设计模式-观察者模式
    设计模式-迭代器模式
    设计模式-命令模式
    设计模式-模板方法模式
  • 原文地址:https://www.cnblogs.com/woainifanfan/p/6024796.html
Copyright © 2011-2022 走看看