记录二叉查找树常用方法
- 相关概念
- 二叉树,且有序,如:任意节点大于左节点 且 小于右节点 【若左右节点存在】
- 树节点类结构
public static class Node {
int val;
Node left;
Node right;
}
- 创建固定层级的随机二叉查找树
// min: 整棵树最小节点值; max: 整棵树最大节点值;maxLevel:最大层级
// 使用方式: Node node = genRandomBST(0, 100, 3);
public static Node genRandomBST(int min, int max, int maxLevel) {
return createRandomBST(min, max, 1, maxLevel);
}
public static Node createRandomBST(int min, int max, int level, int maxLevel) {
if (min > max || level > maxLevel) {
return null;
}
Node node = new Node(random(min, max));
node.left = createRandomBST(min, node.val - 1, level+1, maxLevel);
node.right = createRandomBST(node.val + 1, max, level+1, maxLevel);
return node;
}
// 区间内随机取值
public static int random(int min, int max) {
Random random = new Random();
int s = random.nextInt(max-min+1)+min;
return s;
}
- 递归后续遍历
public static List<Integer> postIterator(Node head) {
List<Integer> list = new ArrayList<>();
postRecursion(head, list);
return list;
}
// 后续遍历形式
public static void postRecursion(Node head, List<Integer> list) {
if (head != null) {
postIterator(head.left, list);
postIterator(head.right, list);
list.add(head.val); // 后续遍历【位置不同遍历顺序不同】
}
}
递归遍历二叉树,代码形式非常简单;仔细思考执行过程,方法调用间的入栈与出栈起到了关键作用
非递归调用写法,可以参考递归调用方法栈的思路
- 非递归后续遍历
public static List<Integer> postIteratorWhile(Node head) {
// 节点值栈
List<Integer> list = new ArrayList<>();
if (head == null) {
return list;
}
// 节点栈
Stack<Node> stack = new Stack<>();
do {
if (stack.isEmpty()) {
// 首节点压栈
stack.push(head);
}
// 当前操作的节点出栈
Node curr = stack.pop();
// 遍历过的节点值入栈【list:反向遍历后与栈效果相同】
list.add(curr.val);
if (curr.left != null) {
stack.push(curr.left);
}
if (curr.right != null) {
stack.push(curr.right);
}
} while (!stack.isEmpty());
// 节点值反向遍历 即:后进先出
Collections.reverse(list);
return list;
}
- 根据后序数组构建树
public static Node postArrTree(int[] postArr) {
return postArrTree(postArr, 0, postArr.length-1);
}
public static Node postArrTree(int[] arr, int l, int r) {
if (l > r) {
return null;
}
Node head = new Node(arr[r]);
if (l == r) {
return head;
}
int M = l - 1;
int left = l;
int right = r;
// 类二分法查找到mid值
while (left <= right) {
int mid = left + ((right - left) >> 1);
if (arr[mid] < arr[r]) {
M = mid;
left = mid + 1;
} else {
right = mid - 1;
}
}
// 上面的二分法与for 循环效果一样
// int M = l - 1;
// for (int i = l; i < r; i++) {
// if (arr[i] < arr[r]) {
// M = i;
// }
// }
head.left = process3(arr, l, M);
head.right = process3(arr, M + 1, r - 1);
return head;
}