数据结构:二叉树及相关算法

二叉树

class Tree {
	Node left;
	Node right;
	int value;
	//递归
	public static void f(Tree head) {
		if(head == null) {
		reutrn;
		}
		f(head.left);
		f(head.right);
	}
	//遍历结果
	//1,2,4,4,4,2,5,5,5,2,1,3,6,6,6,3,7,7,7,3,1
}

遍历

在这里插入图片描述

先序遍历

先序遍历指的是所有子树中先打印头节点、在左节点、最后右节点
头左右::1,2,4,5,3,6,7(利用递归顺第一次出现的打印)
递归方式:

	public static void f(Tree head) {
		if(head == null) {
		reutrn;
		}
		System.out.println(head.value);
		f(head.left);
		f(head.right);
	}

非递归压栈形式可实现:
每次

  1. 从栈中弹出一个节点cur
  2. 打印
  3. 先右后左压入(如果有)
  4. 重复1
	public static void f(Tree head) {
		if(head == null) {
			return;
		}
		Stack<Node> stack = new Stack();
		stack.add(head);
		while(!stack.isEmpty()){
		Node head = stack.pop();
		System.out.print(head.value);
		if(head.right != null) {
			stack.push(head.right);
		}
		if(head.left!= null) {
			stack.push(head.left);
		}
		}
	}

中序遍历

左头右:4,2,5,1,6,3,7(利用递归顺第二次出现的打印)

	public static void f(Tree head) {
		if(head == null) {
		reutrn;
		}
		f(head.left);
		System.out.println(head.value);
		f(head.right);
	}

非递归:

  1. 先将所有子树左节点放入栈中
  2. 弹出打印
  3. 弹出时判断是否存在右子树
  4. 存在压入右节点
    public void inOrderUnRecur(Node head) {
        if (head == null) {
            return;
        }
        Stack<Node> stack = new Stack<Node>();
        while (!stack.isEmpty() || head != null) {
            if (head != null) {
                stack.push(head);
                head = head.left;
            } else {
                head = stack.pop();
                System.out.println(head.value);
                head = head.right;
            }
        }
    }

后序遍历

左右头:4,5,2,6,7,3,1(利用递归顺第三次出现的打印)

	public static void f(Tree head) {
		if(head == null) {
		reutrn;
		}
		f(head.left);
		f(head.right);
		System.out.println(head.value);
	}

非递归:

  1. 申请1个栈、1个收集栈
  2. 放入头cur 弹出放入收集栈
  3. 先左在右放入(如果右)
  4. 弹出
  5. 遍历收集栈
	public static void f(Tree head) {
		if(head == null) {
			return;
		}
		Stack<Node> s1= new Stack();
		Stack<Node> s2 = new Stack();
		stack.push(head);
		while(!s1.isEmpty()){
		 head = s1.pop();
		  s2.push(head);
			if(head.left!= null) {
			stack.push(head.right);
		}
		if(head.right != null) {
			stack.push(head.right);
		}
		}
		while(!s2.isEmpty()){
		System.out.println(s2.pop().value);
		}
	}

深度遍历

二叉树的深度遍历即为先序遍历。

广度遍历(宽度遍历)

用队列先左在右放入取出即可

    public static void f(Node head) {
        if(head == null) {
            return;
        }
        Queue<Node> queue = new LinkedList<Node>();
        queue.add(head);
        while(!queue.isEmpty()){
            head= queue.poll();
            System.out.print(head.value);
            if(head.left!= null) {
                queue.add(head.left);
            }
            if(head.right!= null) {
                queue.add(head.right);
            }
        }
    }

计算当前树最大宽度是多少

   public static int w(Node head) {
        if(head == null) {
            return 0;
        }
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.add(head);
        //记录节点个数
        Map<TreeNode, Integer> levelMap = new HashMap<>();
        levelMap.put(head,1);
        //当前最大个数
        int max = Integer.MIN_VALUE;
        //当前层数
        int curLevel = 0;
        //当前节点个数统计
        int curNodeNum = 0;

        while(!queue.isEmpty()){
             head = queue.poll();
            if (levelMap.get(head) == curLevel) {
                curNodeNum ++;
            } else {
                max = Math.max(max, curNodeNum);
                curLevel ++;
                curNodeNum = 1;
            }
            if(head.left!= null) {
                levelMap.put(head.left, curLevel + 1);
                queue.add(head.left);
            }
            if(head.right!= null) {
                levelMap.put(head.right, curLevel + 1);
                queue.add(head.right);
            }
        }
        return Math.max(max, curNodeNum);
    }

