Android 算法知识点-二叉树相关

《Java 数据结构和算法 第二版》
原文
本文用于方便整理和复习,感谢作者分享

特性

二叉树的重要特性
  • 1.二叉树的第 n 层上节点数最多 2 n − 1 2^{n-1} 2n1

  • 2.高度为 k 的二叉树中,最多有 2 k − 1 2^k-1 2k1 个节点

  • 3.若采用连续储存的方式存放二叉树,则节点下标之间的关系:
    若某个节点的下标为 i ,则这个节点的父节点的下标为 i / 2 i / 2 i/2
    若某个节点下标为 i ,且节点的度为2,则这个节点的【左子节点的下标为 2 ∗ i + 1 2 * i + 1 2i+1】 ,【右子节点的下标为 2 ∗ i + 2 2 * i + 2 2i+2 】。

满二叉树的性质:
  • 1.满二叉树的第i层的节点数为 2 n − 1 2^{n-1} 2n1

  • 2.深度为 k 的满二叉树必有 2 k − 1 2^k-1 2k1 个节点 ,叶子数为 2 k − 1 2^{k-1} 2k1

  • 3.具有n个节点的满二叉树的深度为 l o g 2 ( n + 1 ) log_2(n+1) log2(n+1)

完全二叉树的性质:
  • 1.在完全二叉树中,若某个节点没有左子树,则一定没有有子树

  • 2.若采用连续储存的方式存放二叉树,则节点下标之间的关系(根节点下标为0):
     
     若某个节点的下标为 i ,则这个节点的父节点的下标为 i / 2 i / 2 i/2
     
     若某个节点下标为 i ,且节点的度为2,则这个节点的【左子节点的下标为 2 ∗ i + 1 2 * i + 1 2i+1】 ,
     右子节点的下标为 2 ∗ i + 2 2 * i + 2 2i+2

  • 3.除了根节点外,左子树的下标为基数,右子树的下标为偶数

一、二叉树相关算法 前序、中序、后序遍历(递归,迭代)

概念
1)前序遍历:先遍历根节点,然后遍历左子节点,最后遍历右子节点,简记为“根-左-右”;

2)中序遍历:先遍历左子节点,然后遍历根节点,最后遍历右子节点,简记为“左-根-右”;

3)后序遍历:先遍历左子节点,然后遍历右子节点,最后遍历根节点,简记为“左-右-根”;

public class TreeNode {
	int value;
	TreeNode left;
	TreeNode right;
	
	TreeNode(int value) { 
		this.value = value; 
	}
}
1、前序遍历 “根-左-右”
public static void preOrderRe(TreeNode biTree) {//递归实现
    System.out.println(biTree.value);
    TreeNode leftTree = biTree.left;
    if (leftTree != null) {
        preOrderRe(leftTree);
    }
    TreeNode rightTree = biTree.right;
    if (rightTree != null) {
        preOrderRe(rightTree);
    }
}

public static void preOrder(TreeNode biTree) {//迭代实现
    Stack<TreeNode> stack = new Stack<TreeNode>();
    while (biTree != null || !stack.isEmpty()) {
        while (biTree != null) {
            System.out.println(biTree.value);
            stack.push(biTree);
            biTree = biTree.left;
        }
        if (!stack.isEmpty()) {
            biTree = stack.pop();
            biTree = biTree.right;
        }
    }
}
2、中序遍历 “左-根-右”
public static void midOrderRe(TreeNode biTree) {//中序遍历递归实现
    if (biTree == null) {
        return;
    } else {
        midOrderRe(biTree.left);
        System.out.println(biTree.value);
        midOrderRe(biTree.right);
    }
}	

