二叉树学习(一)

树的基础知识

树的定义:

  1. 树包含n(n ≥≥ 0 )个节点,n = 0时称为空树。
  2. 在树的结构关系中,有且仅有一个节点没有前趋节点,这个节点称为树的根节点。
  3. 除根节点外,树中其他的节点有且仅有一个前趋节点,但可以有很多后继节点。如图,A为根节点。

树的基本术语:

  1. 结点的度:每个节点具有的子树的个数(后继节点的个数)称为该节点的度;A的度为3,B的度为0。(节点的度 = 节点的孩子节点 = 节点的后继节点
  2. 树的度:树中所有节点的度的最大值;图中树的度为3。(树的度 取 所有节点度的最大值
  3. 分枝节点:度大于0的节点。(有分枝【孩子节点,后继节点,度】的节点
  4. 叶子节点:度为0的节点;如B、H、F、G。
  5. 孩子节点:一个节点的后继称为该节点的孩子节点;B为A的孩子节点。
  6. 父亲节点:一个节点的前趋称为该节点的父亲节点;A为B的父亲节点。
  7. 子孙节点:一个节点的所有子树中的节点称为该节点的子孙节点。(例如C的子孙节点是E、F、H)
  8. 祖先节点:从树根节点到达某个节点的路径上所通过的所有节点称为该节点的祖先节点。(H的祖先节点是E、C、A)
  9. 兄弟节点:具有相同父亲节点的节点;B、C、D为兄弟节点。
  10. 节点的层数:从上到下,根为第一层。(H在第四层)
  11. 树的深度:树中节点的最大层数称为树的深度或高度;图中树深为4。

二叉树的定义:二叉树是指树的度为2的有序树。左边的为左子树,右边的为右子树。

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

二叉树的性质:

  1. 二叉树上叶子节点数等于度为2的节点数加1。(上面树的度[子孙节点]为2的几点有7个,叶子节点有8个)
  2. 二叉树上第i层上最多有个节点(i ≥ 1)。(上面的树第2层有 2个节点)
  3. 深度为h的二叉树最多有个节点。

二叉树的遍历:

  • 二叉树的先序遍历:先遍历根节点,再遍历左子树,再遍历右子树。(第一个是根节点,最后一个所有树的最后一个节点)
  • 二叉树的中序遍历:先遍历左子树,再遍历根节点,再遍历右子树。(第一个是最后一层的第一个节点,最后一个最后一层的最后一个节点)
  • 二叉树的后序遍历:先便利左子树,再遍历右子树,再遍历根节点。(第一个是最后一层的第一个节点,最后一个根节点)
  • 二叉树的层次遍历:从上到下逐层遍历,根节点为第一层。

先序遍历为:A  BDH  I  E JK  - CFL M G NO 
中序遍历为:HDIBJEK A LFMCNGO 
后序遍历为:HID JKE B - LMF NOG C A 
层次遍历为:A BC DEFG HIJKLMNO

二叉树的重建

  • 已知二叉树的先序遍历和中序遍历,可重建二叉树;
  • 已知二叉树的后序遍历和中序遍历,可重建二叉树;
  • 已知二叉树的先序遍历和后序遍历不能重建二叉树,因为无法确定左子树和右子树,所以重建所得二叉树不唯一。

根据  前序遍历结果 和 中序遍历结果 重建二叉树 递归解法

package ins.platform.web.dd.web.action;

/**
 * 重建二叉树 递归解法
 *
 * @author DELL
 *
 */
public class RebuildBinTree {
    // 定义节点类
    public static class Node {
        int left; // 左子树位置
        int right; // 右子树位置
        char value; // 节点值

        public Node(int left, int right, char value) {
            this.left = left;
            this.right = right;
            this.value = value;
        }

        public void setLeft(int left) {
            this.left = left;
        }

        public void setRight(int right) {
            this.right = right;
        }
    }

    /**
     * 重建二叉树
     *
     * @param preOrder
     *            前序遍历结果
     * @param inOrder
     *            中序遍历结果
     * @param tree
     *            重建的树
     * @param root
     *            当前重建树的根节点位置
     */
    public static void rebuild(String preOrder, String inOrder, Node[] tree, int root) {

        int nTreeLen = preOrder.length();
        // 检查边界条件
        if (preOrder.length() == 0 || inOrder.length() == 0)
            return;
        // 获取当前遍历的第一个节点
        Node temp = new Node(-1, -1, preOrder.charAt(0));
        // 如果节点为空,把当前节点复制到根节点
        if (tree[root] == null) {
            tree[root] = temp;
        }
        // 如果当前树的长度为1,那么已经是最后一个节点
        if (nTreeLen == 1) {
            return;
        }
        // 寻找左子树的结尾
        int i = 0;
        while (inOrder.charAt(i) != temp.value && i < nTreeLen) {
            i++;
        }
        // System.out.println(i);
        // 重建左子树
        int index = root;
        if (i > 0) {
            tree[index].setLeft(++root);
            Node left = new Node(-1, -1, preOrder.charAt(1));
            tree[root] = left;
            // System.out.println(preOrder.substring(1,i+1)+" "+i);
            rebuild(preOrder.substring(1, i + 1), inOrder.substring(0, i), tree, root);
        }
        // 重建右子树
        if (nTreeLen - i - 1 > 0) {
            tree[index].setRight(root + i);
            Node right = new Node(-1, -1, preOrder.charAt(i + 1));
            tree[root + i] = right;
            rebuild(preOrder.substring(i + 1, nTreeLen), inOrder.substring(i + 1, nTreeLen), tree, root + i);
        }
    }

    public static void main(String[] args) {
        String preOrder = "ABDHIEJKCFLMGNO";//abdcef
        //ABDHIEJKCFLMGNO
        String inOrder = "HDIBJEKALFMCNGO";//dbaecf
        //HDIBJEKALFMCNGO
        Node[] tree = new Node[preOrder.length()];
        rebuild(preOrder, inOrder, tree, 0);
        System.out.println("重建的树为:");
        for (int i = 0; i < tree.length; i++) {
            String left, right;
            if (tree[i].left != -1)
                left = String.valueOf(tree[tree[i].left].value);
            else
                left = null;
            if (tree[i].right != -1)
                right = String.valueOf(tree[tree[i].right].value);
            else
                right = null;
            System.out.println(tree[i].value + " 左子树:" + left + " 右子树:" + right);
        }
    }

}

输出结果为:

重建的树为:
A 左子树:B 右子树:C
B 左子树:D 右子树:E
D 左子树:H 右子树:I
H 左子树:null 右子树:null
I 左子树:null 右子树:null
E 左子树:J 右子树:K
J 左子树:null 右子树:null
K 左子树:null 右子树:null
C 左子树:F 右子树:G
F 左子树:L 右子树:M
L 左子树:null 右子树:null
M 左子树:null 右子树:null
G 左子树:N 右子树:O
N 左子树:null 右子树:null
O 左子树:null 右子树:null

主要思路是 先序遍历的第一个节点是根节点、在中序遍历中可以根据根节点找到左子树,循环找左子树,直到找到最后一层的第一个节点

原文地址:https://www.cnblogs.com/llq1214/p/9332276.html

时间: 2024-11-09 04:50:42

二叉树学习(一)的相关文章

二叉树学习笔记。

1. 层序构建和先序遍历: 1 public class Tree { 2 public Tree left; 3 public Tree right; 4 public int val; 5 6 public Tree() { 7 8 } 9 10 public Tree(String n) { 11 this.val = Integer.parseInt(n); 12 } 13 14 public Tree createTreeByLevel(String[] var) { 15 if (v

二叉树学习笔记之二叉查找树(BSTree)

二叉查找树即搜索二叉树,或者二叉排序树(BSTree),学习回顾一下有关的知识. >>关于二叉查找树 二叉查找树(Binary Search Tree)是指一棵空树或者具有下列性质的二叉树:1. 若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值:2. 若任意节点的右子树不空,则右子树上所有节点的值均大于它的根节点的值:3. 任意节点的左.右子树也分别为二叉查找树.4. 没有键值相等的节点,这个特征很重要,可以帮助理解二叉排序树的很多操作.二叉查找树具有很高的灵活性,对其优化可

二叉树学习之非递归遍历

二叉树递归遍历可谓是学过数据结构的同仁都能想一下就能写出来,但在应聘过程我们常常遇到的是写出一个二叉树非递归遍历函数,接着上篇文章写二叉树的非递归遍历,先难后易,一步一步的来. 先上代码: #include "binarytree.h" #include <stack> #include <queue> #ifndef RECU #warning("RECU is not defined") /** *前序遍历(根左右) * *1.当前节点为

二叉树学习笔记1

数组.向量.链表都是一种顺序容器,它们提供了按位置访问数据的手段.而很多情况下,我们需要按数据的值来访问元素,而不是它们的位置来访问元素.比如有这样一个数组int num[3]={1,2,3},我们可以非常快速的访问数组中下标为2的数据,也就是说我们知道这个数据的位置,就可以快速访问.有时候我们是不知道元素的位置,但是却知道它的值是多少.假设我们有一个变量,存放在num这个数组中,我们知道它的值为2,却不知道它下标是多少,也就是说不知道它的位置.这个时候再去数组中访问这个元素就比较费劲,就得遍历

第5章 树与二叉树学习小结

前几章学习的基本都是线性的数据结构,就有顺序存储结构和链式存储结构,而这一章“树”结构是一类非线性数据结构,跟之前就有不同的点,但是,树的存储结构还是可以通过找到元素之间逻辑关系,采用类似线性表的方式,按照结点之间的逻辑关系放到线性存储中. 这部分主要学习到二叉树的内容,二叉树有好几个性质,我想这些性质很重要,有时候在解决问题,它能够帮助理解这棵树比较抽象的结构层次,这是我在理解代码时候体会到的.二叉树存储结构跟遍历有很大的关系,遍历的结果是将非线性结构的树中结点排成一个线性序列. 这是二叉链表

二叉树学习二:二叉搜索树

二叉搜索树(Binary Search Tree),或者是一棵空树,或者: 1)若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值: 2)若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值: 3)二叉搜索树的左.右子树也分别为二叉搜索树. 搜索二叉树相关的算法实现: 1)搜索二叉树的创建与转化为双链表实现: 1 #include "stdafx.h" 2 #include<iostream> 3 using namespace std; 4 5 /*二无

二叉树学习笔记-实现

上一篇文章中,算是初步了解了二叉树是一种怎样的数据结构,也算是有了一个初步的印象.接下来用自己的代码去实现一个二叉搜索树(以下全叫二叉树)类,对外提供常用的接口,比如insert.erase.size.find等等.就像盖房一样,如果说二叉树是一座建筑,那么其中的节点就是一块块砖.要实现二叉树这个类,就必须先实现节点类,假设我们起名为treeNode.在STL标准库中,像一般的数据结构都是模板类,在这里为了方便起见,假设二叉树这个类中保存的数据全是int型. 这个节点类中,需要包含如下的一些成员

二叉树学习笔记之树的旋转

树旋转(Tree rotation)是二叉树中的一种子树调整操作,每一次旋转并不影响对该二叉树进行中序遍历的结果.树旋转通常应用于需要调整树的局部平衡性的场合. >>左旋和右旋 树的旋转有两种基本的操作,即左旋(逆时针方向旋转)和右旋(顺时针方向旋转). 树旋转包括两个不同的方式,分别是左旋转(以P为转轴)和右旋转(以Q为转轴).两种旋转呈镜像,而且互为逆操作. 下图示意了两种树旋转过程中, 子树的初态和终态 +---+ +---+ | Q | | P | +---+ +---+ / \ ri

二叉树学习一:二叉树创建与遍历

二叉树的遍历有三种方式: 1)先序遍历:若二叉树为空,则空操作:不为空,则先访问根结点,先序遍历左子树,先序遍历右子树. 2)后序遍历:若二叉树为空,则空操作:不为空,则中序遍历左子树,访问根结点,中序遍历右子树. 3)后序遍历:若二叉树为空,则空操作:不为空,则后序遍历左子树,后序遍历右子树,访问根结点. 例: 1)先序遍历结果为:ABDECF 2)中序遍历结果为:DBEAFC 3)后序遍历结果为:DEBFCA 二叉树输出的思想是将树转换成线性结构输出,一般采用递归方式,非递归方式是使用栈实现

二叉树学习——简单入门题

入门题一: 输入一颗二叉树.你的任务是按从上到下.从左到右的顺序输出各个节点的值.每一个节点都依照从根节点到它的移动序列给出 (L表示左,R表示右).在输入中,每一个节点的左括号和右括号之间没有空格,相邻节点之间用一个空格隔开. 每颗树的输入用一 对空括号()结束(这对空括号不代表节点) 注意,假设从根到某个叶节点的路径上有的节点没有在输入中给出,或者给出了超出一次,应到输出 -1 .节点个数不超过256. 例子输入: (11,LL) (7,LLL) (8,R) (5,) (4,L) (13,R