搜索二叉树

所有子树左节点都比右小

判断是否为搜索二叉树

中序遍历 判断是否为依次升序、升序即为搜索二叉树

	public static boolean isBST(Tree head) {
		int preValue = 0;
		if(head == null) {
		reutrn true;
		}
		boolean result= isBST(head.left);
		if(!result){
			return false;
		}
		if(head.value <= preValue) {
			return false;
		}else{
			preValue = head.value;
		}
		return isBST(head.right);
	}

判断完全二叉树

  1. 进行广度遍历并记录
  2. 如果出现有右孩子无左孩子直接false
  3. 满足2条件如果出现第一个左右不全必须为叶子节点
    public Boolean isCBT(Node head) {
        Queue<Node> queue = new LinkedList<Node>();
        queue.add(head);
        Node l = null;
        Node r = null;
        //是否遇到左右孩子不双全
        boolean leaf = false;
        while (!queue.isEmpty()) {
            Node node = queue.poll();
            l = node.left;
            r = node.right;
            if ((l == null && r != null) ||(leaf && (l != null || r != null))) {
                return false;
            }

            if (node.left != null) {
                queue.add(node.left);
            }
            if (node.right != null) {
                queue.add(node.right);
            }
            if (l== null || r == null) {
                leaf = true;
            }
        }
        return true;
    }

满二叉树

概念:

  • 最大深度l
  • 节点个数n
  • 当满足n = 2l-1时该树必为满二叉树
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class ReturnData {
        private int nodeNum;
        private int height;
    }

    public boolean isF(Node head) {
        if (head == null) {
            return true;
        }

        ReturnData data = isFull(head);
        return data.nodeNum == (1 << data.height -1);
    }

    public ReturnData isFull(Node x) {
        if (x == null) {
            return new ReturnData(0,0);
        }
        ReturnData left = isFull(x.left);
        ReturnData right = isFull(x.right);

        int height = Math.max(left.height, right.height) +1;
        int nodes = left.nodeNum + right.nodeNum + 1;

        return new ReturnData(nodes, height);
    }

平衡二叉树

  • 概念:
  • 对于任何二叉树而言他的左树和右树高度差不超过1的树
    

算法判断:

  • 左子树要是平衡二叉树
  • 右子树要是平衡二叉树
  • |左高-右高|<=1
    以上成立即为平衡二叉树
   @Data
    @AllArgsConstructor
    public class ReturnType {
        private int height;
        private boolean isBalanced;
    }

    public boolean isBalanced(Node head) {
       return process(head).isBalanced;
    }

    public ReturnType process(Node x) {
        if (x == null) {
            return new ReturnType(0, true);
        }

        ReturnType leftProcess = process(x.left);
        ReturnType rightProcess = process(x.right);

        //计算当前高度 子树最大高度加上自身1 即为当前高度
        int height = Math.max(leftProcess.height, rightProcess.height) +1;

        //判断是否为平衡树并高度小于等于1
        boolean isBalanced = leftProcess.isBalanced && rightProcess.isBalanced && Math.abs( leftProcess.height - rightProcess.height) < 2;

        return new ReturnType(height, isBalanced);
    }

	//搜索二叉树
    @Data
    @AllArgsConstructor
    public class ReturnData {
        private boolean isSearch;
        private int max;
        private int min;
    }

    public boolean isSearch(Node head) {
        return isIBS(head).isSearch;
    }

    public ReturnData isIBS(Node x) {
        if (x == null) {
            return null;
        }
        ReturnData left = isIBS(x.left);
        ReturnData right = isIBS(x.right);

        int max = x.value;
        int min = x.value;
        boolean isBST = true;

        if (left != null) {
            max = Math.max(left.max, max);
            min = Math.max(left.min, min);
        }
        if (right != null) {
            max = Math.max(right.max, max);
            min = Math.max(right.min, min);
        }

        if (left != null && (!left.isSearch || left.max >= x.value)) {
            isBST = false;
        }
        if (right != null && (!right.isSearch || right.min <= x.value)) {
            isBST = false;
        }
        return new ReturnData(isBST, max, min);

    }

二叉树算法中套路总结

  • 递归形式
    • 思考所有可能性
    • 默认可以拿到左右树所有信息

例子:平衡二叉树
可能性:假设x为头的二叉树

  • 左树要为平衡二叉树
  • 右树要为平衡二叉树
  • 左右高度差<=1
  • 都满足则为平衡
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值