二叉树的概念和Python和Java实现

51 阅读5分钟

由于树可以转换为二叉树,故直接进行二叉树的学习。

二叉树

二叉树最多只有左子树和右子树两个子树,二叉树的性质如下:

  • 在二叉树的第 i i i层最多有 2 i − 1 2^{i-1} 2i−1个节点
  • 深度为 k k k的二叉树最多有 2 k − 1 2^{k-1} 2k−1个节点
  • 对于任意一棵二叉树,如果叶节点数为 N 0 N_{0} N0​,而度数为2的节点总数为 N 2 N_{2} N2​,则有 N 0 = N 2 + 1 N_0 = N_2 + 1 N0​=N2​+1
  • 具有 n n n个节点的完全二叉树的深度必为 log ⁡ 2 ( n + 1 ) \log2(n+1) log2(n+1)
  • 对完全二叉树,若从上至下、从左至右编号,则编号为 i i i的结点,其左孩子编号必为 2 i + 1 2i + 1 2i+1,其右孩子编号必为 2 i + 2 2i+2 2i+2;其双亲的编号必为 ( i − 1 ) / 2 (i - 1)/2 (i−1)/2(除 i = 1 i=1 i=1外)

常用的二叉树有满二叉树完全二叉树,满二叉树指除最后一层无任何子节点外,每一层上的所有结点都有两个子结点二叉树;完全二叉树指当二叉树的深度为 h h h,除第 h h h 层外,其它各层 ( 1 ∼ h − 1 ) (1 \sim h-1) (1∼h−1) 的结点数都达到最大个数,第 h h h 层所有的结点都连续集中在最左边的二叉树。


在这里插入图片描述
满二叉树
在这里插入图片描述
完全二叉树

二叉树的实现:

from collection import deque
# 二叉树结点
class TreeNode(object):
	def __init__(self, x):
	   self.val = x
	   self.left = None
	   self.right = None
# 二叉树
class Tree(object):
	def __init__(self):
	   self.root = None

二叉树层序遍历:若树为空,则返回空,zh否则从根节点开始访问,从上而下逐层遍历。在同一层中按从左到右的顺序对节点逐个访问。若二叉树如下所示,则层序遍历的顺序为:ABCDEFGHI。


在这里插入图片描述

# 层序遍历

 def bfs(self, root):
      if not root: return []

      queue = [root]
      res = []
      while queue:
          nextLayer = []
          for node in queue:
              res.append(node.val)
              if node.left:
                  nextLayer.append(node.left)
              if node.right:
                  nextLayer.append(node.right)
          
          queue = nextLayer
      
      return res

二叉树前序遍历:若二叉树为空,则空操作返回,否则先访问根结点,然后前序遍历左子树,再前序遍历右子树。若二叉树如上图所示,遍历的顺序为:ABDGHCEIF。

# 递归法
def getPreOrder(root):
	res = []
	def preOrderRec(root):
	    if not root: return []
	    
	    res.append(root.val)
	    preOrderRec(root.left)
	    preOrderRec(root.right)
	    
   getPreOrder(root)
   return res

# 迭代法
def preOrderIter(root):
	if not root: return []
	
	stack = [root]
	res = []
	while stack:
	    root = stack.pop()
	    if root:
	        res.append(root.val)
	    if root.right:
	        stack.append(root.right)
	    if root.left:
	        stack.append(root.left)
	        
	return res

二叉树中序遍历:若树为空,则空操作返回,否则从根结点开始(注意并不是先访问根结点),中序遍历根结点的左子树,然后是访问根结点,最后中序遍历右子树。若二叉树如上图图所示,遍历的顺序为:GDHBAEICF。

中序遍历的结果一个很重要的特性:遍历结果自然就是升序的

# 递归法
    def getInOrder(root):
		res = []
        def inOrderRec(root):
            if not root: return []
            
            inOrderRec(root.left)
            res.append(root.val)
            inOrderRec(root.right)	
        
        inOrderRec(root)
		return res

# 迭代法
def inOrderIter(root):
   if not root: return []

	stack = []
	res = []
	while stack or root:
		if root:
			stack.append(root)
			root = root.left
	    else:
			node = stack.pop()
			res.append(node.val)
			root = node.right
	return res

二叉树后序遍历:若树为空,则空操作返回,否则从左到右先叶子后结点的方式遍历访向左右子树,最后是访问根结点。若二叉树如上图所示,遍历的顺序为:GHDBIEFCA。

