二叉树例题

树是一种非线性数据结构,根据子节点数量可分为 「二叉树」 和 「多叉树」,最顶层的节点称为「根节点 root」。以二叉树为例,每个节点包含三个成员变量:「值 val」、「左子节点 left」、「右子节点 right」 。

class TreeNode {
    int val;        // 节点值
    TreeNode left;  // 左子节点
    TreeNode right; // 右子节点
    TreeNode(int x) { val = x; }
}
//建立此二叉树需要实例化每个节点,并构建各节点的引用指向。
// 初始化节点
TreeNode n1 = new TreeNode(3); // 根节点 root
TreeNode n2 = new TreeNode(4);
TreeNode n3 = new TreeNode(5);
TreeNode n4 = new TreeNode(1);
TreeNode n5 = new TreeNode(2);

// 构建引用指向
n1.left = n2;
n1.right = n3;
n2.left = n4;
n2.right = n5;

在这里插入图片描述

一、二叉树的前序遍历

前序遍历

//递归
class Solution {
    public List<Integer> preOrderRecur(TreeNode root) {
        List<Integer> res = new ArrayList<Integer>();
        preOrder(root, res);
        return res;
    }

    public void preOrder(TreeNode root, List<Integer> res) {
        if (root == null) {
            return;
        }
        res.add(root.val);
        preOrder(root.left, res);
        preOrder(root.right, res);
    }
}

//栈
//1、初始化栈,并将根节点入栈;
//2、当栈不为空时:
//	弹出栈顶元素 node,并将值添加到结果中;
//	如果 node 的右子树非空,将右子树入栈;
//	如果 node 的左子树非空,将左子树入栈;

//由于栈是“先进后出”的顺序,所以入栈时先将右子树入栈,这样使得前序遍历结果为 “根->左->右”的顺序。
 class Solution {
        public List<Integer> preorderTraversal(TreeNode root) {
            List<Integer> res = new ArrayList<Integer>();
            if (root == null) {
                return res;
            }
            Deque<TreeNode> stack = new LinkedList<TreeNode>();
            stack.push(root);
            while (!stack.isEmpty()) {
                TreeNode node = stack.pop();
                res.add(node.val);
                if (node.right != null) {
                    stack.push(node.right);
                }
                if (node.left != null) {
                    stack.push(node.left);
                }
            }
            return res;
        }
    }

二、二叉树的中序遍历

中序遍历

//递归
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<Integer>();
        inorder(root, res);
        return res;
    }

    public void inorder(TreeNode root, List<Integer> res) {
        if (root == null) {
            return;
        }
        inorder(root.left, res);
        res.add(root.val);
        inorder(root.right, res);
    }
}

//迭代
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<Integer>();
        Deque<TreeNode> stk = new LinkedList<TreeNode>();
        while (root != null || !stk.isEmpty()) {
            while (root != null) {
                stk.push(root);
                root = root.left;
            }
            root = stk.pop();
            res.add(root.val);
            root = root.right;
        }
        return res;
    }
}

//给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。
class Solution {
    public TreeNode sortedArrayToBST(int[] nums) {
        return helper(nums, 0, nums.length - 1);
    }

    public TreeNode helper(int[] nums, int left, int right) {
        if (left > right) {
            return null;
        }

        // 总是选择中间位置左边的数字作为根节点
        int mid = (left + right) / 2;

        TreeNode root = new TreeNode(nums[mid]);
        root.left = helper(nums, left, mid - 1);
        root.right = helper(nums, mid + 1, right);
        return root;
    }
}

验证二叉搜索树

节点的左子树只包含小于当前节点的数。
节点的右子树只包含大于当前节点的数。
所有左子树和右子树自身必须也是二叉搜索树。

98. 验证二叉搜索树

