二叉树理解

二叉树 :

二叉树结构:

class Node {
    V value;
    Node left;
    Node right;
}

什么是子树?

【子树】说明:从某个头节点开始,拿到它下面的所有节点 才 称为 子树

如:下图中的C-D ,就不是一个子树,因为它缺少了下面的E节点。但B节点,也是一个子树。

二叉树的 先序、中序、后序。

先序:任何子树的处理顺序都是,先头结点、再左子树、然后右子树。 即:头、左、右

中序:任何子树的处理顺序都是,先左子树、再头节点、然后右子树。即:左、头、右

后序:任何子树的处理顺序都是,先左子树、再右子树、然后头节点。即:左、右、头

二叉树 遍历说明:

上图中的子树总共有7个:

1-2-3-4-5-6-7

2-4-5

3-6-7

4

5

6

7

上图二叉树遍历:对每个子树来说,都要符合指定的遍历规则。

先序遍历(头左右):1-2-4-5-3-6-7 ,

中序遍历(左头右):4-2-5-1-6-3-7

后序遍历(左右头):4-5-2-6-7-3-1

二叉树代码实现

package com.example.demo.javatest.tree.binarytree;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Stack;

import com.alibaba.fastjson.JSONObject;

/**
* 二叉树
* @author likui 
* @since  2021年4月23日 上午9:14:38
* @version 1.0
*
*/
public class BinaryTreeTest {

	/**    
	 *
	 * @Description: 二叉树节点实体类
	 * @ClassName:  Node     
	 * @version V1.0 
	 * @author: likui     
	 * @date: 2021年4月23日 上午9:16:52  
	 *
	 */ 
	public static class Node {
		
		private int value;// 头节点
		private Node left;// 左树
		private Node right;// 右树
		
		public Node(int v) {
			value = v;
		}
		
		public int getValue() {
			return value;
		}
		public void setValue(int value) {
			this.value = value;
		}
		public Node getLeft() {
			return left;
		}
		public void setLeft(Node left) {
			this.left = left;
		}
		public Node getRight() {
			return right;
		}
		public void setRight(Node right) {
			this.right = right;
		}
		
	}
	
	/**   
	 * @Title: f   
	 * @Description: 二叉树遍历,递归实现
	 * @param: @param head      
	 * @return: void      
	 * @throws   
	 */  
	public static void f(Node head) {
		if (head == null) {
			return ;
		}
		f(head.getLeft());
		f(head.getRight());
	}
	
	/**   
	 * @Title: before   
	 * @Description: 先序遍历(头左右)  ,递归实现 
	 * @param: @param head      
	 * @return: void      
	 * @throws   
	 */  
	public static void before(Node head) {
		if (head == null) {
			return ;
		}
		System.out.print(head.getValue() + "->");
		before(head.getLeft());
		before(head.getRight());
	}
	
	/**   
	 * @Title: preOrderTraverse   
	 * @Description: 先序遍历(头左右)  ,非递归实现 
	 * @param:  head      
	 * @return: void      
	 * @throws   
	 * 
	 * 弹出则打印;
	 * 如有右,压入右。
	 * 如有左,压入左。
	 */  
	public static void preOrderTraverse(Node head) {
		//  Stack是栈;特点是:先进后出。
		if (head != null) {
			Stack<Node> stack = new Stack<>();
			// 把对象 压入堆栈顶部。
			stack.push(head);
			while (!stack.empty()) {
				// pop 移除堆栈顶部的对象,并作为此函数的值返回该对象。
				head = stack.pop();
				System.out.print(head.getValue() + "->");
				// 把右树对象压入堆栈顶部。	
				if (head.getRight() != null) {
					stack.push(head.getRight());
				}
				// 把左树对象压入堆栈顶部。
				if (head.getLeft() != null) {
					stack.push(head.getLeft());
				}
			}
		}
    }
	
	/**   
	 * @Title: middle   
	 * @Description: 中序遍历 (左头右),递归实现
	 * @param: @param head      
	 * @return: void      
	 * @throws   
	 */  
	public static void middle(Node head) {
		if (head == null) {
			return ;
		}
		middle(head.getLeft());
		System.out.print(head.getValue() + "->");
		middle(head.getRight());
	}
	
	/**   
	 * @Title: inOrderTraverse   
	 * @Description:  中序遍历 (左头右),非递归实现  
	 * @param:  root      
	 * @return: void      
	 * @throws   
	 * 1、整条左边界依次入栈;
	 * 2、步骤1无法再继续,弹出节点,然后在弹出节点的右树上,继续执行步骤1
	 * 
	 */  
	public static void inOrderTraverse(Node head) {
		if (head != null) {
			Stack<Node> stack = new Stack<>();
			while (head != null || !stack.isEmpty()) {
				if (head != null) {
					stack.push(head);
					head = head.getLeft();
				} else {
					head = stack.pop();
					System.out.print(head.getValue() + "->");
					head = head.getRight();
				}
			}
		}
    }
	
