package deneme01; import lombok.NoArgsConstructor; import java.util.*; class Node { public Node parent; int data, depth, weight; Node left, right; int height; boolean ignore; public Node(int data) { this.data = data; } public boolean isLeaf() { if (left == null && right == null) return true; else return false; } @Override public String toString() { return "" + data; } } @NoArgsConstructor class Tree { Node root; public Tree(Node root) { this.root = root; } public void preOrderRecursive(Node node) { if (node == null) { return; } System.out.print (" " + node.data); preOrderRecursive (node.left); preOrderRecursive (node.right); } public void inOrderRecursive(Node node) { if (node == null) { return; } preOrderRecursive (node.left); System.out.print (" " + node.data); preOrderRecursive (node.right); } public void postOrderRecursive(Node node) { if (node == null) { return; } preOrderRecursive (node.left); preOrderRecursive (node.right); System.out.print (" " + node.data); } public void preOrderIterative() { Stack<Node> stack = new Stack<> (); stack.push (root); while (!stack.isEmpty ()) { Node pop = stack.pop (); System.out.print (" " + pop.data); if (pop.right != null) stack.push (pop.right); if (pop.left != null) stack.push (pop.left); } } public void inOrderIterative() { Stack<Node> stack = new Stack<> (); Node current = root; while (!stack.isEmpty () || null != current) { if (current != null) { stack.push (current); current = current.left; } else { Node pop = stack.pop (); System.out.print (" " + pop.data); current = pop.right; } } } public void postOrderIterative() { Stack<Node> stack = new Stack<> (); stack.push (root); while (!stack.isEmpty ()) { Node peek = stack.peek (); if (peek.isLeaf ()) { Node pop = stack.pop (); System.out.print (" " + pop.data); } else { if (peek.right != null) { stack.push (peek.right); peek.right = null; } if (peek.left != null) { stack.push (peek.left); peek.left = null; } } } } public void bfsRecursive() { int height = Math.max (height (root.left), height (root.right)) + 1; for (int i = 1; i <= height; i++) { bfs (root, i); System.out.println (""); } } private void bfs(Node node, int height) { if (node == null) { return; } if (height == 1) { System.out.print (" " + node.data); } else if (height > 1) { bfs (node.left, height - 1); bfs (node.right, height - 1); } } public void bfsIterative() { Queue<Node> queue = new LinkedList<> (); root.depth = 0; queue.add (root); int currentDepth = root.depth; while (!queue.isEmpty ()) { Node poll = queue.poll (); if (currentDepth != poll.depth) { System.out.println (""); currentDepth = poll.depth; } System.out.print (" " + poll.data); if (poll.left != null) { poll.left.depth = poll.depth + 1; queue.add (poll.left); } if (poll.right != null) { poll.right.depth = poll.depth + 1; queue.add (poll.right); } } } public void bfsIterativeBottom2Top() { Queue<Node> queue = new LinkedList<> (); Stack<Node> stack = new Stack<> (); queue.add (root); while (!queue.isEmpty ()) { Node poll = queue.poll (); //System.out.print(" " + poll.data); stack.push (poll); if (poll.right != null) { queue.add (poll.right); } if (poll.left != null) { queue.add (poll.left); } } while (!stack.isEmpty ()) { Node pop = stack.pop (); System.out.print (" " + pop.data); } } public int size() { Stack<Node> stack = new Stack<> (); stack.push (root); int size = 0; while (!stack.isEmpty ()) { Node pop = stack.pop (); size++; if (pop.right != null) { stack.push (pop.right); } if (pop.left != null) { stack.push (pop.left); } } return size; } public int height() { return height (root); } private int height(Node node) { if (node == null) { return 0; } return Math.max (height (node.left), height (node.right)) + 1; } public Node insert(int x) { return insert (x, root); } public Node insert(int x, Node node) { if (node == null) { node = new Node (x); } if (x < node.data) { node = insert (x, node); if (x < node.left.data) { node = rightRotate (node); } else { node = doubleRightRotate (node); } } else if (x > node.data) { node = insert (x, node); if (x > node.right.data) { node = leftRotate (node); } else { node = doubleLeftRotate (node); } } else { //duplicate , ignore } return node; } private Node doubleRightRotate(Node node) { node.left = leftRotate (node.left); return rightRotate (node); } private Node rightRotate(Node k1) { Node k2 = k1.left; k1.left = k2.right; k2.right = k1; k1.height = Math.max (height (k1.left), height (k1.left)) + 1; k2.height = Math.max (height (k2.left), height (k2.left)) + 1; return k2; } private Node doubleLeftRotate(Node node) { node.right = rightRotate (node.right); return leftRotate (node); } private Node leftRotate(Node k1) { Node k2 = k1.right; k1.right = k2.left; k2.left = k1; k1.height = Math.max (height (k1.left), height (k1.left)) + 1; k2.height = Math.max (height (k2.left), height (k2.left)) + 1; return k2; } public void findMaxDepth() { Stack<Node> nodes = new Stack<> (); root.depth = 0; nodes.push (root); int maxDepth = 0; while (!nodes.isEmpty ()) { Node current = nodes.pop (); System.out.printf ("%s ", current.data); if (maxDepth < current.depth) { maxDepth = current.depth; } if (current.right != null) { current.right.depth = current.depth + 1; nodes.push (current.right); } if (current.left != null) { current.left.depth = current.depth + 1; nodes.push (current.left); } } System.out.println ("maxDepth = " + maxDepth); } //shortest path = breadth first search public void findMinDepth() { Queue<Node> queue = new LinkedList<> (); root.depth = 0; queue.add (root); int minDepth = Integer.MAX_VALUE; while (!queue.isEmpty ()) { Node poll = queue.poll (); if (poll.isLeaf () && minDepth > poll.depth) { minDepth = poll.depth; } System.out.print (" " + poll.data); if (poll.left != null) { poll.left.depth = poll.depth + 1; queue.add (poll.left); } if (poll.right != null) { poll.right.depth = poll.depth + 1; queue.add (poll.right); } } System.out.println ("minDepth = " + minDepth); } //fix this!!! public void traverseAndCalculateNodeTotalWeightTop2Bottom() { Stack<Node> stack = new Stack<> (); root.weight = root.data; stack.push (root); while (!stack.isEmpty ()) { Node peek = stack.peek (); if (peek.isLeaf ()) { Node pop = stack.pop (); System.out.print ("[ " + pop.data + " nw:" + pop.weight + "] "); } else { if (peek.right != null) { peek.right.weight = peek.weight + peek.right.data; stack.push (peek.right); peek.right = null; } if (peek.left != null) { peek.left.weight = peek.weight + peek.left.data; stack.push (peek.left); peek.left = null; } } } } public int[] averageInEachLevel() { int[] averages = new int[height (root)]; Queue<Node> queue = new LinkedList<> (); queue.add (root); int currentDepth = 0; root.depth = 0; int levelSum = 0, levelMember = 0; while (!queue.isEmpty ()) { Node poll = queue.poll (); if (currentDepth != poll.depth) { System.out.print (" => sum: " + levelSum + " member: " + levelMember); averages[poll.depth - 1] = levelSum / levelMember; levelMember = 0; levelSum = 0; System.out.println (" "); currentDepth = poll.depth; } levelSum += poll.data; levelMember++; System.out.print (" " + poll.data); if (poll.left != null) { poll.left.depth = poll.depth + 1; queue.add (poll.left); } if (poll.right != null) { poll.right.depth = poll.depth + 1; queue.add (poll.right); } } averages[averages.length - 1] = levelSum / levelMember; return averages; } public Double[] averageInEachLevel2() { ArrayList<Double> averages = new ArrayList<> (); Queue<Node> queue = new LinkedList<> (); queue.add (root); List<List<Node>> levelMembers = new ArrayList<> (); ArrayList<Node> rootLevel = new ArrayList<> (); rootLevel.add (root); levelMembers.add (rootLevel); while (!queue.isEmpty ()) { double count = queue.size (); double sum = 0; ArrayList currentLevel = new ArrayList<> (); for (int i = 0; i < count; i++) { Node poll = queue.poll (); sum += poll.data; if (poll.right != null) { queue.add (poll.right); currentLevel.add (poll.right); } if (poll.left != null) { queue.add (poll.left); currentLevel.add (poll.left); } } averages.add (sum / count); levelMembers.add (currentLevel); } return averages.toArray (new Double[averages.size ()]); } //---- public boolean find(int id) { Node current = root; while (current != null) { if (current.data == id) { return true; } else if (current.data > id) { current = current.left; } else { current = current.right; } } return false; } //while deleting you need two things ! parent and isLeftChild ! //for the rest of the scenarios you need to go through to following considerations //is it root ? is it leftChild ? is it right child ? //Scenarios are is leaf node ? has only one right child ? has only one left child ? has two child ? public boolean deleteUnbalanced(int id) { Node parent = root; Node current = root; boolean isLeftChild = false; while (current.data != id) { parent = current; if (current.data > id) { isLeftChild = true; current = current.left; } else { isLeftChild = false; current = current.right; } if (current == null) { return false; } } //if i am here that means we have found the node //Case 1: if node to be deleted has no children if (current.left == null && current.right == null) { if (current == root) { root = null; } if (isLeftChild == true) { parent.left = null; } else { parent.right = null; } } //Case 2 : if node to be deleted has only one child else if (current.right == null) { if (current == root) { root = current.left; } else if (isLeftChild) { parent.left = current.left; } else { parent.right = current.left; } } else if (current.left == null) { if (current == root) { root = current.right; } else if (isLeftChild) { parent.left = current.right; } else { parent.right = current.right; } } else if (current.left != null && current.right != null) { //now we have found the minimum element in the right sub tree Node successor = getSuccessor (current); if (current == root) { root = successor; } else if (isLeftChild) { parent.left = successor; } else { parent.right = successor; } successor.left = current.left; } return true; } //from right to leftmost... public Node getSuccessor(Node deleleNode) { Node successsor = null; Node successsorParent = null; Node current = deleleNode.right; while (current != null) { successsorParent = successsor; successsor = current; current = current.left; } //check if successor has the right child, it cannot have left child for sure //if it does have the right child, add it to the left of successorParent. //successsorParent if (successsor != deleleNode.right) { successsorParent.left = successsor.right; successsor.right = deleleNode.right; } return successsor; } public boolean delete(int x) { Node parent = root; Node current = root; boolean isLeftChild = false; while (current.data != x) { parent = current; if (current.data < x) { isLeftChild = false; current = current.right; } else { isLeftChild = true; current = current.left; } if (current == null) { return false;// not found the X in the tree } } if (current.left == null && current.right == null) { if (current == root) { root = null; } if (isLeftChild) { parent.left = null; } else { parent.right = null; } } else if (current.right != null) { if (current == root) { root = current.right; } if (isLeftChild) { parent.left = current.right; } else { parent.right = current.right; } } else if (current.left != null) { if (current == root) { root = current.left; } if (isLeftChild) { parent.left = current.left; } else { parent.right = current.left; } } else if (current.left != null && current.right != null) { Node successor = getSuccessor (current); if (current == root) { root = successor; } else if (isLeftChild) { current.left = successor; } else { current.right = successor; } successor.left = current.left; } return isLeftChild; } public void insertUnBalanced(int id) { Node newNode = new Node (id); if (root == null) { root = newNode; return; } Node current = root; Node parent = null; while (true) { parent = current; if (id < current.data) { current = current.left; if (current == null) { parent.left = newNode; return; } } else { current = current.right; if (current == null) { parent.right = newNode; return; } } } } //--------- public void allPathsToLeafNodesWithPreOrderDFS() { Stack<Node> stack = new Stack<> (); stack.push (root); List<Deque<Integer>> paths = new ArrayList<> (); while (!stack.isEmpty ()) { Node pop = stack.pop (); System.out.print (" " + pop.data); if (pop.isLeaf ()) { Deque<Integer> path = new ArrayDeque<> (); Node current = pop; while (current != null) { path.add (current.data); current = current.parent; } paths.add (path); } if (pop.right != null) { pop.right.parent = pop; stack.push (pop.right); } if (pop.left != null) { pop.left.parent = pop; stack.push (pop.left); } } System.out.println ("paths = " + paths); } public void allPathsToLeafNodesWithInOrderDFS() { Stack<Node> stack = new Stack<> (); List<Deque<Integer>> paths = new ArrayList<> (); Node current = root; while (!stack.isEmpty () || current != null) { if (current != null) { stack.push (current); if (current.left != null) current.left.parent = current; current = current.left; } else { Node pop = stack.pop (); System.out.println (" " + pop.data); if (pop.isLeaf ()) { Deque<Integer> path = new ArrayDeque<> (); Node now = pop; while (now != null) { path.add (now.data); now = now.parent; } paths.add (path); } current = pop.right; if (pop.right != null) pop.right.parent = pop; } } System.out.println ("paths = " + paths); } public void allPathsToLeafNodesWithBFS() { List<Deque<Integer>> paths = new ArrayList<> (); Queue<Node> queue = new LinkedList<> (); queue.add (root); while (!queue.isEmpty ()) { Node poll = queue.poll (); System.out.println ("poll = " + poll); if (poll.isLeaf ()) { Deque<Integer> path = new ArrayDeque<> (); Node current = poll; while (current != null) { path.add (current.data); current = current.parent; } paths.add (path); } if (poll.left != null) { poll.left.parent = poll; queue.add (poll.left); } if (poll.right != null) { poll.right.parent = poll; queue.add (poll.right); } } System.out.println ("paths = " + paths); } } public class Main { // 40 // 20 50 // 10 30 45 60 // 5 15 25 35 44 46 55 61 //4 6 14 16 24 26 34 36 43 47 54 56 62 // 63 // 64 // 40 20 10 5 15 30 25 35 50 45 44 46 60 55 61 // 5 10 15 20 25 30 35 40 44 45 46 50 55 60 61 // 5 15 10 25 35 30 20 44 46 45 55 61 60 50 40 public static String traversePreOrder(Node root) { if (root == null) { return ""; } StringBuilder sb = new StringBuilder (); sb.append (root.data); String pointerRight = "└──"; String pointerLeft = (root.right != null) ? "├──" : "└──"; traverseNodes (sb, "", pointerLeft, root.left, root.right != null); traverseNodes (sb, "", pointerRight, root.right, false); return sb.toString (); } public static void traverseNodes(StringBuilder sb, String padding, String pointer, Node node, boolean hasRightSibling) { if (node != null) { sb.append ("\n"); sb.append (padding); sb.append (pointer); sb.append (node.data); StringBuilder paddingBuilder = new StringBuilder (padding); if (hasRightSibling) { paddingBuilder.append ("│ "); } else { paddingBuilder.append (" "); } String paddingForBoth = paddingBuilder.toString (); String pointerRight = "└──"; String pointerLeft = (node.right != null) ? "├──" : "└──"; traverseNodes (sb, paddingForBoth, pointerLeft, node.left, node.right != null); traverseNodes (sb, paddingForBoth, pointerRight, node.right, false); } } public static void main(String[] args) { Tree tree = buildTree (); System.out.println ("Before deletion --"); String s = traversePreOrder (tree.root); System.out.println (s); tree.deleteUnbalanced (40); System.out.println ("After insertion --"); s = traversePreOrder (tree.root); System.out.println (s); System.out.println (""); tree = buildTree (); System.out.println ("Before insertion --"); s = traversePreOrder (tree.root); System.out.println (s); tree.insertUnBalanced (12); System.out.println ("After insertion --"); s = traversePreOrder (tree.root); System.out.println (s); System.out.println (""); tree = buildTree (); System.out.println ("PreOrder --"); tree.preOrderIterative (); System.out.println (""); tree = buildTree (); System.out.println ("InOrder --"); tree.inOrderIterative (); System.out.println (""); tree = buildTree (); System.out.println ("PostOrder --"); tree.postOrderIterative (); System.out.println (""); System.out.println (""); tree = buildTree (); System.out.println (" Size : " + tree.size ()); System.out.println (""); System.out.println ("-- tree height--"); tree = buildTree (); System.out.println (" Height : " + tree.height ()); System.out.println (""); System.out.println ("-- bfs recursive--"); tree = buildTree (); tree.bfsRecursive (); System.out.println (""); System.out.println ("-- bfs iterative --"); tree = buildTree (); tree.bfsIterative (); System.out.println (""); System.out.println ("-- each level average iterative --"); tree = buildTree (); tree.averageInEachLevel (); System.out.println (""); System.out.println ("-- each level average iterative 2 --"); tree = buildTree (); tree.averageInEachLevel2 (); System.out.println (""); System.out.println ("-- maxDepth --"); tree = buildTree (); System.out.println (""); tree.findMaxDepth (); System.out.println (""); System.out.println ("-- totalNodeWeights --"); tree = buildTree (); System.out.println (""); tree.traverseAndCalculateNodeTotalWeightTop2Bottom (); System.out.println (""); System.out.println ("-- findMinDepthToLeafNode --"); tree = buildTree (); System.out.println (""); tree.findMinDepth (); System.out.println (""); System.out.println ("-- findMinDepthToLeafNode --"); tree = buildTree (); System.out.println (""); tree.bfsIterativeBottom2Top (); System.out.println (""); System.out.println ("-- allPaths2LeafNodesWithPreOrderDFS --"); tree = buildTree (); System.out.println (""); tree.allPathsToLeafNodesWithPreOrderDFS (); System.out.println (""); System.out.println ("-- allPaths2LeafNodesWithInOrderDFS --"); tree = buildTree (); System.out.println (""); tree.allPathsToLeafNodesWithInOrderDFS (); System.out.println (""); } // 40 // 20 50 // 10 30 45 60 // 15 25 35 55 61 // 14 16 24 26 34 36 54 56 62 // 63 // 64 private static Tree buildTree() { Tree tree = new Tree (); Node root = new Node (400); tree.root = root; tree.root.left = new Node (200); tree.root.right = new Node (500); tree.root.left.left = new Node (100); tree.root.left.right = new Node (300); tree.root.right.left = new Node (450); tree.root.right.right = new Node (600); tree.root.left.left.left = new Node (50); tree.root.left.left.right = new Node (150); tree.root.left.right.left = new Node (250); tree.root.left.right.right = new Node (350); tree.root.right.left.left = new Node (440); tree.root.right.left.right = new Node (460); tree.root.right.right.left = new Node (550); tree.root.right.right.right = new Node (610); tree.root.right.right.left.left = new Node (540); tree.root.right.right.left.right = new Node (560); tree.root.left.left.left.left = new Node (40); tree.root.left.left.left.right = new Node (60); tree.root.left.left.left.left.left = new Node (35); tree.root.left.left.left.left.right = new Node (45); tree.root.left.left.left.left.right.left = new Node (44); tree.root.left.left.left.left.right.right = new Node (48); tree.root.left.left.left.left.right.right.left = new Node (47); tree.root.left.left.left.left.right.right.right = new Node (49); tree.root.left.left.left.left.right.left.left = new Node (43); tree.root.left.left.right.left = new Node (140); tree.root.left.left.right.right = new Node (160); tree.root.left.right.left.left = new Node (240); tree.root.left.right.left.right = new Node (260); tree.root.left.right.right.left = new Node (340); tree.root.left.right.right.right = new Node (360); tree.root.right.left.left.left = new Node (430); tree.root.right.left.right.right = new Node (470); tree.root.right.right.right.right = new Node (620); tree.root.right.right.right.right.right = new Node (630); tree.root.right.right.right.right.right.right = new Node (640); return tree; } }