class Solution {
    public boolean isValidBST(TreeNode root) {
        if(root == null){
            return false;
        }
        Deque<TreeNode> stack =new LinkedList<>();
        TreeNode pre =null;
        while(root != null || !stack.isEmpty()){
            while(root != null){
                stack.push(root);
                root=root.left;
            }
            root = stack.pop();
            //如果当前遍历到的节点比前一个小,说明不是二叉搜索树
            if(pre != null && root.val <= pre.val){
                return false;
            }
            pre = root;
            root=root.right;
        }
        return true;
    }
}

三、二叉树的后序遍历

后续遍历

//递归
class Solution {
    public List<Integer> postOrderRecur(TreeNode root) {
        List<Integer> res = new ArrayList<Integer>();
        postOrder(root, res);
        return res;
    }

    public void postOrder(TreeNode root, List<Integer> res) {
        if (root == null) {
            return;
        }
        postOrder(root.left, res);
        postOrder(root.right, res);
        res.add(root.val);
    }
}

//栈
class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        LinkedList<Integer>  res = new LinkedList<>();
        if(root == null){
            return  res;
        }
        Deque<TreeNode> stack1 = new LinkedList<TreeNode>();
        stack1.push(root);
        while(!stack1.isEmpty()){
            TreeNode node = stack1.pop();
            res.addFirst(node.val);
            if(node.left!= null){
                stack1.push(node.left);
            }
            if(node.right != null){
                stack1.push(node.right);
            }
        }
        
        return res;
     }
}

剑指Offer 33.二叉搜索树的后序遍历序列

输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。


在这里插入图片描述
1、数组的最后一个元素即为根节点

2、划分左右子树

  • 遍历后序遍历的 [i,j] 区间元素,寻找第一个大于根节点的节点,索引记为m。此时[i,m-1]为左子树区间,[m,j-1]为右子树区间根节点索引为j。

3、判断是否为二叉搜索树

  • 左子树区间所有节点都小于根节点(pstorder[j])
  • 右子树区间内的所有节点都大于根节点(pstorder[j])
  • 当遇到≤postorder[j] 的节点则跳出;则可通过p=j 判断是否为二叉搜索树。

class Solution {
    public boolean verifyPostorder(int[] postorder) {
        return  recure(postorder,0,postorder.length-1);
    }
    boolean recure(int[] postorder,int i, int j){
        if(i>=j){
            return true;
        }
        int p=i;
        //寻找第一个大于根节点的值,postorder[j]为根节点
        //左子树全部小于根节点
        while(postorder[p] < postorder[j]){
            p++;
        }
        //此时p指向右子树的第一个节点       
        int m=p;
        //[i,m-1],[m,j]分别为左右子树区间
        //验证右子树的正确性,右子树的值全部大于根节点
        while(postorder[p] > postorder[j]){
            p++;
        }
        //此时p指向根节点
        return p==j && recure(postorder,i,m-1) &&  recure(postorder,m,j-1);
    }
}

四、二叉树的层序遍历(广度优先搜索)

层序遍历

// 二叉树的层序遍历

//1、首先根元素入队
//2、当队列不为空的时候
//	求当前队列的长度si//	依次从队列中取si个元素进行拓展,然后进入下一次迭代
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> ret = new ArrayList<List<Integer>>();
        if (root == null) {
            return ret;
        }

        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            List<Integer> level = new ArrayList<Integer>();
            int currentLevelSize = queue.size();
              while(currentLevelSize >0){
                TreeNode node = queue.poll();
                level.add(node.val);
                if (node.left != null) {
                    queue.offer(node.left);
                }
                if (node.right != null) {
                    queue.offer(node.right);
                }
                currentLevelSize--;
            }
            ret.add(level);
        }
        return ret;
    }
}


