二叉树(java)

二叉树基础

二叉树的理论基础

二叉树的分类

满二叉树

满二叉树:如果一颗二叉树只有度为0的节点和度为2的节点,并且度为0的结点在同一层上,那么这颗树就是满二叉树(度:表示子节点的个数)
如果一颗满二叉树的深度为k 那么他的节点个数就是2^k-1

完全二叉树

完全二叉树:除了最低层的结点可能没有填满外,其余各层节点数都大道 最大值 并且最低层的节点都集中在最左边的若干位置
如果最底层为h层 那应该包含 1~2^(h-1)个节点

二叉搜索树

二叉搜索树也成为二叉排序树或者二叉查找树
满足以下性质:
1、 非空左子树的键值都小于根节点;
2、 非空右子树的键值都大于根节点
3、 它的左右子树也是搜索树

平衡二叉搜索树

平衡二叉搜索树:又被称为AVL(Adelson-Velsky and Landis)树,且具 有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。

二叉树的存储方式

链式存储

在这里插入图片描述

顺序存储

在这里插入图片描述
顺序存储有以下特点:如果父节点的对应数组下标为i 那么他的左孩子就是2i+1 右孩子就是i2+1;

二叉树的定义

 二叉树每个结点都是由 键值和左右孩子组成(叶子结点没有左右子树);
 因此一个结点TreeNode 包括了 三个属性 分别是val 表示键值 和左孩子left 右孩子right
public class TreeNode {
		int val;
		TreeNode left;
		TreeNode right;
		public TreeNode(int val,TreeNode left,TreeNode right ){
			this.val=val;
			this.left=left;
			this.right=right;
		}
}

二叉树的遍历

二叉树的遍历方式

深度优先搜索 (递归法,迭代法)

1、 前序遍历:中左右
2、 中序遍历:左中右
3、 后序遍历:左右中

递归法
前序遍历
public void preorder(TreeNode root){//前序遍历
			if(root!=null)
			{
				System.out.print(root.data+" ");
				preorder(root.left);
				preorder(root.right);
			}
		}
中序遍历
	public void midorder(TreeNode root){//中序遍历
			if(root!=null)
			{
				midorder(root.left);
				System.out.print(root.data+" ");
				midorder(root.right);
			}
		}
后序遍历
	public void postorder(TreeNode root){//后序遍历
			if(root!=null)
			{
				postorder(root.left);
				postorder(root.right);
				System.out.print(root.data+" ");
			}
		}

总结 递归法 前序中序后序遍历的区别就主要在于 print的位置;

迭代法

迭代法前中后序 遍历主要是利用栈来实现的

前序遍历

前序遍历:中左右首先处理根节点 那么就先将根节点入栈 随后处理左结点那么将右子树入栈;为什么处理与入栈顺序不同呢?
因为栈是先进后出 只有这样处理我出栈的顺序才是中左右

public static List<Character> preorderByStack(TreeNode root)
		{
			List<Character> ans = new ArrayList<>();
			if(root==null){
				return ans;
			}
			Stack<TreeNode> st = new Stack<>();
			st.add(root);
			while(!st.isEmpty())
			{
				TreeNode tmp = st.pop();
				ans.add(tmp.val);
				if(tmp.right != null) st.add(tmp.right);
				if(tmp.left !=null) st.add(tmp.left);
			}
			return ans;
		}
后序遍历

后序遍历与前序遍历类似,简单来说就是把前序遍历的“中” 放到最后,但是要注意我们使用的是栈来模拟因此我们要调整前序遍历变成中右左的遍历顺序,然后反转rans数组,输出结果就是我们想要的左右中了。

	public static List<Character> postOrderByStack(TreeNode root)
		{
			List<Character> ans = new ArrayList<>();
			if(root == null)
				return ans;
			Stack<TreeNode> st = new Stack<>();
			st.add(root);
			while(!st.isEmpty())
			{
				TreeNode tmp = st.pop();
				ans.add(tmp.val);
				if(tmp.left!=null) st.add(tmp.left);
				if(tmp.right!=null) st.add(tmp.right);
			}
			Collections.reverse(ans);
			return ans;
		}
中序遍历

中序遍历相较于前序遍历和后序遍历更加复杂一下:中序遍历是左中右,先访问的是二叉树顶部的节点,然后一层一层向下访问,直到到达树左面的最底部,再开始处理节点(也就是在把节点的数值放进ans数组中),这就造成了处理顺序和访问顺序是不一致的。
所以我们针对这种情况那么在使用迭代法写中序遍历,就需要借用指针的遍历来帮助访问节点,栈则用来处理节点上的元素。

public static List<Character> midOrderByStack(TreeNode root)
		{
			List<Character> ans = new ArrayList<>();
			if(root == null) return ans;
			Stack<TreeNode> st = new Stack<>();
			TreeNode cur = root;
			while(cur!=null||!st.isEmpty())
			{
				if(cur!=null){
					st.push(cur);
					cur = cur.left;
				}
				else 
				{
					cur = st.pop();
					ans.add(cur.val);
					cur = cur.right;
				}
			}
			return ans;
		}

层序遍历

bfs迭代(借助队列)
public void levelorderByQueue(TreeNode root){
			Queue<TreeNode> q=new LinkedList<>();
			if(root==null) return;
			q.offer(root);
			while(!q.isEmpty())
			{
				TreeNode head=q.poll();
				System.out.print(head.data+" ");
				if(head.left!=null)
				q.offer(head.left);
				if(head.right!=null)
				q.offer(head.right);
			}
		}
dfs迭代
 public void levelorderBydfs(TreeNode node, Integer deep) {
 	 List<List<Integer>> resList = new ArrayList<List<Integer>>();
        if (node == null) return;
        deep++;
        if (resList.size() < deep) {
            List<Integer> item = new ArrayList<Integer>();
            resList.add(item);
        }
        resList.get(deep - 1).add(node.val);

        levelorderBydfs(node.left, deep);
        levelorderBydfs(node.right, deep);
    }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值