diff --git a/trees/BST.java b/trees/BST.java new file mode 100644 index 0000000..50647ee --- /dev/null +++ b/trees/BST.java @@ -0,0 +1,552 @@ +package trees; + +import java.util.LinkedList; + +public class BST { + private class Node { + int data; + Node left; + Node right; + } + + private Node root; + private int size; + + public BST(int[] pre, int[] in){ + this.root = this.construct(pre, 0, pre.length - 1, in, 0, in.length - 1); + } + + private Node construct(int[] pre, int plo, int phi, int[] in, int ilo, int ihi){ + if(plo > phi){ + return null; + } + + // create and attach data + Node node = new Node(); + this.size++; + + node.data = pre[plo]; + + // search in ino -> to know the number of elements on left side + int srchIdx = -1; + for(int i = ilo; i <= ihi; i++){ + if(in[i] == pre[plo]){ + srchIdx = i; + break; + } + } + + int nelOnls = srchIdx - ilo; + + // set left + node.left = this.construct(pre, plo + 1, plo + nelOnls, in, ilo, srchIdx - 1); + + // set right + node.right = this.construct(pre, plo + nelOnls + 1, phi, in, srchIdx + 1, ihi); + + return node; + } + + public BST(int[] sa){ + this.root = this.construct(sa, 0, sa.length - 1); + } + + private Node construct(int[] sa, int lo, int hi){ + if(lo > hi){ + return null; + } + + int mid = (lo + hi) / 2; + + Node node = new Node(); + this.size++; + node.data = sa[mid]; + + node.left = this.construct(sa, lo, mid - 1); + node.right = this.construct(sa, mid + 1, hi); + + return node; + } + + public void display() { + this.display(this.root); + } + + private void display(Node node) { + if (node == null) { + return; + } + + String str = ""; + + if (node.left != null) { + str += node.left.data; + } else { + str += "."; + } + + str += " => " + node.data + " <= "; + + if (node.right != null) { + str += node.right.data; + } else { + str += "."; + } + + System.out.println(str); + + this.display(node.left); + this.display(node.right); + } + + public int size() { + return this.size; + } + + public boolean isEmpty() { + return this.size() == 0; + } + + public int size2() { + return this.size2(this.root); + } + + private int size2(Node node) { + if (node == null) { + return 0; + } + + int ls = this.size2(node.left); + int rs = this.size2(node.right); + + return ls + rs + 1; + } + + public int max() { + return this.max(this.root); + } + + private int max(Node node) { + if(node.right != null){ + return this.max(node.right); + } else { + return node.data; + } + } + + public int height() { + return this.height(this.root); + } + + private int height(Node node) { + if (node == null) { + return -1; + } + + int lh = this.height(node.left); + int rh = this.height(node.right); + return Math.max(lh, rh) + 1; + } + + public boolean find(int data) { + return this.find(this.root, data); + } + + private boolean find(Node node, int data) { + if (node == null) { + return false; + } + + if(data > node.data){ + return find(node.right, data); + } else if(data < node.data){ + return find(node.left, data); + } else // equal + { + return true; + } + } + + public int diameter() { + return this.diameter(this.root); + } + + public int diameter(Node node) { + if (node == null) { + return 0; + } + + int ld = this.diameter(node.left); // on the left subtree what is + // maximum edge distance between any + // pair of nodes + int rd = this.diameter(node.right); // on the right subtree what is + // maximum edge distance between any + // pair of nodes + + int lh = this.height(node.left); + int rh = this.height(node.right); + + int rootFactor = lh + rh + 2; + return Math.max(rootFactor, Math.max(ld, rd)); + } + + public int diameter2() { + return this.diameter2(this.root).diameter; + } + + public DiaPair diameter2(Node node) { + if (node == null) { + DiaPair bp = new DiaPair(); + + bp.height = -1; + bp.diameter = 0; + + return bp; + } + + DiaPair lp = this.diameter2(node.left); + DiaPair rp = this.diameter2(node.right); + + DiaPair mp = new DiaPair(); + + mp.height = Math.max(lp.height, rp.height) + 1; + mp.diameter = Math.max(lp.height + rp.height + 2, Math.max(lp.diameter, rp.diameter)); + + return mp; + } + + private class DiaPair { + int height; + int diameter; + } + + public boolean IsBalanced() { + return this.IsBalanced(this.root).isBalanced; + } + + private BalancedPair IsBalanced(Node node) { + if (node == null) { + BalancedPair bp = new BalancedPair(); + + bp.height = -1; + bp.isBalanced = true; + + return bp; + } + + BalancedPair lp = IsBalanced(node.left); + BalancedPair rp = IsBalanced(node.right); + + BalancedPair mp = new BalancedPair(); + + mp.height = Math.max(lp.height, rp.height) + 1; + + if (lp.isBalanced && rp.isBalanced && Math.abs(lp.height - rp.height) <= 1) { + mp.isBalanced = true; + } else { + mp.isBalanced = false; + } + + return mp; + } + + private class BalancedPair { + int height; + boolean isBalanced; + } + + public void preOrder() { + this.preOrder(this.root); + System.out.println("."); + } + + private void preOrder(Node node) { + if (node == null) { + return; + } + + System.out.print(node.data + ", "); + this.preOrder(node.left); + this.preOrder(node.right); + } + + public void postOrder() { + this.postOrder(this.root); + System.out.println("."); + } + + private void postOrder(Node node) { + if (node == null) { + return; + } + + this.postOrder(node.left); + this.postOrder(node.right); + System.out.print(node.data + ", "); + } + + public void inOrder() { + this.inOrder(this.root); + System.out.println("."); + } + + private void inOrder(Node node) { + if (node == null) { + return; + } + + this.inOrder(node.left); + System.out.print(node.data + ", "); + this.inOrder(node.right); + } + + public void levelOrder() { + LinkedList queue = new LinkedList<>(); + queue.addLast(this.root); + + while (queue.size() != 0) { + Node temp = queue.removeFirst(); + + System.out.print(temp.data + ", "); + + if (temp.left != null) { + queue.addLast(temp.left); + } + + if (temp.right != null) { + queue.addLast(temp.right); + } + } + + System.out.println(""); + } + + public void preOrderI() { + LinkedList stack = new LinkedList<>(); + + stack.addFirst(new OrderPair(this.root)); + while (stack.size() != 0) { + OrderPair temp = stack.getFirst(); + + if (temp.selfDone == false) { + System.out.print(temp.node.data + ", "); + temp.selfDone = true; + } else if (temp.leftDone == false) { + if (temp.node.left != null) { + OrderPair leftPair = new OrderPair(temp.node.left); + stack.addFirst(leftPair); + } + temp.leftDone = true; + } else if (temp.rightDone == false) { + if (temp.node.right != null) { + OrderPair rightPair = new OrderPair(temp.node.right); + stack.addFirst(rightPair); + } + temp.rightDone = true; + } else { + stack.removeFirst(); + } + } + System.out.println(); + } + + public void inOrderI() { + LinkedList stack = new LinkedList<>(); + + stack.addFirst(new OrderPair(this.root)); + while (stack.size() != 0) { + OrderPair temp = stack.getFirst(); + + if (temp.leftDone == false) { + if (temp.node.left != null) { + OrderPair leftPair = new OrderPair(temp.node.left); + stack.addFirst(leftPair); + } + temp.leftDone = true; + } else if (temp.selfDone == false) { + System.out.print(temp.node.data + ", "); + temp.selfDone = true; + } else if (temp.rightDone == false) { + if (temp.node.right != null) { + OrderPair rightPair = new OrderPair(temp.node.right); + stack.addFirst(rightPair); + } + temp.rightDone = true; + } else { + stack.removeFirst(); + } + } + System.out.println(); + } + + public void postOrderI() { + LinkedList stack = new LinkedList<>(); + + stack.addFirst(new OrderPair(this.root)); + while (stack.size() != 0) { + OrderPair temp = stack.getFirst(); + + if (temp.leftDone == false) { + if (temp.node.left != null) { + OrderPair leftPair = new OrderPair(temp.node.left); + stack.addFirst(leftPair); + } + temp.leftDone = true; + } else if (temp.rightDone == false) { + if (temp.node.right != null) { + OrderPair rightPair = new OrderPair(temp.node.right); + stack.addFirst(rightPair); + } + temp.rightDone = true; + } else if (temp.selfDone == false) { + System.out.print(temp.node.data + ", "); + temp.selfDone = true; + } else { + stack.removeFirst(); + } + } + System.out.println(); + } + + private class OrderPair { + Node node; + + boolean selfDone; + boolean leftDone; + boolean rightDone; + + OrderPair(Node node) { + this.node = node; + } + } + + public void printrange(int lo, int hi){ + this.printrange(this.root, lo, hi); + } + + private void printrange(Node node, int lo, int hi){ + if (node == null) { + return; + } + + if(node.data < lo){ + printrange(node.right, lo, hi); + } else if(node.data > hi){ + printrange(node.left, lo, hi); + } else if(node.data >= lo && node.data <= hi){ + printrange(node.left, lo, hi); + System.out.println(node.data); + printrange(node.right, lo, hi); + } + } + + private class HeapMover{ + int sum = 0; + } + + public void replaceWSumLarger(){ + HeapMover mover = new HeapMover(); + this.replaceWSumLarger(this.root, mover); + } + + private void replaceWSumLarger(Node node, HeapMover mover){ + if(node == null){ + return; + } + + replaceWSumLarger(node.right, mover); + + int temp = node.data; + node.data = mover.sum; + mover.sum += temp; + + replaceWSumLarger(node.left, mover); + } + + public void replaceWSumLarger1(){ + this.replaceWSumLarger1(this.root, 0); + } + + private int replaceWSumLarger1(Node node, int sum){ + if(node == null){ + return sum; + } + + int orsplusrsf = replaceWSumLarger1(node.right, sum); + + int temp = node.data; + node.data = orsplusrsf; + + int finalSum = replaceWSumLarger1(node.left, orsplusrsf + temp); + return finalSum; + } + + public void addNode(int data){ + addNode(root, data); + } + + public void addNode(Node node, int data){ + if(data > node.data){ + if(node.right == null){ + node.right = new Node(); + node.right.data = data; + size++; + } else { + addNode(node.right, data); + } + } else if(data < node.data){ + if(node.left == null){ + node.left = new Node(); + node.left.data = data; + size++; + } else { + addNode(node.left, data); + } + } else { + + } + } + + public void removeNode(int data){ + this.removeNode(data, null, this.root, true); + } + + private void removeNode(int data, Node parent, Node child, boolean ilc){ + if(data > child.data){ + removeNode(data, child, child.right, false); + } else if(data < child.data){ + removeNode(data, child, child.left, true); + } else { + if(child.left != null && child.right != null){ + int lmax = this.max(child.left); + child.data = lmax; + this.removeNode(lmax, child, child.left, true); + } else if(child.left != null){ + if(ilc){ + parent.left = child.left; + } else { + parent.right = child.left; + } + + this.size--; + } else if(child.right != null){ + if(ilc){ + parent.left = child.right; + } else { + parent.right = child.right; + } + + this.size--; + } else { + if(ilc){ + parent.left = null; + } else { + parent.right = null; + } + + this.size--; + } + } + } + +} diff --git a/trees/BSTClient.java b/trees/BSTClient.java new file mode 100644 index 0000000..c7c3ded --- /dev/null +++ b/trees/BSTClient.java @@ -0,0 +1,10 @@ +package trees; + +public class BSTClient { + + public static void main(String[] args) { + // TODO Auto-generated method stub + + } + +} diff --git a/trees/BinaryClient.java b/trees/BinaryClient.java new file mode 100644 index 0000000..fd92b7d --- /dev/null +++ b/trees/BinaryClient.java @@ -0,0 +1,10 @@ +package trees; + +public class BinaryClient { + + public static void main(String[] args) { + // TODO Auto-generated method stub + + } + +} diff --git a/trees/BinaryTree.java b/trees/BinaryTree.java new file mode 100644 index 0000000..b0b2ebc --- /dev/null +++ b/trees/BinaryTree.java @@ -0,0 +1,556 @@ +package trees; + +import java.util.LinkedList; +import java.util.Scanner; + +public class BinaryTree { + private class Node { + int data; + Node left; + Node right; + } + + private Node root; + private int size; + + public BinaryTree(int[] pre, int[] in){ + this.root = this.construct(pre, 0, pre.length - 1, in, 0, in.length - 1); + } + + private Node construct(int[] pre, int plo, int phi, int[] in, int ilo, int ihi){ + if(plo > phi){ + return null; + } + + // create and attach data + Node node = new Node(); + this.size++; + + node.data = pre[plo]; + + // search in ino -> to know the number of elements on left side + int srchIdx = -1; + for(int i = ilo; i <= ihi; i++){ + if(in[i] == pre[plo]){ + srchIdx = i; + break; + } + } + + int nelOnls = srchIdx - ilo; + + // set left + node.left = this.construct(pre, plo + 1, plo + nelOnls, in, ilo, ihi); + + // set right + node.right = this.construct(pre, plo + nelOnls + 1, phi, in, ilo, ihi); + + return node; + } + + public BinaryTree() { + this.root = this.takeInput(new Scanner(System.in), null, false); + } + + public Node takeInput(Scanner scn, Node parent, boolean ilc) { + // prompt + if (parent == null) { + System.out.println("Enter the root"); + } else { + if (ilc) { + System.out.println("Enter the left child for " + parent.data); + } else { + System.out.println("Enter the right child for " + parent.data); + } + } + + // collect data and create node + int cdata = scn.nextInt(); + Node child = new Node(); + child.data = cdata; + this.size++; + + // left + System.out.println("Do you have a left child for " + child.data); + boolean hlc = scn.nextBoolean(); + + if (hlc) { + child.left = this.takeInput(scn, child, true); + } + + // right + System.out.println("Do you have a right child for " + child.data); + boolean hrc = scn.nextBoolean(); + + if (hrc) { + child.right = this.takeInput(scn, child, false); + } + + // return + return child; + } + + public void display() { + this.display(this.root); + } + + private void display(Node node) { + if (node == null) { + return; + } + + String str = ""; + + if (node.left != null) { + str += node.left.data; + } else { + str += "."; + } + + str += " => " + node.data + " <= "; + + if (node.right != null) { + str += node.right.data; + } else { + str += "."; + } + + System.out.println(str); + + this.display(node.left); + this.display(node.right); + } + + public int size() { + return this.size; + } + + public boolean isEmpty() { + return this.size() == 0; + } + + public int size2() { + return this.size2(this.root); + } + + private int size2(Node node) { + if (node == null) { + return 0; + } + + int ls = this.size2(node.left); + int rs = this.size2(node.right); + + return ls + rs + 1; + } + + public int max() { + return this.max(this.root); + } + + private int max(Node node) { + if (node == null) { + return Integer.MIN_VALUE; + } + + int lm = this.max(node.left); + int rm = this.max(node.right); + return Math.max(node.data, Math.max(lm, rm)); + } + + public int height() { + return this.height(this.root); + } + + private int height(Node node) { + if (node == null) { + return -1; + } + + int lh = this.height(node.left); + int rh = this.height(node.right); + return Math.max(lh, rh) + 1; + } + + public boolean find(int data) { + return this.find(this.root, data); + } + + private boolean find(Node node, int data) { + if (node == null) { + return false; + } + + if (node.data == data) { + return true; + } + + boolean fil = this.find(node.left, data); + if (fil) { + return true; + } + + boolean fir = this.find(node.right, data); + if (fir) { + return true; + } else { + return false; + } + } + + public int diameter() { + return this.diameter(this.root); + } + + public int diameter(Node node) { + if (node == null) { + return 0; + } + + int ld = this.diameter(node.left); // on the left subtree what is + // maximum edge distance between any + // pair of nodes + int rd = this.diameter(node.right); // on the right subtree what is + // maximum edge distance between any + // pair of nodes + + int lh = this.height(node.left); + int rh = this.height(node.right); + + int rootFactor = lh + rh + 2; + return Math.max(rootFactor, Math.max(ld, rd)); + } + + public int diameter2() { + return this.diameter2(this.root).diameter; + } + + public DiaPair diameter2(Node node) { + if (node == null) { + DiaPair bp = new DiaPair(); + + bp.height = -1; + bp.diameter = 0; + + return bp; + } + + DiaPair lp = this.diameter2(node.left); + DiaPair rp = this.diameter2(node.right); + + DiaPair mp = new DiaPair(); + + mp.height = Math.max(lp.height, rp.height) + 1; + mp.diameter = Math.max(lp.height + rp.height + 2, Math.max(lp.diameter, rp.diameter)); + + return mp; + } + + private class DiaPair { + int height; + int diameter; + } + + public boolean IsBalanced() { + return this.IsBalanced(this.root).isBalanced; + } + + private BalancedPair IsBalanced(Node node) { + if (node == null) { + BalancedPair bp = new BalancedPair(); + + bp.height = -1; + bp.isBalanced = true; + + return bp; + } + + BalancedPair lp = IsBalanced(node.left); + BalancedPair rp = IsBalanced(node.right); + + BalancedPair mp = new BalancedPair(); + + mp.height = Math.max(lp.height, rp.height) + 1; + + if (lp.isBalanced && rp.isBalanced && Math.abs(lp.height - rp.height) <= 1) { + mp.isBalanced = true; + } else { + mp.isBalanced = false; + } + + return mp; + } + + private class BalancedPair { + int height; + boolean isBalanced; + } + + public boolean IsBST() { + BSTPair bstp = IsBST(this.root); + + System.out.println(bstp.largestBSTRoot.data); + System.out.println(bstp.size); + + return bstp.isBST; + } + + private BSTPair IsBST(Node node) { + if (node == null) { + BSTPair bp = new BSTPair(); + + bp.isBST = true; + bp.max = Integer.MIN_VALUE; + bp.min = Integer.MAX_VALUE; + bp.largestBSTRoot = null; + bp.size = 0; + + return bp; + } + + BSTPair lp = this.IsBST(node.left); + BSTPair rp = this.IsBST(node.right); + + BSTPair mp = new BSTPair(); + mp.max = Math.max(node.data, Math.max(lp.max, rp.max)); + mp.min = Math.min(node.data, Math.min(lp.min, rp.min)); + + if (lp.isBST && rp.isBST && node.data > lp.max && node.data < rp.min) { + mp.isBST = true; + mp.largestBSTRoot = node; + mp.size = lp.size + rp.size + 1; + } else { + mp.isBST = false; + + if (lp.size > rp.size) { + mp.largestBSTRoot = lp.largestBSTRoot; + mp.size = lp.size; + } else { + mp.largestBSTRoot = rp.largestBSTRoot; + mp.size = rp.size; + } + } + + return mp; + } + + private class BSTPair { + boolean isBST; + int min; + int max; + int size; + Node largestBSTRoot; + } + + public void preOrder() { + this.preOrder(this.root); + System.out.println("."); + } + + private void preOrder(Node node) { + if (node == null) { + return; + } + + System.out.print(node.data + ", "); + this.preOrder(node.left); + this.preOrder(node.right); + } + + public void postOrder() { + this.postOrder(this.root); + System.out.println("."); + } + + private void postOrder(Node node) { + if (node == null) { + return; + } + + this.postOrder(node.left); + this.postOrder(node.right); + System.out.print(node.data + ", "); + } + + public void inOrder() { + this.inOrder(this.root); + System.out.println("."); + } + + private void inOrder(Node node) { + if (node == null) { + return; + } + + this.inOrder(node.left); + System.out.print(node.data + ", "); + this.inOrder(node.right); + } + + public void levelOrder() { + LinkedList queue = new LinkedList<>(); + queue.addLast(this.root); + + while (queue.size() != 0) { + Node temp = queue.removeFirst(); + + System.out.print(temp.data + ", "); + + if (temp.left != null) { + queue.addLast(temp.left); + } + + if (temp.right != null) { + queue.addLast(temp.right); + } + } + + System.out.println(""); + } + + public void preOrderI() { + LinkedList stack = new LinkedList<>(); + + stack.addFirst(new OrderPair(this.root)); + while (stack.size() != 0) { + OrderPair temp = stack.getFirst(); + + if (temp.selfDone == false) { + System.out.print(temp.node.data + ", "); + temp.selfDone = true; + } else if (temp.leftDone == false) { + if (temp.node.left != null) { + OrderPair leftPair = new OrderPair(temp.node.left); + stack.addFirst(leftPair); + } + temp.leftDone = true; + } else if (temp.rightDone == false) { + if (temp.node.right != null) { + OrderPair rightPair = new OrderPair(temp.node.right); + stack.addFirst(rightPair); + } + temp.rightDone = true; + } else { + stack.removeFirst(); + } + } + System.out.println(); + } + + public void inOrderI() { + LinkedList stack = new LinkedList<>(); + + stack.addFirst(new OrderPair(this.root)); + while (stack.size() != 0) { + OrderPair temp = stack.getFirst(); + + if (temp.leftDone == false) { + if (temp.node.left != null) { + OrderPair leftPair = new OrderPair(temp.node.left); + stack.addFirst(leftPair); + } + temp.leftDone = true; + } else if (temp.selfDone == false) { + System.out.print(temp.node.data + ", "); + temp.selfDone = true; + } else if (temp.rightDone == false) { + if (temp.node.right != null) { + OrderPair rightPair = new OrderPair(temp.node.right); + stack.addFirst(rightPair); + } + temp.rightDone = true; + } else { + stack.removeFirst(); + } + } + System.out.println(); + } + + public void postOrderI() { + LinkedList stack = new LinkedList<>(); + + stack.addFirst(new OrderPair(this.root)); + while (stack.size() != 0) { + OrderPair temp = stack.getFirst(); + + if (temp.leftDone == false) { + if (temp.node.left != null) { + OrderPair leftPair = new OrderPair(temp.node.left); + stack.addFirst(leftPair); + } + temp.leftDone = true; + } else if (temp.rightDone == false) { + if (temp.node.right != null) { + OrderPair rightPair = new OrderPair(temp.node.right); + stack.addFirst(rightPair); + } + temp.rightDone = true; + } else if (temp.selfDone == false) { + System.out.print(temp.node.data + ", "); + temp.selfDone = true; + } else { + stack.removeFirst(); + } + } + System.out.println(); + } + + private class OrderPair { + Node node; + + boolean selfDone; + boolean leftDone; + boolean rightDone; + + OrderPair(Node node) { + this.node = node; + } + } + + public void printSiblingLess() { + this.printSiblingLess(null, this.root, false); + } + + private void printSiblingLess(Node parent, Node child, boolean ilc) { + if (child == null) { + return; + } + + // work + if(ilc == true && parent.right == null){ + System.out.println(child.data); + } + + if(ilc == false && parent.left == null){ + System.out.println(child.data); + } + + this.printSiblingLess(child, child.left, true); + this.printSiblingLess(child, child.right, false); + } + + public void removeLeaves() { + this.removeLeaves(null, this.root, false); + } + + private void removeLeaves(Node parent, Node child, boolean ilc) { + if (child == null) { + return; + } + + // work + + if(child.left == null && child.right == null){ + if(ilc){ + parent.left = null; + } else { + parent.right = null; + } + } + + + this.removeLeaves(child, child.left, true); + this.removeLeaves(child, child.right, false); + } + +} diff --git a/trees/GenericClient.java b/trees/GenericClient.java new file mode 100644 index 0000000..bdd78ed --- /dev/null +++ b/trees/GenericClient.java @@ -0,0 +1,5 @@ +package trees; + +public class GenericClient { + +} diff --git a/trees/GenericTree.java b/trees/GenericTree.java new file mode 100644 index 0000000..bc9c298 --- /dev/null +++ b/trees/GenericTree.java @@ -0,0 +1,369 @@ +package trees; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.Scanner; + +public class GenericTree { + private class Node { + int data; + ArrayList children = new ArrayList<>(); + } + + private Node root; + private int size; + + public GenericTree() { + this.root = this.takeInput(new Scanner(System.in), null, -1); + } + + // create ith child for parent and return that + private Node takeInput(Scanner scn, Node parent, int i) { + if (parent == null) { + System.out.println("Enter the data for root node"); + } else { + System.out.println("Enter the data for " + i + " child of " + parent.data); + } + + int childData = scn.nextInt(); + + System.out.println("Enter the number of children for " + childData); + int numGC = scn.nextInt(); + + Node child = new Node(); + child.data = childData; + this.size++; + + for (int j = 0; j < numGC; j++) { + Node gc = this.takeInput(scn, child, j); + child.children.add(gc); + } + + return child; + } + + public void display() { + System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + this.display(this.root); + System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + } + + private void display(Node node) { + // work + String str = node.data + "=>"; + for (Node child : node.children) { + str += child.data + ", "; + } + System.out.println(str + "."); + + // delegate + for (Node child : node.children) { + this.display(child); + } + } + + public int size() { + return this.size; + } + + public boolean isEmpty() { + return this.size() == 0; + } + + public int size2() { + return this.size2(this.root); + } + + private int size2(Node node) { + int size = 0; + for (Node child : node.children) { + int csize = this.size2(child); + size += csize; + } + + return 1 + size; // for the node itself + } + + public int max() { + return this.max(this.root); + } + + private int max(Node node) { + int max = node.data; + + for (Node child : node.children) { + int cmax = this.max(child); + max = Math.max(max, cmax); + } + + return max; + } + + public int height() { + return this.height(this.root); + } + + private int height(Node node) { + int mh = -1; + + for (Node child : node.children) { + int ch = this.height(child); + mh = Math.max(mh, ch); + } + + return mh + 1; + } + + public boolean find(int data) { + return this.find(this.root, data); + } + + private boolean find(Node node, int data) { + if (node.data == data) { + return true; + } + + for (Node child : node.children) { + boolean fic = this.find(child, data); + if (fic) { + return true; + } + } + + return false; + } + + public void mirror() { + this.mirror(this.root); + } + + private void mirror(Node node) { + for (Node child : node.children) { + this.mirror(child); + } + + int li = 0, ri = node.children.size() - 1; + while (li < ri) { + Node left = node.children.get(li); + Node right = node.children.get(ri); + node.children.set(li, right); + node.children.set(ri, left); + + li++; + ri--; + } + } + + public void preOrder() { + this.preOrder(this.root); + System.out.println("."); + } + + private void preOrder(Node node) { + System.out.print(node.data + "\t"); + + for (Node child : node.children) { + this.preOrder(child); + } + } + + public void postOrder() { + this.postOrder(this.root); + System.out.println("."); + } + + private void postOrder(Node node) { + // System.out.println("Hi" + node.data + "\t"); + for (Node child : node.children) { + // System.out.println("To the next child " + node.data + ":" + + // child.data); + this.postOrder(child); + } + // System.out.println("Bye" + node.data + "\t"); + System.out.print(node.data + "\t"); + } + + public void levelOrder() { + LinkedList queue = new LinkedList<>(); + + queue.addLast(this.root); + while (!queue.isEmpty()) { + // de + Node node = queue.removeFirst(); + + // print + System.out.print(node.data + "\t"); + + // en child + for (Node child : node.children) { + queue.addLast(child); + } + } + System.out.println("."); + } + + public void preOrderI2() { + LinkedList stack = new LinkedList<>(); + + PreOPair pair = new PreOPair(); + pair.node = this.root; + stack.addFirst(pair); + + while (!stack.isEmpty()) { + PreOPair prnt = stack.getFirst(); + + if (prnt.self == false) { + System.out.println(prnt.node.data + " via " + prnt.ptillme); + prnt.self = true; + } else if (prnt.childrenDone < prnt.node.children.size()) { + PreOPair cpair = new PreOPair(); + cpair.node = prnt.node.children.get(prnt.childrenDone); + cpair.ptillme = prnt.ptillme + " => " + prnt.node.data; + stack.addFirst(cpair); + + prnt.childrenDone++; + } else { + stack.removeFirst(); + } + } + } + + private class PreOPair { + Node node; + boolean self = false; + int childrenDone = 0; + String ptillme = ""; + } + + public void multiSolver(int data) { + HeapMover rb = new HeapMover(); + this.multiSolver(this.root, rb, 0, data); + + System.out.println("Size = " + rb.size); + System.out.println("Max = " + rb.max); + System.out.println("Min = " + rb.min); + System.out.println("Height = " + rb.height); + System.out.println("Found = " + rb.found); + System.out.println("Pred = " + (rb.pred == null ? "null" : rb.pred.data)); + System.out.println("Succ = " + (rb.succ == null ? "null" : rb.succ.data)); + System.out.println("JL = " + (rb.justLarger == null ? "null" : rb.justLarger.data)); + } + + private void multiSolver(Node node, HeapMover rb, int depth, int data) { + // work + rb.size++; + if (node.data > rb.max) { + rb.max = node.data; + } + + if (node.data < rb.min) { + rb.min = node.data; + } + + if (depth > rb.height) { + rb.height = depth; + } + + rb.prev = rb.curr; + + if (rb.found == true && rb.succ == null) { + rb.succ = node; + } + + if (node.data == data) { + rb.pred = rb.prev; + rb.found = true; + } + + rb.curr = node; + + if (node.data > data) { + if (rb.justLarger == null) { + rb.justLarger = node; + } else { + if (node.data < rb.justLarger.data) { + rb.justLarger = node; + } + } + } + + // work + + for (Node child : node.children) { + this.multiSolver(child, rb, depth + 1, data); + } + } + + private class HeapMover { + int size = 0; + int max = Integer.MIN_VALUE; + int min = Integer.MAX_VALUE; + int height = 0; + boolean found = false; + + Node curr = null; + Node prev = null; + + Node pred = null; + Node succ = null; + + Node justLarger = null; + } + + public int kthSmallest(int k) { + // int ks = Integer.MIN_VALUE; + // + // for (int i = 0; i < k; i++) { + // HeapMover rb = new HeapMover(); + // this.multiSolver(this.root, rb, 0, ks); + // ks = rb.justLarger.data; + // } + // + // return ks; + ArrayList list = new ArrayList<>(); + this.kthSmallest(this.root, list); + + Integer[] arr = new Integer[list.size()]; + list.toArray(arr); + + Arrays.sort(arr); + return arr[k]; + } + + private void kthSmallest(Node node, ArrayList list) { + list.add(node.data); + for (Node child : node.children) { + this.kthSmallest(child, list); + } + } + + public void printAtLevel(int level) { + + } + + public void removeLeaves() { + this.removeLeaves(this.root); + } + + private void removeLeaves(Node node) { + System.out.print(node.data + "\t"); + + // hi node + + for (int i = node.children.size() - 1; i >= 0; i--) { + // before moving to the child + Node child = node.children.get(i); + if (child.children.size() == 0) { + node.children.remove(i); + } else { + this.removeLeaves(child); + } + // back from the child + } + + // bye node + } + + +}