import java.io.PrintStream; import java.util.Random; import java.util.concurrent.Callable; /** * Eine Sammlung von Klassenmethoden, um wiederkehrende * Aufgaben mit binären Bäumen zu vereinfachen. * @version 0.1 (2019-09-13) * @author J. Neugebauer */ public class Trees { public static int getMaxDepth( BinaryTree pRoot ) { if( pRoot.isEmpty() ) { return 0; } return 1 + Math.max( getMaxDepth( pRoot.getLeftTree() ), getMaxDepth( pRoot.getRightTree() ) ); } public static int countNodes( BinaryTree pRoot ) { if( pRoot.isEmpty() ) { return 0; } return 1 + countNodes( pRoot.getLeftTree() ) + countNodes( pRoot.getRightTree() ); } public static int countLeaves( BinaryTree pRoot ) { if( pRoot.isEmpty() ) { return 0; } else if( pRoot.getLeftTree().isEmpty() && pRoot.getRightTree().isEmpty() ) { return 1; } return countLeaves( pRoot.getLeftTree() ) + countLeaves( pRoot.getRightTree() ); } public static void printPretty( BinaryTree pRoot ) { printPretty(pRoot, System.out); } public static void printPretty( BinaryTree pRoot, PrintStream pOut ) { pOut.print(printPretty(pRoot, new StringBuilder(), true, new StringBuilder()).toString()); } // Adapted from https://stackoverflow.com/a/27153988/10921408 private static StringBuilder printPretty( BinaryTree pRoot, StringBuilder prefix, boolean isTail, StringBuilder sb) { if( !pRoot.getRightTree().isEmpty() ) { printPretty(pRoot.getRightTree(), new StringBuilder().append(prefix).append(isTail ? "│ " : " "), false, sb); } sb.append(prefix).append(isTail ? "└── " : "┌── ").append(pRoot.getContent().toString()).append("\n"); if( !pRoot.getLeftTree().isEmpty() ) { printPretty(pRoot.getLeftTree(), new StringBuilder().append(prefix).append(isTail ? " " : "│ "), true, sb); } return sb; } public static void printPreorder( BinaryTree pRoot ) { printPreorder(pRoot, System.out); } public static void printPreorder( BinaryTree pRoot, PrintStream pOut ) { if( pRoot.getContent() == null ) { return; } pOut.print(pRoot.getContent().toString() + ","); printPreorder(pRoot.getLeftTree(), pOut); printPreorder(pRoot.getRightTree(), pOut); } public static void printPostorder( BinaryTree pRoot ) { printPostorder(pRoot, System.out); } public static void printPostorder( BinaryTree pRoot, PrintStream pOut ) { if( pRoot.getContent() == null ) { return; } pOut.print(pRoot.getContent().toString() + ","); printPostorder(pRoot.getLeftTree(), pOut); printPostorder(pRoot.getRightTree(), pOut); } public static void printInorder( BinaryTree pRoot ) { printInorder(pRoot, System.out); } public static void printInorder( BinaryTree pRoot, PrintStream pOut ) { if( pRoot.getContent() == null ) { return; } pOut.print(pRoot.getContent().toString() + ","); printInorder(pRoot.getLeftTree(), pOut); printInorder(pRoot.getRightTree(), pOut); } public static BinaryTree generateBalancedIntegerTree( int pNodeCount, int pMinValue, int pMaxValue ) { return generateIntegerTree(pNodeCount, pMinValue, pMaxValue, 0.5, 0.0); } public static BinaryTree generateCompleteIntegerTree( int pDepth, int pMinValue, int pMaxValue ) { return generateBalancedIntegerTree((int)Math.pow(2,pDepth)-1, pMinValue, pMaxValue); } public static BinaryTree generateIntegerTree( int pNodeCount, double pWeight, double pUncertainty ) { return generateIntegerTree(pNodeCount, 0, 100, pWeight, pUncertainty); } public static BinaryTree generateIntegerTree( int pNodeCount, int pMinValue, int pMaxValue, double pWeight, double pUncertainty ) { final Random rand = new Random(); return generateTree(pNodeCount, new Callable() { @Override public Integer call() throws Exception { return new Integer(rand.nextInt(pMaxValue-pMinValue)+pMinValue); } }, pWeight, pUncertainty); } public static BinaryTree generateStringTree( int pNodeCount, double pWeight, double pUncertainty ) { return generateStringTree(pNodeCount, new String[]{"Jonas", "Martin", "Harald", "Sabine", "Feline", "Kathrin"}, pWeight, pUncertainty); } public static BinaryTree generateStringTree( int pNodeCount, final String[] pWords, double pWeight, double pUncertainty ) { final Random rand = new Random(); return generateTree(pNodeCount, new Callable() { @Override public String call() throws Exception { return pWords[rand.nextInt(pWords.length)]; } }, pWeight, pUncertainty); } public static BinaryTree generateTree( int pNodeCount, Callable pGenerator, double pWeight, double pUncertainty ) { return generateTree(new BinaryTree(), pNodeCount, pGenerator, pWeight, pUncertainty); } public static BinaryTree generateTree( BinaryTree pRoot, int pNodeCount, Callable pGenerator, double pWeight, double pUncertainty ) { if( pNodeCount > 0 ) { try { pRoot.setContent(pGenerator.call()); } catch( Exception ex ) { return pRoot; } double weight = pWeight + (pUncertainty - (Math.random() * pUncertainty * 2)); weight = Math.min(1.0, Math.max(0.0, weight)); int leftCount = (int) (pNodeCount * weight); int rightCount = pNodeCount - leftCount - 1; generateTree(pRoot.getLeftTree(), leftCount, pGenerator, pWeight, pUncertainty); generateTree(pRoot.getRightTree(), rightCount, pGenerator, pWeight, pUncertainty); } return pRoot; } }