def getPostOrder(self, root):
	res = []
	def postOrderRec(root):
    	if not root: return []
    
	    postOrderRec(root.left)
	    postOrderRec(root.right)
	    res.append(root.val)

    def postOrderIter(root):
        if not root: return []
        
        stack = [root]
        res = []
        while stack:
            node = stack.pop()
            if node.left:
                stack.append(node.left)
            if node.right:
                stack.append(node.right)
            res.append(node.val)
            
		return res

根据前序遍历和中序遍历重建二叉树


在这里插入图片描述

df construct_tree(preorder=None, inorder=None):
	if not preorder or not inorder:
	   return None
	
	index = inorder.index(preorder[0])
	# 左子树的中序遍历序列
	left = inorder[0:index]
	# 右子树的中序遍历序列
	right = inorder[index+1:]
	# 返回根节点
	root = TreeNode(preorder[0])
	
	# 递归调用重建二叉树
	root.left = construct_tree(preorder[1:1+len(left)], left)
	root.right = construct_tree(preorder[-len(right):], right)
	
	return root

完整实验代码

class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

class Solution:
    def __init__(self):
        self.res = []
    def getPreOrder(self, root):
        # 递归法
        def preOrderRec(root):
            if not root:
                return None
            
            self.res.append(root.val)
            preOrderRec(root.left)
            preOrderRec(root.right)

        # 迭代法
        def preOrderIter(root):
            if not root: self.res = []

            stack = [root]
            while stack:
                root = stack.pop()
                if root:
                    self.res.append(root.val)
                if root.right:
                    stack.append(root.right)
                if root.left:
                    stack.append(root.left)

        # preOrderRec(root)
        preOrderIter(root)

    def getInOrder(self, root):
        def inOrderRec(root):
            if not root:
                return None
            
            inOrderRec(root.left)
            self.res.append(root.val)
            inOrderRec(root.right)

        def inOrderIter(root):
            if not root: self.res = []

            stack = []
            while stack or root:
                if root:
                    stack.append(root)
                    root = root.left
                else:
                    node = stack.pop()
                    self.res.append(node.val)
                    root = node.right


        # inOrderRec(root)
        inOrderIter(root)

    def getPostOrder(self, root):
        def postOrderRec(root):
            if not root:
                return None
            
            postOrderRec(root.left)
            postOrderRec(root.right)
            self.res.append(root.val)

        def postOrderIter(root):
            if not root: self.res = []

            stack = [root]
            while stack:
                node = stack.pop()
                if node.left:
                    stack.append(node.left)
                if node.right:
                    stack.append(node.right)
                self.res.append(node.val)

        # postOrderRec(root)   
        postOrderIter(root)

    def bfs(self, root):
        if not root: self.res = []

        queue = [root]
        while queue:
            nextLayer = []
            for node in queue:
                self.res.append(node.val)
                if node.left:
                    nextLayer.append(node.left)
                if node.right:
                    nextLayer.append(node.right)
            
            queue = nextLayer
        

if __name__ == "__main__":
    
    node1 = TreeNode('A')
    node2 = TreeNode('B')
    node3 = TreeNode('C')
    node4 = TreeNode('D')
    node5 = TreeNode('E')
    node6 = TreeNode('F')
    node7 = TreeNode('G')
    node8 = TreeNode('H')
    node9 = TreeNode('I')

    node1.left = node2
    node1.right = node3
    node2.left = node4
    node4.left = node7
    node4.right = node8
    node3.left = node5
    node3.right = node6
    node5.right = node9

    s = Solution()
    # s.getPreOrder(node1)
    # print (s.res) # ['A', 'B', 'D', 'G', 'H', 'C', 'E', 'I', 'F']

    # s.getInOrder(node1)
    # print (s.res) # ['G', 'D', 'H', 'B', 'A', 'E', 'I', 'C', 'F']

    # s.getPostOrder(node1)
    # print (s.res[::-1]) # ['G', 'H', 'D', 'B', 'I', 'E', 'F', 'C', 'A']

    # s.bfs(node1)
    # print (s.res) # ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I']

Java实现代码:

import java.util.*;

/**
 * @Author dyliang
 * @Date 2020/10/7 21:22
 * @Version 1.0
 */
