学习日志---二叉树概念与遍历(递归)

概念:

树,简单来说这种结构每个节点至多只有一个父节点,父节点可以有多个子节点。

树的内部概念:

结点:结点由数据元素和构造数据元素之间关系的指针组成。
    结点的度:结点所拥有的子树的个数称为该结点的度。
    叶结点:度为0的结点称为叶结点,叶结点也称作终端结点。
    分支结点:度不为0的结点称为分支结点,分支结点也称  作非终端结点。
    孩子结点:树中一个结点的子树的根结点称作这个结点的孩子结点。
    双亲结点:若树中某结点有孩子结点,则这个结点就称作它的孩子结点的双亲结点。
    兄弟结点:具有相同的双亲结点的结点称为兄弟结点。
    树的度:树中所有结点的度的最大值称为该树的度。
    结点的层次:从根结点到树中某结点所经路径上的分支数。
    树的深度:树中所有结点的层次的最大值称为该树的深度。
    无序树:树中任意一个结点的各孩子结点的排列没有严格次序的树称为无序树。
    有序树:树中任意一个结点的各孩子结点的排列有严格次序的树称为有序树。
    森林:m(m≥0)棵树的集合称为森林。

树的存储结构:

双亲表示法:数组实现,map的value表示的是父节点情况,缺点就是不容易找其孩子节点

孩子表示法:链表实现,指针指向孩子节点,缺点就是不容易找其双亲节点

双亲孩子表示法:用数组记录父节点,后面的接着跟链表,记录孩子节点的下标,弥补了以上两种不

孩子兄弟表示法:每个节点的下一整层都用一个链表表示。

详见附件的ppt。


二叉树:

二叉树的定义
    二叉树是n(n≥0)个结点构成的、每个结点最多只有两个子树的有序树
    满二叉树:在一棵二叉树中,如果所有分支结点都存在左子树和右子树,并且所有叶子结点都在同一层上。
    完全二叉树:如果一棵具有n个结点的二叉树的逻辑结构与满二叉树的前n个结点的逻辑结构相同

左边是满二叉树,右边是完全二叉树。

二叉树的性质:

性质1  若规定根结点的层次为0,则一棵非空二叉树的第i层上最多有2i(i≥0)个结点。
    性质2  若规定空二叉树树的深度为-1(即根结点的深度为0),则深度为k的二叉树的最大结点数是         2k+1-1(k≥-1)个。
   性质3  具有n个结点的完全二叉树的深度k为不超过log2(n+1)-1的最大整数。
   性质4  对于一棵非空的二叉树,如果叶结点个数为n0,度为2的结点数为n2,则有n0= n2+1。
   性质5  对于具有n个结点的完全二叉树,如果按照从上至下和从左至右的顺序对所有结点从0开始顺序编号,则对于序号为i的结点,有:
 (1)如果i>0,则序号为i结点的双亲结点的序号为 (i-1)/2(“/”表示整除);如果i=0,则序号为i结点为根结点,无双亲结点。
 (2)如果2×i+1<n,则序号为i结点的左孩子结点的序号为2×i+1;如果2×i+1≥n,则序号为i结点无左孩子结点。
 (3)如果2×i+2<n,则序号为i结点的右孩子结点的序号为2×i+2;如果2×i+2≥n,则序号为i结点无右孩子结点

二叉树的存储结构:

数组结构:存之前要先把二叉树补成完全二叉树,然后逐层编号。利用上述的性质找节点;

链表结构:分为有头指针和无头指针的,存左孩子和右孩子;

二叉树实现:

//二叉树结点类
public class BiTreeNode {
    private BiTreeNode leftChild; // 左孩子
    private BiTreeNode rightChild; // 右孩子
    private Object data; // 数据元素

    BiTreeNode() {
        this.leftChild = null;
        this.rightChild = null;
    }
    
    BiTreeNode(Object data,BiTreeNode leftNode,BiTreeNode rightNode)
    {
        this.data = data;
        this.leftChild = leftNode;
        this.rightChild = rightNode;
    }
    
