我必须解决以下问题:给定一个完美的二叉树,它在其节点上存储字符,反转奇数级别的节点。问题和解决方案来自这里:http://www.geeksforgeeks.org/reverse-alternate-levels-binary-tree/。
我正在尝试实施棘手的解决方案。这是我的代码:
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
public class ReverseLevel {
public static class Node{
char id;
Node left;
Node right;
public Node(char id){
this.id = id;
left = null;
right = null;
}
}
static Node root;
static Queue<Node> q;
static int index;
static List<Character> res = new ArrayList<Character>();
public static void main(String[] args) {
createBT();
printLevelbyLevel(root);
reverseLevels(root, 0);
int n = res.size();
System.out.println();
for (int i = 0; i < n; i++) {
System.out.print(res.get(i) + " ");
}
System.out.println();
setLevels(root, 0, n-1);
printLevelbyLevel(root);
}
private static void printLevelbyLevel(Node root2) {
q = new LinkedList<Node>();
q.add(root);
Queue<Node> nextLevel = new LinkedList<Node>();
while(!q.isEmpty()){
Node n = q.remove();
printNode(n);
if(hasLeftChild(n)){
nextLevel.add(n.left);
}
if(hasRightChild(n)){
nextLevel.add(n.right);
}
if(q.isEmpty()){
System.out.println();
while(!nextLevel.isEmpty()){
q.add(nextLevel.poll());
}
}
}
}
private static void reverseLevels(Node root, int level){
if(root == null){
return;
}
reverseLevels(root.left, level+1);
if(level%2 == 1){
res.add(root.id);
}
reverseLevels(root.right, level+1);
}
private static void setLevels(Node root, int level, int index){
if(root == null){
return;
}
setLevels(root.left, level+1, index);
if(level%2 == 1){
root.id = res.get(index);
index--;
}
setLevels(root.right, level+1, index);
}
private static boolean hasRightChild(Node n) {
if(n.right != null)
return true;
return false;
}
private static boolean hasLeftChild(Node n) {
if(n.left != null)
return true;
return false;
}
private static void printNode(Node n) {
System.out.print(n.id + " ");
}
private static void createBT() {
Node n1 = new Node('a');
Node n2 = new Node('b');
Node n3 = new Node('c');
Node n4 = new Node('d');
Node n5 = new Node('e');
Node n6 = new Node('f');
Node n7 = new Node('g');
Node n8 = new Node('h');
Node n9 = new Node('i');
Node n10 = new Node('g');
Node n11 = new Node('k');
Node n12 = new Node('l');
Node n13 = new Node('m');
Node n14 = new Node('n');
Node n15 = new Node('o');
root = n1;
n1.left = n2;
n1.right = n3;
n2.left = n4;
n2.right = n5;
n4.left = n8;
n4.right = n9;
n5.left = n10;
n5.right = n11;
n3.left = n6;
n3.right = n7;
n6.left = n12;
n6.right = n13;
n7.left = n14;
n7.right = n15;
}
}
想法是遍历树in-order
方式,将奇数级别的节点存储在ArrayList
res
中,然后再次遍历in-order
res
中的树{1}}方式,对于奇数级别的每个节点,我将其id替换为res
中的相应值。在第二次有序遍历时,我保留了字段索引,它告诉我res
哪个索引应该获取我的数据。
每当我用index
中的数据替换相应节点中的数据时,我会递减index
。但是因为它是一个递归,如果我进入递归的上层,{{1}}的值与之前相同,并且我没有正确地更改节点的数据。有人可以建议我怎样才能避免这种情况?我已经包含了逐层打印树级别的方法,因此可以看出该方法无法正常工作。
答案 0 :(得分:1)
我承认我没看过你的节目,抓住我的是你提到的odd levels
并且你正在进行inorder
遍历。对我来说这很安静!
如果我要编码,这将是我的方法:
如果我必须在BST中使用级,我会选择level-order-traversal
( BFS简单)并保持跟踪奇怪的水平。
然后,在每个奇数级别上,在deQueue
一个节点的值上,我将它与当前节点值交换。 (就是它 !!)
这更节省空间(不需要堆栈空间)并且在O(n)时间内实现
示例:
10 //Level 0
/ \
5 20 //Level 1
/ \ / \
1 3 12 25 //Level 2
当{1}}为第1级时,enQueue
中的5
和deQueue
20
的{{1}}。{ / p>
现在,只需检查水平是否为奇数。如果是,则将front
ed值与前面的节点值交换!
Queue
答案 1 :(得分:1)
您应该使用java.util.Stack来推送和弹出节点。以下是代码的修改版本:
public class ReverseLevel {
public static class Node {
char id;
Node left;
Node right;
public Node(char id) {
this.id = id;
left = null;
right = null;
}
}
static Node root;
static Queue<Node> q;
static int index;
static Stack<Character> stack = new Stack<Character>();
public static void main(String[] args) {
createBT();
printLevelbyLevel(root);
reverseLevels(root, 0);
setLevels(root, 0);
printLevelbyLevel(root);
}
private static void printLevelbyLevel(Node root2) {
q = new LinkedList<Node>();
q.add(root);
Queue<Node> nextLevel = new LinkedList<Node>();
while (!q.isEmpty()) {
Node n = q.remove();
printNode(n);
if (hasLeftChild(n)) {
nextLevel.add(n.left);
}
if (hasRightChild(n)) {
nextLevel.add(n.right);
}
if (q.isEmpty()) {
System.out.println();
while (!nextLevel.isEmpty()) {
q.add(nextLevel.poll());
}
}
}
}
private static void reverseLevels(Node root, int level) {
if (root == null) {
return;
}
reverseLevels(root.left, level + 1);
if (level % 2 == 1) {
stack.push(root.id);
}
reverseLevels(root.right, level + 1);
}
private static void setLevels(Node root, int level) {
if (root == null) {
return;
}
setLevels(root.left, level + 1);
if (level % 2 == 1) {
root.id = stack.pop();
}
setLevels(root.right, level + 1);
}
private static boolean hasRightChild(Node n) {
if (n.right != null)
return true;
return false;
}
private static boolean hasLeftChild(Node n) {
if (n.left != null)
return true;
return false;
}
private static void printNode(Node n) {
System.out.print(n.id + " ");
}
private static void createBT() {
Node n1 = new Node('a');
Node n2 = new Node('b');
Node n3 = new Node('c');
Node n4 = new Node('d');
Node n5 = new Node('e');
Node n6 = new Node('f');
Node n7 = new Node('g');
Node n8 = new Node('h');
Node n9 = new Node('i');
Node n10 = new Node('g');
Node n11 = new Node('k');
Node n12 = new Node('l');
Node n13 = new Node('m');
Node n14 = new Node('n');
Node n15 = new Node('o');
root = n1;
n1.left = n2;
n1.right = n3;
n2.left = n4;
n2.right = n5;
n4.left = n8;
n4.right = n9;
n5.left = n10;
n5.right = n11;
n3.left = n6;
n3.right = n7;
n6.left = n12;
n6.right = n13;
n7.left = n14;
n7.right = n15;
}
}
答案 2 :(得分:0)
在调用 reverseLevels()后使用 Collections.reverse(res)。这将颠倒您的ArrayList。
在函数 setLevels()中而不是代码
if(level%2 == 1)
{
root.id = res.get(index);
index--;
}
使用下面的代码段。然后就不需要使用索引,因为您想要的元素是第一个元素,然后将其删除。
if(level%2 == 1)
{
root.id = res.get(0);
res.remove(0);
}