//给你一个二叉树,请你返回其按 层序遍历 得到的节点值。(即逐层地,从左到右访问所有节点)。
public List<List<Integer>> levelOrder(TreeNode root) {
    List<List<Integer>> res = new ArrayList<>();

    Queue<TreeNode> queue = new ArrayDeque<>();
    if (root != null) {
        queue.add(root);
    }
    while (!queue.isEmpty()) {
        int n = queue.size();
        List<Integer> level = new ArrayList<>();
        for (int i = 0; i < n; i++) { 
            TreeNode node = queue.poll();
            level.add(node.val);
            if (node.left != null) {
                queue.add(node.left);
            }
            if (node.right != null) {
                queue.add(node.right);
            }
        }
        res.add(level);
    }

    return res;
}
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> res = new ArrayList<>();
        List<Integer> ans = new ArrayList<>();
        if(root == null) return res;
        Deque<TreeNode> queue = new LinkedList<>();
        TreeNode cur = root;
        queue.add(cur) ;
        TreeNode curEnd = root;
        TreeNode nextEnd = null;
        while(!queue.isEmpty()){
            cur = queue.poll();
            ans.add(cur.val);
            if(cur.left != null){
                queue.add(cur.left);
                nextEnd = cur.left;
            }
            if(cur.right != null){
                queue.add(cur.right);
                nextEnd = cur.right;
            }
            if(cur == curEnd){
                res.add(new ArrayList<>(ans));
                ans.clear();    
                curEnd = nextEnd;
            }   
        }  
        return res;
    }
}

二叉树的最大深度(广度优先搜索)

104. 二叉树的最大深度

//广度优先搜索
class Solution {
    public int maxDepth(TreeNode root) {
        if(root == null){
            return 0;
        }
        Queue<TreeNode> queue  = new LinkedList<>();
        queue.offer(root);
        int count = 0;
        while(!queue.isEmpty()){
            int size =queue .size();
            while(size > 0){
                TreeNode node = queue.poll();
                if(node.left!= null){
                    queue.offer(node.left);
                }
                if(node.right!= null){
                    queue.offer(node.right);
                }
                size--;
            }
            count++;
        }
        return count;
    }
}

//递归
class Solution {
    public int maxDepth(TreeNode root) {
        if(root == null){
            return 0;
        }else{
            int leftDepth =maxDepth(root.left);
            int rightDepth=maxDepth(root.right);
            return Math.max(leftDepth,rightDepth)+1;
        }
    }
}

剑指Offer55-II.平衡二叉树

输入一棵二叉树的根节点,判断该树是不是平衡二叉树。如果某二叉树中任意节点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。

class Solution {
    public boolean isBalanced(TreeNode root) {
        if (root == null) return true;
        return Math.abs(depth(root.left) - depth(root.right)) <= 1 && isBalanced(root.left) && isBalanced(root.right);
    }

    private int depth(TreeNode root) {
        if (root == null) return 0;
        return Math.max(depth(root.left), depth(root.right)) + 1;
    }
}

剑指Offer32-III.从上到下打印二叉树III

请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。


双端队列

 LinkedList<Integer> tmp = new LinkedList<>();
 tmp.addLast(node.val)
 tmp.addFirst(node.val)
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {

        List<List<Integer>> res = new LinkedList<>();
        if(root == null){
            return res;
        }

        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while(!queue.isEmpty()){
            LinkedList<Integer> list = new LinkedList<>();
            int size =queue.size();
            while(size > 0){
                TreeNode node = queue.poll();
                if(res.size() % 2 ==0){
                    list.addLast(node.val);
                }else{
                    list.addFirst(node.val);
                }
                if(node.left!= null){
                    queue.add(node.left);
                } 
                if(node.right!= null){
                    queue.add(node.right);
                } 
                size--;
            }
            res.add(list);
        }
       return res;
    }
}
在这里插入代码片

五、 重建二叉树

后续遍历,重建二叉树

给定一个搜索二叉树的后续遍历数组,重建二叉树,返回新建的头节点