    public BiTreeNode getLeftChild() {
        return leftChild;
    }

    public void setLeftChild(BiTreeNode leftChild) {
        this.leftChild = leftChild;
    }

    public BiTreeNode getRightChild() {
        return rightChild;
    }

    public void setRightChild(BiTreeNode rightChild) {
        this.rightChild = rightChild;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

}

//下面的是二叉树的初始化
public class BiTree {
    
    //一切的起源都是根节点
    private BiTreeNode  root;//根节点
    
    BiTree()
    {
        this.root = null;
    }
    //传进来两个子树,有两个子树的根节点构成该树根节点的左右子孩子
    //每个树最重要的是根节点,找到根节点即可以操作树
    BiTree(Object data,BiTree left,BiTree right)
    {
        BiTreeNode l,r;
        if(left==null)
        {
            l = null;
        }
        else
        {
           l=left.root; 
        }      
        if(right==null)
        {
            r = null;
        }
        else
        {
            r = right.root;
        }
        this.root = new BiTreeNode(data,l,r);
    }    
}

二叉树遍历

三种遍历算法分别为前序遍历(DLR)、中序遍历(LDR)和后序遍历(LRD)。

前中后可以记为根的位置;

还有一种是层次遍历,按每一层的由左至右依次遍历;

二叉树的层序遍历算法如下(使用队列的数据结构):
(1)初始化设置一个队列;
(2)把根结点指针入队列;
(3)当队列非空时,循环执行步骤(3.a)到步骤(3.c);
  (3.a)出队列取得当前队头结点,访问该结点;
  (3.b)若该结点的左孩子结点非空,则将该结点的左孩子结点指针入队列;
  (3.c)若该结点的右孩子结点非空,则将该结点的右孩子结点指针入队列;
(4)结束。

递归算法实现遍历:

import java.util.LinkedList;
import java.util.Queue;

public class Traverse {
   
    //前序遍历--递归算法
    public static void preOrder(BiTreeNode root,Visit visit)
    {
        if(root!=null)
        {
            visit.print(root.getData());
            preOrder(root.getLeftChild(),visit);
            preOrder(root.getRightChild(),visit);
        }
    }
    
    //中序遍历--递归算法
    public static void inOrder(BiTreeNode root,Visit visit)
    {
        if(root!=null)
        {
            inOrder(root.getLeftChild(),visit);
            visit.print(root.getData());
            inOrder(root.getRightChild(),visit);
        }
    }
    
    //后序遍历--递归算法
    public static void postOrder(BiTreeNode root,Visit visit)
    {
        if(root!=null)
        {
            postOrder(root.getLeftChild(),visit);
            postOrder(root.getRightChild(),visit);
            visit.print(root.getData());
        }
        
    }
    
    //层次遍历
    public static void levOrder(BiTreeNode root,Visit visit)
    {
       //这里要使用队列Queue
       Queue<BiTreeNode> queue = new LinkedList<BiTreeNode>();
       
       if(root==null)
       {
           return ;
       }
       BiTreeNode curr;
       queue.add(root);
       
       while(!queue.isEmpty())
       {
           curr = queue.remove();
           visit.print(curr.getData());
           if(curr.getLeftChild()!=null)
           {
              queue.add(curr.getLeftChild());   
           }
           if(curr.getRightChild()!=null)
           {
              queue.add(curr.getRightChild());   
           }
       }
       
    }
}

//打印节点信息类
public class Visit {
   
