/*----------------------------------------------------------------------+ | Title: Phyltree.java | | Java Class | | (used in Phylap.java applet) | | | | Author: David E. Joyce | | Department of Mathematics and Computer Science | | Clark University | | Worcester, MA 01610-1477 | | U.S.A. | | | | http://aleph0.clarku.edu/~djoyce/ | | | | Date: January, 1996, updated November, 2002. | +----------------------------------------------------------------------*/ import java.awt.*; import java.lang.*; /* * Description of the data structure. A tree has a number of leaves, n, * and a number of other nodes, at most 2n nodes in all. Each node has a * height. The leaves have height 0.0. The variable treeHeight indicates * the maximum height of the nodes in the tree, which will be the height * of a root for a completed tree. Each node in the tree has a parent node, * except the root, of course. Nodes that are parents of other nodes * point to one of those nodes, called the eldest node. The eldest node * points to the next sibling of the node; thus, the children of the parent * are kept in a linked list. * * As a tree is constructed, many of the nodes will not have parents. But * as new nodes are added to the tree, they will receive parents. Eventually * when the number of parentless nodes gets down to 1, the construction is * finished. */ public class Phyltree { private int n; // the number of leaves on the tree private int assigned; // the number of assigned nodes private int parentless; // the number of parentless nodes private double treeHeight; // the greatest height of any node private double height[]; // the heights of the nodes private int parent[]; // the parents of the nodes private int eldest[]; // the eldest children of the nodes private int sib[]; // the next siblings of the nodes public Phyltree (int nval) { setSize(nval); } /* setSize sets up an incomplete tree with n leaves, all parentless. * Later, the rest of the nodes of the tree will be created. */ public void setSize(int nval) { n = nval; int two_n = 2*n; assigned = n; parentless = n; treeHeight = 0; height = new double[two_n]; parent = new int[two_n]; eldest = new int[two_n]; sib = new int[two_n]; for (int i=0; i= assigned) return -1; return parent[i]; } public int getEldest(int i) { if (i < 0 || i >= assigned) return -1; return eldest[i]; } public int getSib(int i) { if (i < 0 || i >= assigned) return -1; return sib[i]; } public double getHeight(int i) { if (i < 0 || i >= assigned) return 0.0; return height[i]; } /* newNode creates a new node of a specified height. It is unconnected * to the tree as yet. */ private int newNode(double h) { // return the next available node after setting its height height[assigned] = h; if (h > treeHeight) treeHeight = h; ++parentless; return assigned++; } // newNode /* a child node is connected to a parent node. The parent pointer of * the child is set, and the list of children of the parent is updated. */ private void assertParentage (int child, int paren) { if (parent[child] == -1) { parent[child] = paren; --parentless; sib[child] = eldest[paren]; eldest[paren] = child; } } // assertParentage /* find the most remote ancestor of a given node. Run up the parent * pointers until one without a parent is found. */ private int remoteAncestor (int i) { int j; while ((j=parent[i]) != -1) i = j; return i; } /* given two nodes i and j, find the most recent common ancestor if there * is one, otherwise indicate they have no common ancestor. */ private int commonAncestor (int i, int j) { int p,q; while (i!=-1 && j!=-1 && i!=j) { if (height[i] < height[j]) i = parent[i]; else if (height[i] > height[j]) j = parent[j]; else if (i 1) { // select some number of nodes to merge int numberToMerge = 2; while (Math.random() < extra) ++numberToMerge; if (numberToMerge > parentless) numberToMerge = parentless; // Next merge that many parentless nodes. Before that's done // the height of the new node has to be determined. It will // be at least 0.2 plus the maximum height of the children, but // no more than 1.0 more than that. double maxHeight = 0.0; for (j=0; j maxHeight) maxHeight = height[i]; } // Now create the node and link it up int k = newNode(0.2+Math.random()+maxHeight); for (j=0; j 1) { // first find the closest pair double close_d = Double.POSITIVE_INFINITY; int close_i=-2, close_j=-2; for (i=1; i=n && height[owner[i]]>=height_k) { k = owner[i]; assertParentage(owner[j],k); } else if (owner[j]>=n && height[owner[j]]>=height_k) { k = owner[j]; assertParentage(owner[i],k); } else { k = newNode(height_k); assertParentage(owner[i],k); assertParentage(owner[j],k); } // if/else owner[i] = k; owner[j] = -1; for (p=0; p