public static TreeNode process(int[] posArr, int L, int R) {
        //头节点为后序遍历的最后一个节点
        TreeNode head = new TreeNode(posArr[R]);
        //[L,R-1]
        int M = -1;
        //搜索二叉树的左子树<根节点<右子树
        for (int i = L; i < R; i++) {
            if (posArr[i] < posArr[R]) {//搜索二叉树的左子树小于根节点,M指向左子树的最后一个节点
                M = i;
            }
        }
        if (M == -1) {//左边的数全部大于头节点,只要右子树
            head.right = process(posArr, L, R - 1);
        } else if (M == R - 1) {//左边的数全部小于头节点,只有左子树
            head.left = process(posArr, L, R - 1);
        } else {//否则,左右子树都有
            head.left = process(posArr, L, M);
            head.right = process(posArr, M + 1, R - 1);
        }
        return head;
    }

剑指Offer07.重建二叉树

输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。


只要我们在中序遍历中定位到根节点,那么我们就可以分别知道左子树右子树中的节点数目

对于哈希映射中的每个键值对,键表示一个元素(节点的值),值表示其在中序遍历中的出现位置。在构造二叉树的过程之前,我们可以对中序遍历的列表进行一遍扫描,就可以构造出这个哈希映射。在此后构造二叉树的过程中,我们就只需要O(1) 的时间对根节点进行定位了。

class Solution {
    Map<Integer,Integer> indexMap = new HashMap<>();
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        int n =inorder.length;
        for(int i=0; i<n; i++){
            indexMap.put(inorder[i],i);
        }
       return myBuildTree(preorder,inorder,0,n-1,0,n-1);
    }

    public TreeNode myBuildTree(int[] preorder, int[] inorder, int preorder_left, int preorder_right, int inorder_left, int inorder_right) {
        if (preorder_left > preorder_right) {
            return null;
        }
        // 前序遍历中的第一个节点就是根节点
        int preorder_root = preorder_left;
        // 在中序遍历中定位根节点
        int inorder_root = indexMap.get(preorder[preorder_root]);
        
        // 先把根节点建立出来
        TreeNode root = new TreeNode(preorder[preorder_root]);
        // 得到左子树中的节点数目
        int size_left_subtree = inorder_root - inorder_left;
        // 递归地构造左子树,并连接到根节点
        // 先序遍历中「从 左边界+1 开始的 size_left_subtree」个元素就对应了中序遍历中「从 左边界 开始到 根节点定位-1」的元素
        root.left = myBuildTree(preorder, inorder, preorder_left + 1, preorder_left + size_left_subtree,inorder_left, inorder_root - 1);
        // 递归地构造右子树,并连接到根节点
        // 先序遍历中「从 左边界+1+左子树节点数目 开始到 右边界」的元素就对应了中序遍历中「从 根节点定位+1 到 右边界」的元素
        root.right = myBuildTree(preorder, inorder, preorder_left + size_left_subtree + 1, preorder_right, inorder_root + 1, inorder_right);
        return root;
    }
}


六、other

剑指Offer68-I.二叉搜索树的最近公共祖先

给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。


1、找到从根节点到目标节点的路径

  • 我们从根节点开始遍历;
  • 如果当前节点就是 p,那么成功地找到了节点;
  • 如果当前节点的值大于 p 的值,说明 p 应该在当前节点的左子树,因此将当前节点移动到它的左子节点;
  • 如果当前节点的值小于 pp 的值,说明 pp 应该在当前节点的右子树,因此将当前节点移动到它的右子节点。

2、当我们分别得到了从根节点到 p 和 q的路径之后,我们就可以很方便地找到它们的最近公共祖先了。显然,p和q的最近公共祖先就是从根节点到它们路径上的「分岔点」,也就是最后一个相同的节点

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        List<TreeNode> p_path=getPath(root,p);
        List<TreeNode> q_path=getPath(root,q);
        TreeNode ans = null;
        for(int i=0; i<p_path.size() && i<q_path.size(); i++){
            if(p_path.get(i) == q_path.get(i)){
                ans=p_path.get(i);
            }else{
                break;
            }
        }
        return ans;
    }
    public List<TreeNode>  getPath(TreeNode  root, TreeNode target){
        List<TreeNode>  list = new ArrayList<>();
        while(root != target){
            list.add(root);
            if(target.val<root.val){
                root=root.left;
            }else{
                root=root.right;
            }
        }
        list.add(root);
        return list;
    }
}

