一、认识二叉树
二叉树 二叉树 二叉树 二叉搜索树
满二叉树 平衡二叉树 二叉搜索树
二、二叉搜索树
1、判断二叉树是否是二叉搜索树
核心代码:
/**
* 判断二叉树是否是二分搜索树
* @param curr
* @return
*/
public boolean isBst(TreeNode curr){
List<Integer>list = new ArrayList<>();
inOrder(curr,list);
for(int i=1;i<list.size();i++){
if(list.get(i) < list.get(i-1)){
return false;
}
}
return true;
}
/**
* 中序遍历二叉树,将二叉树中的节点值添加到list集合中
* @param curr
* @param list
*/
public void inOrder(TreeNode curr, List<Integer> list){
if(curr == null){
return;
}
inOrder(curr.left, list);
list.add(curr.val);
inOrder(curr.right, list);
}
2、判断二叉树是否是平衡二叉树(通过判断平衡因子是否超过1)
核心代码:
/**
* 获取二叉树的平衡因子
* @param curr
* @return
*/
public int balanceFactor(TreeNode curr){
if(curr == null){
return 0;
}
return Math.abs(getheight(curr.right) - getheight(curr.left));
}
/**
* 获取二叉树的高度
* @return
*/
public int getheight(TreeNode curr){
if(curr == null){
return 0;
}
return curr.height;
}
3、中序图形效果打印二叉树
public class TreePrint<E> {
private final List<TreeNode> mid = new ArrayList<>();//记录bst树的节点
private final Map<TreeNode, Integer> map = new HashMap<>();//记录节点及位置
private Queue<E> queue = new ArrayDeque<>();
private TreeNode root;
public TreePrint() {
}
public TreePrint(TreeNode root) {
this.root = root;
}
/**
* 中序遍历
*
* @param root 树的根节点
*/
public void inOrder(TreeNode root) {
if (root == null) {
return;
}
inOrder(root.left);
mid.add(root);
inOrder(root.right);
}
/**
* 使用Map记录节点及位置
*
* @param root
*/
public void init(TreeNode root) {
if (root == null) {
return;
}
inOrder(root);
for (int i = 0; i < mid.size(); i++) {
map.put(mid.get(i), i);
}
}
/**
* 打印同一层的节点,使用|线和值进行拼接打印
*
* @param TreeNodes
*/
void printLevelTreeNodes(List<TreeNode> TreeNodes) {
StringBuilder VLine = new StringBuilder();
StringBuilder dataLine = new StringBuilder();
StringBuilder line = new StringBuilder();
int lastTreeNodeIndex = 0;
int lastRightIndex = 0;
for (TreeNode TreeNode : TreeNodes) {
int x = map.get(TreeNode);
String addEmpty = getEmpty(x - lastTreeNodeIndex);
lastTreeNodeIndex = x;
VLine.append(addEmpty).append("|");//竖线拼接
dataLine.append(addEmpty).append(TreeNode.val); //值拼接
TreeNode left = TreeNode.left;
TreeNode right = TreeNode.right;
String leftLine = null;
String rightLine = null;
int leftIndex = -1;
int rightIndex = -1;
if (left != null) {
leftIndex = map.get(left);
leftLine = getLineToChildren(x - leftIndex);
}
if (right != null) {
rightIndex = map.get(right);
rightLine = getLineToChildren(rightIndex - x);
}
String curLine = (leftLine == null ? "" : leftLine) + "|" + (rightLine == null ? "" : rightLine);
if (leftLine == null && rightLine == null) curLine = "";
//线段之间的间隔
int dif = (leftIndex == -1 ? x : leftIndex) - lastRightIndex;
String difEmpty = getEmpty(dif);
line.append(difEmpty).append(curLine);//拼接线段
lastRightIndex = rightIndex == -1 ? x : rightIndex;
}
System.out.println(VLine + "\n" + dataLine + "\n" + line);
}
String getEmpty(int x) {
StringBuilder empty = new StringBuilder();
for (int i = 0; i < x; i++) {
empty.append("\t");
}
return empty.toString();
}
//链接子线段的长度
String getLineToChildren(int end) {
StringBuilder line = new StringBuilder();
if (end == 0) return line.toString();
for (int i = 0; i < end; i++) {
line.append("____");
}
return line.toString();
}
/**
* 扫描每一行中每一个节点的左右节点
*
* @param lineTreeNodes 每一行的节点
*/
public void topToDownLevelPrint(List<TreeNode> lineTreeNodes) {
if (lineTreeNodes.isEmpty()) return;
printLevelTreeNodes(lineTreeNodes);//打印同一层的节点
List<TreeNode> children = new ArrayList<>(); //记录当前节点下的所有子节点
//记录当前节点下的所有左右节点
for (TreeNode currentTreeNode : lineTreeNodes) {
if (currentTreeNode.left != null) children.add(currentTreeNode.left);
if (currentTreeNode.right != null) children.add(currentTreeNode.right);
}
topToDownLevelPrint(children);//递归打印下一层节点
}
public void print(TreeNode root) {
init(root);
topToDownLevelPrint(new ArrayList<TreeNode>() {{
add(root);
}});
}
}