    public void print(Object item)
    {
        System.out.print(item+" ");
    }
}

打印二叉树的方法

//打印二叉树
    public static void printBiTree(BiTreeNode root,int level)
    {
        if(root!=null)
        {
            //先打印该层的下一层右侧的元素,
            printBiTree(root.getRightChild(),level+1);
            //打印完右侧之后,把当前的这个向后移动
            if(level!=0)
            {
                //输出6*(level-1)个空格
                for(int i=0;i<6*(level-1);i++)
                {
                    System.out.print(" ");
                }
                System.out.print("-----");
            }
            //打印这一层的数据
            System.out.println(root.getData());
            //再打印该层下一层左侧的数据
            printBiTree(root.getLeftChild(),level+1);
        }
    }
    //打印出的额效果如下:
                  -----F
        -----C
              -----E
        A
        -----B
                    -----G
              -----D

建立和查找指定元素的方法

    //建立二叉树的结点
    public static BiTreeNode getTreeNode(Object data,BiTreeNode left,BiTreeNode right)
    {
        BiTreeNode node = new BiTreeNode(data,left,right);
        return node;
    }
    
    //查找指定元素
    public static BiTreeNode search(BiTreeNode root,Object obj)
    {
        BiTreeNode node=null;
        if(root==null)
        {
            return null;
        }
        if(root.getData().equals(obj))
        {
            return root;
        }
        if(root.getLeftChild()!=null)
        {
            node = search(root.getLeftChild(),obj);
        }
        if(root.getRightChild()!=null)
        {
            node = search(root.getRightChild(),obj);
        }
        
        return node;
    }
    
}

测试类:

public class Test {
   
    public static BiTreeNode makeTree()
    {
        BiTreeNode b,c,d,e,f,g;
        g = BiTree.getTreeNode(new Character(‘G‘), null, null);
        d = BiTree.getTreeNode(new Character(‘D‘), null, g);
        b = BiTree.getTreeNode(new Character(‘B‘), d, null);
        e = BiTree.getTreeNode(new Character(‘E‘), null, null);
        f = BiTree.getTreeNode(new Character(‘F‘), null, null);
        c = BiTree.getTreeNode(new Character(‘C‘), e, f);
        return BiTree.getTreeNode(new Character(‘A‘), b, c);
    }
    
    public static void main(String[] args) {
        
        BiTreeNode root;
        BiTreeNode temp;
        
        Visit visit = new Visit();
        
        root = Test.makeTree();
        System.out.println("二叉树为:");
        BiTree.printBiTree(root, 0);
        System.out.println();
        
        System.out.println("前序遍历的序列是:");
        Traverse.preOrder(root, visit);
        System.out.println();
        
        System.out.println("中序遍历的序列是:");
        Traverse.inOrder(root, visit);
        System.out.println();
        
        System.out.println("后序遍历的序列是:");
        Traverse.postOrder(root, visit);
        System.out.println();
        
        System.out.println("层次遍历的序列是:");
        Traverse.levOrder(root, visit);
        System.out.println();
        
        temp = BiTree.search(root, new Character(‘T‘));
        if(temp!=null)
        {
            System.out.println(temp.getData());
        }
        else
        {
            System.out.println("没有找到指定元素!");
        }
    }

}
时间: 2024-10-10 10:09:12

学习日志---二叉树概念与遍历(递归)的相关文章

二叉树三种遍历递归及非递归实现(Java)

import java.util.Stack; //二叉树三种遍历递归及非递归实现(Java) public class Traverse { /******************定义二叉树**************************/ private final int MAX_SIZE = 10; //链式存储 public static class BinaryTreeNode { int mValue; BinaryTreeNode mLeft; BinaryTreeNode

算法学习笔记 二叉树和图遍历—深搜 DFS 与广搜 BFS

图的深搜与广搜 马上又要秋招了,赶紧复习下基础知识.这里复习下二叉树.图的深搜与广搜.从图的遍历说起,图的遍历方法有两种:深度优先遍历(Depth First Search), 广度优先遍历(Breadth First Search),其经典应用走迷宫.N皇后.二叉树遍历等.遍历即按某种顺序访问"图"中所有的节点,顺序分为: 深度优先(优先往深处走),用的数据结构是栈, 主要是递归实现: 广度优先(优先走最近的),用的数据结构是队列,主要是迭代实现: 对于深搜,由于递归往往可以方便的利