	/**   
	 * @Title: after   
	 * @Description: 后序遍历 (左右头),递归实现
	 * @param:  head      
	 * @return: void      
	 * @throws   
	 */  
	public static void after(Node head) {
		if (head == null) {
			return ;
		}
		after(head.getLeft());
		after(head.getRight());
		System.out.print(head.getValue() + "->");
	}
	
	/**   
	 * @Title: postOrderTraverse   
	 * @Description: 后序遍历 (左右头),非递归实现  
	 * @param:  root      
	 * @return: void      
	 * @throws   
	 */  
	public static void postOrderTraverse(Node h) {
        if (h != null) {
        	Stack<Node> stack = new Stack<>();
        	stack.push(h);
        	Node c = null;
        	while (!stack.empty()) {
        		// 查看堆栈顶部的对象,但不从堆栈中移除它。
        		c = stack.peek();
        		if (c.getLeft() != null && h != c.getLeft() && h != c.getRight()) {
        			// c的左节点不为空,并且上次打印的节点不是c 的左节点,也不是c的右节点,即:为新节点
        			stack.push(c.getLeft());
        		} else if (c.getRight() != null && h != c.getRight()) {
        			// c的右节点不为空,并且 上次打印的节点不是 c的右节点,即 c的右节点还没处理
        			stack.push(c.getRight());
        		} else {
        			// c 的左树、右树均已处理,打印头节点
        			System.out.print(stack.pop().getValue() + "->");
        			// h 跟踪的是上次打印的节点
        			h = c;
        		}
        	}
        }
    }
	
    /**   
     * @Title: laywerTraverse   
     * @Description: 层序遍历,这个是最符合常规思维的遍历方式,
     * 				从上往下,一层一层的从左往右遍历,此处结果为1-2-3-4-5-6-7-8-9
     * @param: @param node      
     * @return: void      
     * @throws   
     */  
    public static void laywerTraverse(Node node){
 
        if(node == null) {
        	return;
        }
 
        Queue<Node> queue = new LinkedList<>();
        queue.add(node);
        Node currentNode;
        while (!queue.isEmpty()){
            currentNode = queue.poll();
            System.out.print(currentNode.getValue()+"->");
            if(currentNode.getLeft() != null){
            	queue.add(currentNode.getLeft());
            }
            if(currentNode.getRight() != null){
            	queue.add(currentNode.getRight());
            }
        }
        System.out.println();
    }
    
    // 先序方式序列化
    public static Queue<String> preSerial(Node head) {
    	Queue<String> queue = new LinkedList<>();
    	beforeSerial(head,queue);
    	return queue;
    }
    // 先序方式序列化
    private static void beforeSerial(Node head, Queue<String> queue) {
		if (head == null) {
			queue.add(null);
		} else {
			queue.add(String.valueOf(head.getValue()));
			beforeSerial(head.getLeft(), queue);
			beforeSerial(head.getRight(), queue);
		}
	}
    
    // 通过先序队列构建二叉树
    public static Node buildByBeforeQueue(Queue<String> beforeList) {
    	if (beforeList == null || beforeList.size() == 0) {
    		return null;
    	}
    	return beforeBuild(beforeList);
    }
    
    // 通过先序队列构建二叉树
    private static Node beforeBuild(Queue<String> beforeList) {
    	String value = beforeList.poll();
    	if (value == null) {
    		return null;
    	}
    	Node head = new Node(Integer.valueOf(value));
    	head.setLeft(beforeBuild(beforeList));
    	head.setRight(beforeBuild(beforeList));
		return head;
	}

	// 中序方式序列化
    private static void middleSerial(Node head, Queue<String> queue) {
    	if (head == null) {
    		queue.add(null);
    	} else {
    		middleSerial(head.getLeft(), queue);
    		queue.add(String.valueOf(head.getValue()));
    		middleSerial(head.getRight(), queue);
    	}
    }
    
    // 后序方式序列化
    private static void afterSerial(Node head, Queue<String> queue) {
    	if (head == null) {
    		queue.add(null);
    	} else {
    		afterSerial(head.getLeft(), queue);
    		afterSerial(head.getRight(), queue);
    		queue.add(String.valueOf(head.getValue()));
    	}
    }
    
    // 层级序列化
    public Queue<String> levelSerialize(Node head) {
		Queue<String> result = new LinkedList<>();
		if (head == null) {
			result.add(null);
			return result;
		}

		result.add(String.valueOf(head.getValue()));

		Queue<Node> queue = new LinkedList<>();
		queue.add(head);
		while (!queue.isEmpty()) {
			head = queue.poll();
			if (head.getLeft() != null) {
				result.add(String.valueOf(head.getLeft().getValue()));
				queue.add(head.getLeft());
			} else {
				result.add(null);
			}

			if (head.getRight() != null) {
				result.add(String.valueOf(head.getRight().getValue()));
				queue.add(head.getRight());
			} else {
				result.add(null);
			}
		}

		return result;
	}
    
