二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。 通常的方法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址 。链式结构又分为二叉链和三叉链,这篇博客重在研究二叉链。
- 二叉树的链式存储结构如下图所示:
- 以下述二叉树为例,它的链式存储结构如下:
可以看得出来二叉树的链式存储和链表基本是一样的。 - 下面是自己总结的一些关于二叉树的经典笔试面试题,仅供大家参考:
package com.xxx;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
/**
* Description: 二叉树
* Author: admin
* Create: 2019-06-06 20:09
*/
public class TestBinaryTree {
class TreeNode {
char value;
TreeNode left;
TreeNode right;
public TreeNode(char value) {
this.value = value;
}
}
public int i = 0;
//根据字符串创建二叉树
public TreeNode createTestTree(String s) {
TreeNode root = null;
if (s.charAt(i) != '#') {
root = new TreeNode(s.charAt(i));
i++;
root.left = createTestTree(s);
root.right = createTestTree(s);
}else {
i++;
}
return root;
}
//结点个数
public int getSize(TreeNode root) {
if (root == null) {
return 0;
}
return getSize(root.left) + getSize(root.right) + 1;
}
//叶子节点的个数
public int getLeafSize(TreeNode root) {
if (root == null) {
return 0;
}
if (root.left == null && root.right == null) {
return 1;
}
return getLeafSize(root.left) + getLeafSize(root.right);
}
//第k层节点个数
public int getKLevelSize(TreeNode root, int k) {
if (root == null) {
return 0;
}else if (k == 1) {
return 1;
}
return getKLevelSize(root.left, k-1) + getKLevelSize(root.right, k-1);
}
//依次在二叉树的根、左子树、右子树中查找value,如果找到,返回结点,否则返回null
public TreeNode find(TreeNode root, int value) {
if (root == null) {
return null;
}
if (root.value == value) {
return root;
}
TreeNode ret = find(root.left, value);
if (ret != null) {
return ret;
}
ret = find(root.right, value);
if (ret != null) {
return ret;
}
return null;
}
//二叉树的高度
public int height(TreeNode root) {
if (root == null) {
return 0;
}else {
int leftHeight = height(root.left);
int rightHead = height(root.right);
return (leftHeight > rightHead ? leftHeight : rightHead) + 1;
}
}
//判断一棵树是否是完全二叉树,返回0代表是完全二叉树
public int binaryTreeComplete(TreeNode root) {
Queue<TreeNode> queue = new LinkedList<>();
if (root != null) {
queue.offer(root);
}
while (!queue.isEmpty()) {
TreeNode top = queue.poll();
if (top != null) {
queue.offer(root.left);
queue.offer(root.right);
}else {
break;
}
}
while (!queue.isEmpty()) {
if (queue.peek() == null) {
queue.poll();
}else {
return -1;
}
}
return 0;
}
//检查两棵树是否相同
public boolean isSameTree(TreeNode p, TreeNode q) {
if (p == null && q == null) {
return true;
}
if ((p == null && q != null) || (p != null && q == null)) {
return false;
}
if (p.value != q.value) {
return false;
}
return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
}
//另一棵树的子树
public boolean isSubtree(TreeNode s, TreeNode t) {
if (s == null || t == null) {
return false;
}
if (isSameTree(s, t)) {
return true;
}else if (isSubtree(s.left, t)) {
return true;
} else if (isSubtree(s.right, t)) {
return true;
}else {
return false;
}
}
//判断一颗二叉树是否是平衡二叉树 O(n^2)
public boolean isBalanced(TreeNode root) {
if (root == null) {
return true;
}else {
int leftHeight = height(root.left);
int rightHeight = height(root.right);
return Math.abs(leftHeight - rightHeight) < 2
&& isBalanced(root.left) && isBalanced(root.right);
}
}
//对称二叉树
public boolean isSymmetricChild(TreeNode leftTree, TreeNode rightTree) {
if ((leftTree == null && rightTree != null)
|| (leftTree != null && rightTree == null)) {
return false;
}
if (leftTree == null && rightTree == null) {
return true;
}
return leftTree.value == rightTree.value
&& isSymmetricChild(leftTree.left, rightTree.right)
&& isSymmetricChild(leftTree.right, rightTree.left);
}
public boolean isSymmetric(TreeNode root) {
if (root == null) {
return true;
}
return isSymmetricChild(root.left, root.right);
}
//根据二叉树创建字符串
public void tree2strChild(TreeNode t, StringBuilder sb) {
if (t == null) {
return;
}
sb.append(t.value);
if (t.left != null) {
sb.append("(");
tree2strChild(t.left, sb);
sb.append(")");
}else {
if (t.right == null) {
return;
}else {
sb.append("()");
}
}
if (t.right == null) {
return;
}else {
sb.append("(");
tree2strChild(t.right, sb);
sb.append(")");
}
}
public String tree2str(TreeNode t) {
StringBuilder sb = new StringBuilder();
tree2strChild(t, sb);
return sb.toString();
}
}