一次遍历

  • 我们从根节点开始遍历;
  • 如果当前节点的值大于 p和 q 的值,说明 p 和 q应该在当前节点的左子树,因此将当前节点移动到它的左子节点;
  • 如果当前节点的值小于 p 和 q的值,说明 p和 q应该在当前节点的右子树,因此将当前节点移动到它的右子节点;
  • 如果当前节点的值不满足上述两条要求,那么说明当前节点就是「分岔点」。此时,p和 q要么在当前节点的不同的子树中,要么其中一个就是当前节点。
class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        TreeNode ancestor = root;
        while (true) {
            if (p.val < ancestor.val && q.val < ancestor.val) {
                ancestor = ancestor.left;
            } else if (p.val > ancestor.val && q.val > ancestor.val) {
                ancestor = ancestor.right;
            } else {
                break;
            }
        }
        return ancestor;
    }
}

剑指Offer27.二叉树的镜像

请完成一个函数,输入一个二叉树,该函数输出它的镜像。


递归

class Solution {
    public TreeNode mirrorTree(TreeNode root) {
        if(root == null){
            return null;
        }
        TreeNode leftRoot = mirrorTree(root.right);
        TreeNode rightRoot = mirrorTree(root.left);
        root.left = leftRoot;
        root.right = rightRoot;
        return root;
    }
}

辅助栈

class Solution {
    public TreeNode mirrorTree(TreeNode root) {
        if(root == null){
            return null;
        }
        Deque<TreeNode> stack =new LinkedList<>();
        stack.push(root);
        while(!stack.isEmpty()){
            TreeNode node =stack.pop();
            TreeNode temp=node.left;
            node.left=node.right;
            node.right=temp;
            if(node.left != null){
                stack.push(node.left);
            }
            if(node.right != null){
                stack.push(node.right);
            }
        }
        return root;
    }
}

剑指Offer28.对称的二叉树

请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。

例如,二叉树 [1,2,2,3,4,4,3] 是对称的。

在这里插入图片描述


终止条件:

  • 当 L和 R 同时越过叶节点: 此树从顶至底的节点都对称,因此返回 true ;
  • 当 L或 R 中只有一个越过叶节点: 此树不对称,因此返回 false ;
  • 当节点 LL值 != 节点 R 值: 此树不对称,因此返回 false;
class Solution {
    public boolean isSymmetric(TreeNode root) {
        if(root == null){
            return true;
        }
        return recur(root.left,root.right);
    }

    boolean recur(TreeNode L,TreeNode R){
        if(L==null && R==null){
            return true;
        }
        if(L == null || R == null || L.val != R.val){
            return false;
        }
        return recur(L.left,R.right) && recur(L.right,R.left);
    }
}

199.二叉树的右视图

给定一个二叉树的 根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。


/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<Integer> rightSideView(TreeNode root) {
        
        List<Integer> res = new ArrayList<>();
        if(root == null) return res;

        Deque<TreeNode> queue = new LinkedList<>();
        TreeNode cur = root;
        queue.add(cur) ;
        TreeNode curEnd = root;
        TreeNode nextEnd = null;
        while(!queue.isEmpty()){
            cur = queue.poll();
            if(cur.left != null){
                queue.add(cur.left);
                nextEnd = cur.left;
            }
            if(cur.right != null){
                queue.add(cur.right);
                nextEnd = cur.right;
            }
            if(cur == curEnd){
                res.add(cur.val);
                curEnd = nextEnd;
            } 
        }  
        return res;
    }
}

前中后遍历

import java.util.*;