public class BinaryTree {
    public static void main(String[] args) {
        TreeNode root = new TreeNode(1);
        root.left = new TreeNode(2);
        root.right = new TreeNode(3);
        root.left.left = new TreeNode(4);
        root.left.right = new TreeNode(5);
        root.left.left.left = new TreeNode(8);
        root.left.left.right = new TreeNode(9);
        root.right.left = new TreeNode(6);
        root.right.right = new TreeNode(7);

        System.out.println("---------recursive---------");
        preOrderRecur(root);
        System.out.println();
        System.out.println("---------------------");
        inOrderRecur(root);
        System.out.println();
        System.out.println("---------------------");
        postOrderRecur(root);
        System.out.println();
        System.out.println("---------Iteration---------");
        preOrderIter(root);
        System.out.println();
        System.out.println("---------------------");
        inOrderIter(root);
        System.out.println();
        System.out.println("---------------------");
        postOrderIter(root);
        System.out.println();
        System.out.println("---------------------");
        levelOrder(root);

        /**
         * ---------recursive---------
         * 1 2 4 8 9 5 3 6 7
         * ---------------------
         * 8 4 9 2 5 1 6 3 7
         * ---------------------
         * 8 9 4 5 2 6 7 3 1
         * ---------Iteration---------
         * 1 2 4 8 9 5 3 6 7
         * ---------------------
         * 8 4 9 2 5 1 6 3 7
         * ---------------------
         * 8 9 4 5 2 6 7 3 1
         * ---------------------
         * 1 2 3 4 5 6 7 8 
         */

    }
    public static class TreeNode{
        int val;
        TreeNode left;
        TreeNode right;

        public TreeNode(int val) {
            this.val = val;
        }

        public TreeNode() {
        }
    }

    /**
     * 递归方式的先序遍历
     * @param root
     */
    public static void preOrderRecur(TreeNode root){
        if(root == null){
            return;
        }

        System.out.print(root.val + " ");
        preOrderRecur(root.left);
        preOrderRecur(root.right);
    }

    /**
     * 递归方式的中序遍历
     * @param root
     */
    public static void inOrderRecur(TreeNode root){
        if(root == null){
            return;
        }

        inOrderRecur(root.left);
        System.out.print(root.val + " ");
        inOrderRecur(root.right);
    }

    /**
     * 递归方式的后续遍历
     * @param root
     */
    public static void postOrderRecur(TreeNode root){
        if(root == null){
            return;
        }

        postOrderRecur(root.left);
        postOrderRecur(root.right);
        System.out.print(root.val + " ");
    }

    /**
     * 迭代方式的先序遍历
     * @param root
     */
    public static void preOrderIter(TreeNode root){
        if(root == null){
            return;
        }

        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        while(!stack.isEmpty()){
            TreeNode node = stack.pop();
            System.out.print(node.val + " ");
            if(node.right != null){
                stack.push(node.right);
            }
            if(node.left != null){
                stack.push(node.left);
            }
        }
    }

    /**
     * 迭代方式的后序遍历
     * @param root
     */
    public static void postOrderIter(TreeNode root){
        if(root == null){
            return;
        }

        Stack<TreeNode> stack = new Stack<>();
        List<Integer> list = new ArrayList<>();
        stack.push(root);
        while(!stack.isEmpty()){
            TreeNode node = stack.pop();
            list.add(node.val);
            if(node.left != null){
                stack.push(node.left);
            }
            if(node.right != null) {
                stack.push(node.right);
            }
        }

        Collections.reverse(list);
        for (Integer i : list) {
            System.out.print(i + " ");
        }
    }

    /**
     * 迭代方式的中序遍历
     * @param root
     */
    public static void inOrderIter(TreeNode root){
        if(root == null){
            return;
        }

        Stack<TreeNode> stack = new Stack<>();
        while (!stack.isEmpty() || root != null){
            if(root != null){
                stack.push(root);
                root = root.left;
            } else {
                root = stack.pop();
                System.out.print(root.val + " ");
                root = root.right;
            }
        }
    }

    /**
     * 层序遍历
     * @param root
     */
    public static void levelOrder(TreeNode root){
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        while (!queue.isEmpty()){
            Queue<TreeNode> next = new LinkedList<>();
            for (TreeNode node : queue) {
                if(node != null){
                    System.out.print(node.val + " ");
                    if(root.left != null){
                        next.add(node.left);
                    }
                    if(root.right != null){
                        next.add(node.right);
                    }
                }else{
                    return;
                }
            }
            queue = next;
        }
    }
}