//树的前序中序后续递归非递归+层序+按照每层节点输出
package baselearning.tree;
import java.util.*;
class TreeNode {
String val;
TreeNode left;
TreeNode right;
public TreeNode(String val) {
this.val = val;
}
}
public class Orders {
//递归前序
public static TreeNode preOrder(TreeNode tree) {
//中止条件
if (tree == null)
return null;
TreeNode root = tree;
System.out.printf(root.val + " ");
//不用判断直接递归调用
preOrder(tree.left);
preOrder(tree.right);
return root;
}
//前序非递归 用栈辅助操作
public static void preOrder2(TreeNode root) {
//判空
if (root == null)
return;
Stack<TreeNode> stack = new Stack<>();
//先把头结点放进栈里面
stack.push(root);
while (!stack.isEmpty()) {
TreeNode treeNode = stack.pop();
System.out.println(treeNode.val);
if (treeNode.right != null)
stack.push(treeNode.right);
if (treeNode.left != null)
stack.push(treeNode.left);
}
}
//中序
public static TreeNode midOrder(TreeNode tree) {
if (tree == null)
return null;
midOrder(tree.left);
TreeNode root = tree;
System.out.printf(root.val + " ");
//不用判断直接递归调用
midOrder(tree.right);
return root;
}
//中序非递归
public static void midOrder2(TreeNode root) {
//判空
if (root == null)
return;
Stack<TreeNode> stack = new Stack<>();
//设置一个指针指向根节点
TreeNode cur = root;
stack.push(root);
while (!stack.isEmpty() || cur != null) {
while (cur != null) {
stack.push(cur);
//不用判断 直接把指针往左移动
cur = cur.left;
}
//输出 记录当前输出的节点 看他的右孩子有没有
TreeNode treeNode = stack.pop();
System.out.print(treeNode.val + " ");
//先输出值再看右边的孩子
//移动指针 然后不为空就会方进球
if (treeNode.right != null)
cur = treeNode.right;
}
}
//后续
public static TreeNode postOrder(TreeNode tree) {
if (tree == null)
return null;
TreeNode root = tree;
postOrder(tree.left);
postOrder(tree.right);
System.out.printf(root.val + " ");
//不用判断直接递归调用
return root;
}
//后续 左右根 先序 根左右 先放右再放左
//在先序的基础上更改 先放左再放右 根右左 再逆序 左右根
//用两个栈
public static void postOrder2(TreeNode root) {
//先序后再改进
if (root == null)
return;
Stack<TreeNode> stack = new Stack<>();
Stack<TreeNode> stack2 = new Stack<>();
//先把根节点放入栈中
stack.push(root);
while (!stack.isEmpty()) {
//先放右后放左边
TreeNode treeNode = stack.pop();
//用stack2存储序列·
stack2.push(treeNode);
if (treeNode.left != null) {
stack.push(treeNode.left);
}
if (treeNode.right != null) {
stack.push(treeNode.right);
}
}
while (!stack2.isEmpty())
System.out.print(stack2.pop().val + " ");
}
/**
* 层序遍历
*
* @param root
*/
public static void bfs(TreeNode root) {
//判空
if (root == null)
return;
//构建队列先进先出
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
TreeNode tree = queue.poll();
System.out.print(tree.val + " ");
if (tree.left != null)
queue.add(tree.left);
if (tree.right != null)
queue.add(tree.right);
}
}
//层序遍历 按照每层的节点数量
//按照每层节点数返回输出
/**
* 构建存储字符串链表的链表 输出形式[['a','b'],['c']]
* 用size记录每层的数量
*
* @param root
* @return
*/
public static List<List<String>> bfs2(TreeNode root) {
//判空
if (root == null)
return null;
//构建结果列表
List<List<String>> res = new ArrayList<>();
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
//记录当前队列的长度 每次出队之前记录
int size = queue.size();
System.out.println(size);
List<String> temp = new ArrayList<>();
while (size-- > 0) {
TreeNode tree = queue.poll();
temp.add(tree.val);
if (tree.left != null)
queue.add(tree.left);
if (tree.right != null)
queue.add(tree.right);
}
//每遍历一层就把一层的东西放进去
res.add(temp);
}
return res;
}
public static void main(String[] args) {
//构建树
TreeNode treeA = new TreeNode("A");
TreeNode treeB = new TreeNode("B");
TreeNode treeC = new TreeNode("C");
TreeNode treeD = new TreeNode("D");
TreeNode treeE = new TreeNode("E");
TreeNode treeF = new TreeNode("F");
TreeNode treeG = new TreeNode("G");
treeA.left = treeB;
treeA.right = treeC;
treeB.left = treeD;
treeB.right = treeE;
treeC.right = treeF;
treeE.left = treeG;
// preOrder(treeA);
// postOrder(treeA);
// System.out.println();
// postOrder2(treeA);
// System.out.println();
bfs(treeA);
System.out.println();
System.out.println(bfs2(treeA));
}
}
参考视频:
java高频算法题(二叉树遍历)_哔哩哔哩_bilibili
//二叉排序树的增加删除查找 删除真的很难要多看看
package baselearning.tree;
/*
二叉搜索树的构建增删改查
*/
//存储的数据元素是必须可以比较的 并且树可以迭代
class TreeNode1 {
public int val;
public TreeNode1 left;
public TreeNode1 right;
public TreeNode1(int val) {
this.val = val;
}
}
public class BinarySearchTree {
//构建一个根节点
public TreeNode1 root;
//添加方法
public boolean insert(int val) {
//判断是否为空 如果是空的话直接创建
if (root == null) {
root = new TreeNode1(val);
return true;
}
//不为空的情况 preCur指向上一个节点
TreeNode1 preCur = root;
//cur指向当前节点
TreeNode1 cur = null;
//当cur超出叶子节点后,此时的 preCur指向要插入的叶子节点
//二叉搜索树 左边《根《右边
while (preCur != null) {
//上一个节点小于要插入的数值
if (preCur.val < val) {
//保存上一个节点
cur = preCur;
//往右走
preCur = preCur.right;
} else if (preCur.val > val) {
cur = preCur;
//往左走
preCur = preCur.left;
} else {
return false;
}
}
//在原有树上比较晚了找到了位置 curPre成为了叶子结点
if (cur.val < val) {
cur.right = new TreeNode1(val);
} else {
cur.left = new TreeNode1(val);
}
return true;
}
//查找
public boolean search(int val) {
if (root == null) return false;
TreeNode1 cur = root;
while (cur != null) {
if (cur.val < val)
cur = cur.right;
else if (cur.val > val)
cur = cur.left;
else return true;
}
return false;
}
//替换元素 删除的时候是要更改二叉树的数值的
public boolean remove(int val) {
if (root == null)
return false;
//循环找到要删除的元素
TreeNode1 cur = root;
TreeNode1 curpre = null;
while (cur != null) {
if (cur.val < val) {
//左侧查找 记录当前的指针
curpre = cur;
cur = cur.left;
} else if (cur.val > val) {
//左侧查找 记录当前的指针
curpre = cur;
cur = cur.right;
} else {
//找到该节点删除节点
removeNode(curpre, cur);
return true;
}
}
return false;
}
/**
* @param parent curpre
* @param tmp cur
*/
private void removeNode(TreeNode1 parent, TreeNode1 tmp) {
//分情况
// a.1被删节点的左子树为null
if (tmp.left == null) {
//a.1.1删除节点为根节点
if (tmp == root) {
parent = tmp.right;
//a.1.2删除节点为根节点的右子树
} else if (parent.right == tmp) {
parent.right = tmp.right;
//a.1.3删除节点为根节点的左子树
} else {
parent.left = tmp.right;
}
} else if (tmp.right == null) {
//a.2.1删除节点为根节点
if (tmp == root) {
parent = tmp.left;
//a.1.2删除节点为根节点的右子树
} else if (parent.right == tmp) {
parent.right = tmp.left;
//a.1.3删除节点为根节点的左子树
} else {
parent.left = tmp.left;
}
//a.3删除节点的左右子树都不为null,我使用被删节点的右子树中找最小值
} else {
TreeNode1 curParent = tmp;//记录cur的前一个
TreeNode1 cur = tmp.right;//右子树找Min
//被删节点的右子树下的左子树如果存在,那最小值肯定就在左子树
while (cur.left != null) {
curParent = cur;
cur = cur.left;
}
//此时有两种情况,一种压根没进while(无左子树),一种是进了(有左子树)
//找到最小值并覆盖被删节点的值
tmp.val = cur.val;
//连接跳过最小值
if (cur == curParent.left) {//有左子树
curParent.left = cur.right;//此时cur是最小,连接cur的右子树
} else {//无左子树
curParent.right = cur.right;
}
}
}
//先序遍历
public void preOrder(TreeNode1 root) {
if (root == null) return;
System.out.print(root.val + " ");
preOrder(root.left);
preOrder(root.right);
}
//中序遍历
public void inOrder(TreeNode1 root) {
if (root == null)
return;
inOrder(root.left);
System.out.print(root.val + " ");
inOrder(root.right);
}
public static void main(String[] args) {
BinarySearchTree testBinarySearchTree = new BinarySearchTree();
testBinarySearchTree.insert(13);
testBinarySearchTree.insert(4);
testBinarySearchTree.insert(17);
testBinarySearchTree.insert(5);
testBinarySearchTree.inOrder(testBinarySearchTree.root);
System.out.println();
testBinarySearchTree.preOrder(testBinarySearchTree.root);
System.out.println();
System.out.println(testBinarySearchTree.search(1));
System.out.println(testBinarySearchTree.search(4));
System.out.println(testBinarySearchTree.search(14));
System.out.println(testBinarySearchTree.search(17));
System.out.println("==========================================");
testBinarySearchTree.remove(13);
testBinarySearchTree.inOrder(testBinarySearchTree.root);
System.out.println();
}
}
二叉树的一天+吵架和好的一天
参考链接 写的很好