public static void midOrder(TreeNode biTree) {//中序遍历迭代实现
    Stack<TreeNode> stack = new Stack<TreeNode>();
    while (biTree != null || !stack.isEmpty()) {
        while (biTree != null) {
            stack.push(biTree);
            biTree = biTree.left;
        }
        if (!stack.isEmpty()) {
            biTree = stack.pop();
            System.out.println(biTree.value);
            biTree = biTree.right;
        }
    }
}
3、后序遍历 “左-右-根”
public static void postOrderRe(TreeNode biTree) {//后序遍历递归实现
    if (biTree == null) {
        return;
    } else {
        postOrderRe(biTree.left);
        postOrderRe(biTree.right);
        System.out.println(biTree.value);
    }
}

public static void postOrder(TreeNode biTree) {//后序遍历迭代实现
    int left = 1;//在辅助栈里表示左节点
    int right = 2;//在辅助栈里表示右节点
    Stack<TreeNode> stack = new Stack<TreeNode>();
    Stack<Integer> stack2 = new Stack<Integer>();//辅助栈,用来判断子节点返回父节点时处于左节点还是右节点。

    while (biTree != null || !stack.empty()) {
        while (biTree != null) {//将节点压入栈1,并在栈2将节点标记为左节点
            stack.push(biTree);
            stack2.push(left);
            biTree = biTree.left;
        }

        while (!stack.empty() && stack2.peek() == right) {//如果是从右子节点返回父节点,则任务完成,将两个栈的栈顶弹出
            stack2.pop();
            System.out.println(stack.pop().value);
        }

        if (!stack.empty() && stack2.peek() == left) {//如果是从左子节点返回父节点,则将标记改为右子节点
            stack2.pop();
            stack2.push(right);
            biTree = stack.peek().right;
        }

    }
}
4、层次遍历
1)对于不为空的节点,先把该节点加入到队列中

2)从队列中拿出节点,如果该节点的左右节点不为空,就分别把左右节点加入到队列中

3)重复以上操作直到队列为空

//层次遍历
public static void levelOrder(TreeNode root) {
	if(root == null) {
		return;
	}
	//通过 LinkedList 先进先出
	LinkedList<TreeNode> list = new LinkedList<TreeNode>();
	list.add(root);
	TreeNode currentNode;
	while(!list.isEmpty()) {
		currentNode = list.poll();//poll() 从 LinkedList【头部删除并返回】
		System.out.println(currentNode.value);
		if(currentNode.left != null) {
			list.add(currentNode.left);
		}
		if(currentNode.right != null) {
			list.add(currentNode.right);
		}
	}
}

二、红黑树 与 BL树 等

1、红黑树,参考Java数据结构部分笔记和资料

2、[BL树](https://blog.csdn.net/jimo_lonely/article/details/82716142)
	
	t是自然数,可以自己定义的。
   
	1)所有叶子节点到根节点的路径长度相同,即具有相同的高度;
	
	2)每个非叶子和非根节点(即内部节点)至少有 t-1 个孩子节点;根至少2个孩子
	
	3)每个节点最多有2t个孩子节点。
	
	4)每个节点内的键都是递增的
	
	5)每个节点的孩子比key的个数多1
	
/**
 * B树中的节点。
 */
private static class BTreeNode<K, V> {
	/**
	 * 节点的项,按键非降序存放,每个节点可以存放多组键值对
	 * 每个节点内的 key 是递增的
	 * 每个节点,最多 2t-1 个key
	 */
	private List<Entry<K, V>> entries;
	/**
	 * 内节点的子节点
	 * 每个节点,至少有t-1个孩子节点,最多有 2t 个孩子节点;根至少2个孩子
	 */
	private List<BTreeNode<K, V>> children;
	/**
	 * 是否为叶子节点
	 */
	private boolean leaf;
	/**
	 * 键的比较函数对象
	 */
	private Comparator<K> kComparator;

	private BTreeNode() {
		entries = new ArrayList<>();
		children = new ArrayList<>();
		leaf = false;
	}
	...
}

推荐阅读:

《Java 数据结构和算法 第二版》
刷题---->LeetCode

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值