/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 * }
 */

public class Solution {
    /**
     * 
     * @param root TreeNode类 the root of binary tree
     * @return int整型二维数组
     */
    private ArrayList<Integer> list = new ArrayList<>();
    public int[][] threeOrders (TreeNode root) {
        // write code here
        if(root==null) {
            return new int[3][0];
        }
        preOrder(root);
        inOrder(root);
        afterOrder(root);
        int[][] res = new int[3][list.size()/3];
        int index = 0;
        for(int i=0;i<3;i++) {
            for(int j=0;j<list.size()/3;j++) {
                res[i][j] = list.get(index++);
            }
        }
        return res;
    }

    public void preOrder(TreeNode root) {
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode curr = stack.pop();
            list.add(curr.val);
            if (curr.right != null) {
                stack.push(curr.right);
            }
            if (curr.left != null) {
                stack.push(curr.left);
            }
        }
    }

    public void inOrder(TreeNode root) {
        Deque<TreeNode> stack = new LinkedList<>();
        while(root != null || !stack.isEmpty()){
            while(root != null){
                stack.push(root);
                root=root.left;
            }
            root = stack.pop();
            list.add(root.val);
            root=root.right;
        }
    }

    public void afterOrder(TreeNode root) {
        Deque<TreeNode> stack1 = new LinkedList<>();
        Deque<TreeNode> stack2 = new LinkedList<>();
        stack1.push(root);
        while(!stack1.isEmpty()){
            TreeNode  node = stack1.pop();
            stack2.push(node);
            if(node.left != null){
                stack1.push(node.left);
            }
            if(node.right!= null){
                stack1.push(node.right);
            }	
        }
        while(!stack2.isEmpty()){
            list.add(stack2.pop().val);
        }
    }
}

剑指Offer54.二叉搜索树的第k大节点

给定一棵二叉搜索树,请找出其中第k大的节点。


在这里插入图片描述

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {

    int res, k;
    public int kthLargest(TreeNode root, int k) {
        this.k=k;
        dfs(root);
        return res;
    }

    void dfs(TreeNode root){
        if(root == null){
            return;
        }
        dfs(root.right);
        if(k == 0) return;
        k--;
        if(k==0){
            res=(root.val);
        }
        dfs(root.left);
    }
}
(1)非递归定义 树(tree)是由n(n≥0)个结点组成的有限集合。n=0的树称为空树;n>0的树T: ① 有且仅有一个结点n0,它没有前驱结点,只有后继结点。n0称作树的根(root)结点。 ② 除结点外n0 , 其余的每一个结点都有且仅有一个直接前驱结点;有零个或多个直接后继结点。 (2)递归定义 一颗大树分成几个大的分枝,每个大分枝再分成几个小分枝,小分枝再分成更小的分枝,… ,每个分枝也都是一颗树,由此我们可以给出树的递归定义。 树(tree)是由n(n≥0)个结点组成的有限集合。n=0的树称为空树;n>0的树T: ① 有且仅有一个结点n0,它没有前驱结点,只有后继结点。n0称作树的根(root)结点。 ② 除根结点之外的其他结点分为m(m≥0)个互不相交的集合T0,T1,…,Tm-1,其中每个集合Ti(0≤i<m)本身又是一棵树,称为根的子树(subtree)。 2、掌握树的各种术语: (1) 父母、孩子与兄弟结点 (2) 度 (3) 结点层次、树的高度 (4) 边、路径 (5) 无序树、有序树 (6) 森林 3、二叉树的定义 二叉树(binary tree)是由n(n≥0)个结点组成的有限集合,此集合或者为空,或者由一个根结点加上两棵分别称为左、右子树的,互不相交的二叉树组成。 二叉树可以为空集,因此根可以有空的左子树或者右子树,亦或者左、右子树皆为空。 4、掌握二叉树的五个性质 5、二叉树的二叉链表存储。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

德玛西亚!!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值