
| Current Path : /proc/thread-self/root/usr/share/asymptote/ |
Linux ift1.ift-informatik.de 5.4.0-216-generic #236-Ubuntu SMP Fri Apr 11 19:53:21 UTC 2025 x86_64 |
| Current File : //proc/thread-self/root/usr/share/asymptote/binarytree.asy |
/* **********************************************************************
* binarytree: An Asymptote module to draw binary trees *
* *
* Copyright(C) 2006 *
* Tobias Langner tobias[at]langner[dot]nightlabs[dot]de *
* *
* Modified by John Bowman *
* *
* Condensed mode: *
* Copyright(C) 2012 *
* Gerasimos Dimitriadis dimeg [at] intracom [dot] gr *
* *
************************************************************************
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 3 of the License, or(at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, *
* Boston, MA 02110-1301 USA *
* *
* Or get it online: *
* http: //www.gnu.org/copyleft/lesser.html *
* *
***********************************************************************/
// default values
real minDistDefault=0.2cm;
real nodeMarginDefault=0.1cm;
// structure to represent nodes in a binary tree
struct binarytreeNode {
int key;
binarytreeNode left;
binarytreeNode right;
binarytreeNode parent;
bool spans_calculated=false;
int left_span,total_left_span;
int right_span,total_right_span;
void update_spans();
// Get the horizontal span of the tree consisting of the current
// node plus the whole subtree that is rooted at the right child
// (condensed mode)
int getTotalRightSpan() {
if(spans_calculated == false) {
update_spans();
}
return total_right_span;
}
// Get the horizontal span of the tree consisting of the current
// node plus the whole subtree that is rooted at the left child
// (condensed mode)
int getTotalLeftSpan() {
if(spans_calculated == false) {
update_spans();
}
return total_left_span;
}
// Get the horizontal distance between this node and its right child
// (condensed mode)
int getRightSpan() {
if(spans_calculated == false) {
update_spans();
}
return right_span;
}
// Get the horizontal distance between this node and its left child
// (condensed mode)
int getLeftSpan() {
if(spans_calculated == false) {
update_spans();
}
return left_span;
}
// Update all span figures for this node.
// condensed mode)
update_spans=new void() {
if(spans_calculated == true)
return;
left_span=0;
total_left_span=0;
right_span=0;
total_right_span=0;
if(left != null) {
left_span=left.getTotalRightSpan()+1;
total_left_span=left_span+left.getTotalLeftSpan();
}
if(right != null) {
right_span=right.getTotalLeftSpan()+1;
total_right_span=right_span+right.getTotalRightSpan();
}
spans_calculated=true;
};
// set the left child of this node
void setLeft(binarytreeNode left) {
this.left=left;
this.left.parent=this;
}
// set the right child of this node
void setRight(binarytreeNode right) {
this.right=right;
this.right.parent=this;
}
// return a boolean indicating whether this node is the root
bool isRoot() {
return parent == null;
}
// return the level of the subtree rooted at this node.
int getLevel() {
if(isRoot())
return 1;
else
return parent.getLevel()+1;
}
// set the children of this binarytreeNode
void setChildren(binarytreeNode left, binarytreeNode right) {
setLeft(left);
setRight(right);
}
// create a new binarytreeNode with key <key>
static binarytreeNode binarytreeNode(int key) {
binarytreeNode toReturn=new binarytreeNode;
toReturn.key=key;
return toReturn;
}
// returns the height of the subtree rooted at this node.
int getHeight() {
if(left == null && right == null)
return 1;
if(left == null)
return right.getHeight()+1;
if(right == null)
return left.getHeight()+1;
return max(left.getHeight(),right.getHeight())+1;
}
}
binarytreeNode operator init() {return null;}
// "constructor" for binarytreeNode
binarytreeNode binarytreeNode(int key)=binarytreeNode.binarytreeNode;
// draw the tree rooted at the given <node> at the given position <pos>, with
// <height>=the height of the containing tree,
// <minDist>=the minimal horizontal distance of two nodes at the lowest level,
// <levelDist>=the vertical distance between two levels,
// <nodeDiameter>=the diameter of one node.
object draw(picture pic=currentpicture, binarytreeNode node, pair pos,
int height, real minDist, real levelDist, real nodeDiameter,
pen p=currentpen, bool condensed=false) {
Label label=Label(math((string) node.key),pos);
binarytreeNode left=node.left;
binarytreeNode right=node.right;
// return the distance for two nodes at the given <level> when the
// containing tree has height <height>
// and the minimal distance between two nodes is <minDist> .
real getDistance(int level, int height, real minDist) {
return(nodeDiameter+minDist)*2^(height-level);
}
// return the horiontal distance between node <n> and its left child
// (condensed mode)
real getLeftDistance(binarytreeNode n) {
return(nodeDiameter+minDist) *(real)n.getLeftSpan() * 0.5;
}
// return the horiontal distance between node <n> and its right child
// (condensed mode)
real getRightDistance(binarytreeNode n) {
return(nodeDiameter+minDist) *(real)n.getRightSpan() * 0.5;
}
real dist=getDistance(node.getLevel(),height,minDist)/2;
// draw the connection between the two nodes at the given positions
// by calculating the connection points and drawing the corresponding
// arrow.
void deferredDrawNodeConnection(pair parentPos, pair childPos) {
pic.add(new void(frame f, transform t) {
pair start,end;
// calculate connection path
transform T=shift(nodeDiameter/2*unit(t*childPos-t*parentPos));
path arr=(T*t*parentPos)--(inverse(T)*t*childPos);
draw(f,PenMargin(arr,p).g,p,Arrow(5));
});
pic.addPoint(parentPos);
pic.addPoint(childPos);
}
if(left != null) {
pair childPos;
if(condensed == false) {
childPos=pos-(0,levelDist)-(dist/2,0);
}
else {
childPos=pos-(0,levelDist)-((real)getLeftDistance(node),0);
}
draw(pic,left,childPos,height,minDist,levelDist,nodeDiameter,p,condensed);
deferredDrawNodeConnection(pos,childPos);
}
if(right != null) {
pair childPos;
if(condensed == false) {
childPos=pos-(0,levelDist)+(dist/2,0);
}
else {
childPos=pos-(0,levelDist)+((real)getRightDistance(node),0);
}
draw(pic,right,childPos,height,minDist,levelDist,nodeDiameter,p,condensed);
deferredDrawNodeConnection(pos,childPos);
}
picture obj;
draw(obj,circle((0,0),nodeDiameter/2),p);
label(obj,label,(0,0),p);
add(pic,obj,pos);
return label;
}
struct key {
int n;
bool active;
}
key key(int n, bool active=true) {key k; k.n=n; k.active=active; return k;}
key operator cast(int n) {return key(n);}
int operator cast(key k) {return k.n;}
int[] operator cast(key[] k) {
int[] I;
for(int i=0; i < k.length; ++i)
I[i]=k[i].n;
return I;
}
key nil=key(0,false);
// structure to represent a binary tree.
struct binarytree {
binarytreeNode root;
int[] keys;
// add the given <key> to the tree by searching for its place and
// inserting it there.
void addKey(int key) {
binarytreeNode newNode=binarytreeNode(key);
if(root == null) {
root=newNode;
keys.push(key);
return;
}
binarytreeNode n=root;
while(n != null) {
if(key < n.key) {
if(n.left != null)
n=n.left;
else {
n.setLeft(newNode);
keys.push(key);
return;
}
} else if(key > n.key) {
if(n.right != null)
n=n.right;
else {
n.setRight(newNode);
keys.push(key);
return;
}
}
}
}
// return the height of the tree
int getHeight() {
if(root == null)
return 0;
else
return root.getHeight();
}
// add all given keys to the tree sequentially
void addSearchKeys(int[] keys) {
for(int i=0; i < keys.length; ++i) {
int key=keys[i];
// Ignore duplicate keys
if(find(this.keys == key) == -1)
addKey(key);
}
}
binarytreeNode build(key[] keys, int[] ind) {
if(ind[0] >= keys.length) return null;
key k=keys[ind[0]];
++ind[0];
if(!k.active) return null;
binarytreeNode bt=binarytreeNode(k);
binarytreeNode left=build(keys,ind);
binarytreeNode right=build(keys,ind);
bt.left=left; bt.right=right;
if(left != null) left.parent=bt;
if(right != null) right.parent=bt;
return bt;
}
void addKeys(key[] keys) {
int[] ind={0};
root=build(keys,ind);
this.keys=keys;
}
// return all key in the tree
int[] getKeys() {
return keys;
}
}
binarytree searchtree(...int[] keys)
{
binarytree bt;
bt.addSearchKeys(keys);
return bt;
}
binarytree binarytree(...key[] keys)
{
binarytree bt;
bt.addKeys(keys);
return bt;
}
// draw the given binary tree.
void draw(picture pic=currentpicture, binarytree tree,
real minDist=minDistDefault, real nodeMargin=nodeMarginDefault,
pen p=currentpen, bool condensed=false)
{
int[] keys=tree.getKeys();
// calculate the node diameter so that all keys fit into it
frame f;
for(int i=0; i < keys.length; ++i)
label(f,math(string(keys[i])),p);
real nodeDiameter=abs(max(f)-min(f))+2*nodeMargin;
real levelDist=nodeDiameter*1.8;
draw(pic,tree.root,(0,0),tree.getHeight(),minDist,levelDist,nodeDiameter,p,
condensed);
}