    // 层级反序列化
    public Node levelBuild(Queue<String> levelList) {
		if (levelList == null || levelList.isEmpty()) {
			return null;
		}
		Node head = generateNode(levelList.poll());
		Queue<Node> queue = new LinkedList<>();
		if (head != null) {
			queue.add(head);
		}
		Node node = null;
		while (!queue.isEmpty()) {
			node = queue.poll();
			node.setLeft(generateNode(levelList.poll()));
			if (node.getLeft() != null) {
				queue.add(node.getLeft());
			}
			node.setRight(generateNode(levelList.poll()));
			if (node.getRight() != null) {
				queue.add(node.getRight());
			}
		}
		return head;
	}
    //层级反序列化
	private Node generateNode(String value) {
		if (value == null) {
			return null;
		}
		return new Node(Integer.parseInt(value));
	}
    

	/**   
     * @Title: createBinaryTree   
     * @Description: 创建二叉树
     * @param: @return      
     * @return: List<Node>      
     * @throws   
     */  
    public static List<Node> createBinaryTree(){
 
        int[] array = {1,2,3,4,5,6,7,8,9};
 
        List<Node> nodeList = new ArrayList<>();
 
        for (int nodeIndex = 0; nodeIndex < array.length;nodeIndex++){
            nodeList.add(new Node(array[nodeIndex]));
        }
 
        //对LastParentIndex-1个父节点按照父节点和子节点的关系建立二叉树
        for (int parentIndex = 0; parentIndex < array.length/2-1;parentIndex++){
 
            //左孩子
            nodeList.get(parentIndex).left =  nodeList.get(parentIndex * 2 +1);
            //右孩子
            nodeList.get(parentIndex).right =  nodeList.get(parentIndex * 2 +2);
 
        }
 
        //最后一个父节点,可能存在没有右孩子的情况,所以拿出来单独处理
        int lastParentIndex = array.length/2-1;
 
        //左孩子
        nodeList.get(lastParentIndex).left =  nodeList.get(lastParentIndex * 2 + 1);
 
        //右孩子,如果长度为奇数则建立右孩子
        if(array.length % 2 == 1){
            nodeList.get(lastParentIndex).right = nodeList.get(lastParentIndex * 2 + 2);
        }
 
        // 输出结果
//      [
//	        {"left":{"left":{"left":{"value":8},"right":{"value":9},"value":4},"right":{"value":5},"value":2},"right":{"left":{"value":6},"right":{"value":7},"value":3},"value":1},
//	        {"left":{"left":{"value":8},"right":{"value":9},"value":4},"right":{"value":5},"value":2},
//	        {"left":{"value":6},"right":{"value":7},"value":3},
//	        {"left":{"value":8},"right":{"value":9},"value":4},
//	        {"value":5},
//	        {"value":6},
//	        {"value":7},
//	        {"value":8},
//	        {"value":9}
//        ]

        return nodeList;
    }
	
    
    public static void main(String[] args) {
    	List<Node> createBinaryTree = createBinaryTree();
    	System.out.println(JSONObject.toJSON(createBinaryTree));
    	
    	Node node = createBinaryTree.get(0);
    	System.out.println(JSONObject.toJSON(JSONObject.toJSON(node)));
    	// 先序遍历
    	System.out.println("先序:------------------------------------------------");
    	before(node);
    	System.out.println();
    	preOrderTraverse(node);
    	System.out.println();
    	// 中序遍历
    	System.out.println("中序:-----------------------------------------------");
    	middle(node);
    	System.out.println();
    	inOrderTraverse(node);
    	System.out.println();
    	// 后序遍历
    	System.out.println("后序:-----------------------------------------------");
    	after(node);
    	System.out.println();
    	postOrderTraverse(node);
    	
    	System.out.println();
    	// 层序遍历
    	System.out.println("层序:-----------------------------------------------");
    	laywerTraverse(node);
	}
	
}

输出结果:

{"left":{"left":{"left":{"value":8},"right":{"value":9},"value":4},"right":{"value":5},"value":2},"right":{"left":{"value":6},"right":{"value":7},"value":3},"value":1}
先序:------------------------------------------------
1->2->4->8->9->5->3->6->7->
1->2->4->8->9->5->3->6->7->
中序:-----------------------------------------------
8->4->9->2->5->1->6->3->7->
8->4->9->2->5->1->6->3->7->
后序:-----------------------------------------------
8->9->4->5->2->6->7->3->1->
8->9->4->5->2->6->7->3->1->
层序:-----------------------------------------------
1->2->3->4->5->6->7->8->9->

二叉树分类:

  • 1、 满二叉树(Full Binary Tree)

一棵满二叉树就是高度为k,且拥有(2^k)-1个节点的二叉树,一棵满二叉树每个节点,要么都有两棵子树,要么都没有子树;而且每一层所有的节点之间必须要么都有两棵子树,要么都没子树。

  • 2、完全二叉树(Complete Binary Tree)

完全二叉树是一颗特殊的二叉树,它遵循以下规则:
假设完全二叉树高度为k,则完全二叉树需要符合以下两点:
1)所有叶子节点都出现在k层或k-1层,并且从1~k-1层必须达到最大节点数。
2)第k层可以是不满的,但是第k层的所有节点必须集中在最左边。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值