(1)、在二叉树中找到一个节点的后继节点
【题目】 现在有一种新的二叉树节点类型如下:
public class Node {
public int value;
public Node left;
public Node right;
public Node parent;
public Node(int data) {
this.value = data;
}
}
该结构比普通二叉树节点结构多了一个指向父节点的parent指针。假设有一棵Node类型的节点组成的二叉树,树中每个节点的parent指针都正确地指向自己的父节点,头节点的parent指向null。只给一个在二叉树中的某个节点node,请实现返回node的后继节点的函数。在二叉树的中序遍历的序列中, node的下一个节点叫作node的后继节点。
找到二叉树中某节点的前继节点
public class Demo {
public static class Node {
public int value;
public Node left;
public Node right;
public Node parent;
public Node(int data) {
this.value = data;
}
}
public static void main(String[] args) {
Node node = new Node(1);
node.left = new Node(2);
node.left.parent = node;
node.left.left = new Node(4);
node.left.left.parent = node.left;
node.left.right = new Node(5);
node.left.right.parent = node.left;
node.right = new Node(3);
node.right.parent = node;
node.right.left = new Node(6);
node.right.left.parent = node.right;
node.right.right = new Node(7);
node.right.right.parent = node.right;
Node node1 = findNode(node.right.right);
if(node1 == null){
System.out.println("null");
}else{
System.out.println(node1.value);
}
}
public static Node findNode(Node node) {
if (node == null) {
return node;
}
if (node.right != null) {
//有右子树,就是右子树最左的节点
return getNext(node.right);
}
//如果没有右子树,则找到使得这个节点成为左子树的节点
Node nodeParent = node.parent;
while (nodeParent != null && nodeParent.left != node) {
node = nodeParent;
nodeParent = nodeParent.parent;
}
return nodeParent;
}
public static Node getNext(Node node) {
while (node.left != null) {
node = node.left;
}
return node;
}
}
(2)、二叉树的序列化和反序列化
//先序遍历序列化
public static String binaryTreeToString(Node node) {
if (node == null) {
return "#_";
}
String str = node.value + "_";
str += binaryTreeToString(node.left);
str += binaryTreeToString(node.right);
return str;
}
public static Node stringToBinaryTree(String str) {
String[] s = str.split("_");
Queue<String> queue = new LinkedList<String>();
for (String s1 : s) {
queue.add(s1);
}
return stringToBinaryTree(queue);
}
public static Node stringToBinaryTree(Queue<String> queue){
String value = queue.poll();
if( value.equals("#")){
return null;
}
Node node = new Node(Integer.valueOf(value));
node.left = stringToBinaryTree(queue);
node.right = stringToBinaryTree(queue);
return node;
}
二叉树按层序列化
准备一个队列,用于存储每一层节点的信息
public static String layerString(Node node){
if(node == null){
return "#_";
}
String str = node.value + "_";
Queue<Node> queue = new LinkedList<Node>();
queue.add(node);
while(!queue.isEmpty()){
node = queue.poll();
str += node.value + "_";
if(node.left != null){
queue.add(node.left);
str = node.left.value +"_";
}else{
str += "#_";
}
if(node.right!= null){
queue.add(node.right);
str = node.right.value +"_";
}else{
str += "#_";
}
}
return str;
}
(5)、判断一棵二叉树是否是平衡二叉树
在树中任何一个节点,它左子树和右子树的高度差不超过一,这叫平衡二叉树。
//是平衡二叉树则返回树的高度,否则返回-1
public static int balanceTest(Node node) {
if (node == null) {
return 0;
}
int left = balanceTest(node.left);
if (left == -1) {
return -1;
}
int right = balanceTest(node.right);
if (right == -1) {
return -1;
}
if (Math.abs(left - right) > 1) {
return -1;
} else {
return Math.max(left, right) + 1;
}
}
(6)、判断一棵树是否是搜索二叉树、判断一棵树是否是完全二叉树
搜索二叉树:左子树比他小,右子树比他大
中序遍历依次升序的就是
public static boolean isBST(Node node) {
if (node == null) {
return true;
}
int min = Integer.MIN_VALUE;
Stack<Node> stack = new Stack<Node>();
stack.push(node);
while (!stack.isEmpty() || node != null) {
if (node != null) {
stack.push(node);
node = node.left;
} else {
node = stack.pop();
if (node.value < min) {
return false;
}
node = node.right;
}
}
return true;
}
完全二叉树怎么判断?
按层遍历,以下条件按照顺序判断
1、如果一个子树有右孩子没左孩子肯定不是完二叉。返回false
2、如果一个节点,不是左右孩子都全,出现这种情况,他后面出现的节点,都必须是叶子节点,否则false。
State状态一开始是false,遇到二的情况变true,遇到后续节点不是叶子节点就直接返回false
public static boolean isCBT(Node node) {
if (node == null) {
return true;
}
boolean flag = false;
Queue<Node> queue = new LinkedList<Node>();
queue.offer(node);
while (!queue.isEmpty()) {
node = queue.poll();
if ((flag && (node.left != null || node.right != null)) || (node.left == null && node.right != null)) {
return false;
}
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
} else {//右子树为空左子树不为空或者根本不会遍历到这两个null节点
flag = true;
}
}
return true;
}
(7)、已知一棵完全二叉树,求其节点的个数
public static int nodeSum(Node node){
if(node == null){
return 0;
}
int sum = 1;
Queue<Node> queue = new LinkedList<Node>();
queue.offer(node);
while(!queue.isEmpty()){
node = queue.poll();
if(node.left != null){
queue.offer(node.left);
sum++;
}
if(node.right != null){
queue.offer(node.right);
sum++;
}
}
return sum;
}
(8)、折纸问题
请把一段纸条竖着放在桌子上,然后从纸条的下边向上方对折1次,压出折痕后展开。此时折痕是凹下去的,即折痕突起的方向指向纸条的背面。如果从纸条的下边向上方连续对折2次,压出折痕后展开,此时有三条折痕,从上到下依次是下折痕、下折痕和上折痕。给定一个输入参数N,代表纸条都从下边向上方连续对折N次,请从上到下打印所有折痕的方向。
折一次:下
折两次:下下上
折三次:下下上下下上上
在二叉树中就是中序遍历。整棵树的头结点是下折横,每棵左子树的头结点是下折横,每棵右子树的头结点是上折痕。
public class Demo {
public static void main(String[] args) {
print(2);
}
public static void print(int N) {
if (N <= 0) {
return;
}
print(1, N, true);
}
public static void print(int i, int N, boolean flag) {
if (i > N) {
return;
}
print(i + 1, N, true);
System.out.println(flag ? "down" : "up");
print(i + 1, N, false);
}
}