二叉树先序遍历 递归 非递归

先序遍历的操作如下: 1)访问根节点: 2)先序遍历左子树: 3)先序遍历右子树: 对应的递归算法如下: void PreOrder(Bitree T) { if (T != NULL) { visit(T); PreOrder(T->lchild); PreOrder(T->rchild); } } 对应的非递归算法如下: void PreOrder2(Bitree T) { //借助栈实现 InitStack(S); Bitree p = T; //初始化栈,p是遍历指针 while (p

二叉树中序遍历 递归 非递归

中序遍历的操作如下: 1)中序遍历左子树: 2)访问根节点: 3)中序遍历右子树: 对应的递归算法如下: void InOrder(Bitree T) { if (T != NULL) { InOrder(T->lchild); visit(T); InOrder(T->rchild); } } 对应的非递归算法如下: void InOrder2(Bitree T) { //借助栈实现 InitStack(S); Bitree p = T; //初始化栈,p是遍历指针 while (p ||

学习日志---非递归二叉树游标遍历(前中后层序)

实现: //二叉树类 public class MyBiTree { private MyBiTreeNode  root;//根节点 MyBiTree() { this.root = null; } MyBiTree(Object data,MyBiTree left,MyBiTree right) { MyBiTreeNode l,r; if(left==null) { l = null; } else {    l=left.root;  } if(right==null) { r = n

【C语言】【数据结构】菜鸟学习日志(四) 用二叉树实现非递归排序

唉,由于要备战考研,这篇博文可能是我这一年最后一次更新啦! 其实断断续续的也没有写很多,而且大多都是很初级.很简单的东西,没有和大家分享什么高阶的东西.这也正应了我们<菜鸟学习日志>的标题嘛! 不过说回来我还是很喜欢写博文的.一方面总结学到的知识,以后也可以自己看看别做了就忘了:另一方面,写博文也让我在学习的过程中更加认真,以免分享了错误的知识. 写的东西好不好呢是一说,好像有一些点击量,不过看的人估计也不多.只是我还算乐在其中吧! 大学生活说到底过得有点浪了,导致我苦逼地走向了考研的不归路-

Java学习(十八):二叉树的三种递归遍历

二叉树的三种递归遍历: 1 public class StudentNode 2 { 3 private String name; 4 5 private StudentNode leftNode; 6 7 private StudentNode rightNode; 8 9 public String getName() 10 { 11 return name; 12 } 13 14 public void setName(String name) 15 { 16 this.name = na

【数据结构学习】-二叉树的概念与遍历

链表.栈或队列都是线性结构,包含一个数据元素序列.而二叉树是一种层次结构.一颗二叉树要么为空,要么由一个数据元素(称为跟)和两颗独立的二叉树(称为左子树和右子树).某个节点的左(右)子树的根节点称为该节点的左(右)孩子节点.两颗子树均为空的节点称为叶子节点. 搜索二叉树:其左子树任意节点的值都小于此节点的值,其右子树中任意节点的值都大于此节点的值. 完全二叉树:如果一颗二叉树除最后一层外都保证是满的,且若最后一层不满,所有节点均位于最左边,则称为完全二叉树. 平衡二叉树:它是一颗空树,或它的左右

二叉树遍历递归与非递归实现

说明:本文仅供学习交流,转载请标明出处,欢迎转载! 二叉树遍历是二叉树中非常基础的部分,也是学习二叉树必须熟练掌握的部分,下面我们先给出二叉树三种遍历方式的定义,并通过举例来说明二叉树遍历的过程. 二叉树的遍历分为:前序遍历(也叫先序遍历).中序遍历.后序遍历.所谓前.中.后都是根据当前子树根结点相对左右孩子的位置而言,也就是说: 前序遍历:根结点在前,即:根 ----->左------->右: 中序遍历:根结点在中间,即:左------>根------>右: 后序遍历:根结点在最