📄 inode.java
字号:
/** By Kristi Thompson and Sean McLaughlin
*
* April 10 & 11, 1997
*
* CISC 235 - Information Structures (Winter 1997) taught by David Alex Lamb
*
* Dept of Computer Science
* Queen's University, Kingston
*
* kristi@merlan.ca , seanster@merlan.ca
*
* http://qlink.queensu.ca/~3sm79/BplusTree
*
* Feel free to copy and modify this applet, but please give credit
* to the original author where appropriate
*
* This applet was inspired by and partly based upon the BST Search Tree Applet
* by James Stewart.
*
* http://www.dgp.toronto.edu/people/JamesStewart/applets/bst/bst-property.html
*
*/
import java.awt.*;
/** A BplusTree Inner Node (INode) */
class INode extends Node
{
final Color INodeColor = Color.cyan;
static int INODE_SPACE = 10; // When a new node is created, move over this much
static int INODE_SPACING = ((Key.KEY_WIDTH + Pointer.POINTER_WIDTH ) * (BplusTree.N + 1)) + (INODE_SPACE * 2); // When the tree redraws to respace eveything
static int INODE_HEIGHT = 30;
// This is not definable! final int INODE_WIDTH = KEY_WIDTH + 2 * POINTER_WIDTH;
static int NEW_INODE_WIDTH = Key.KEY_WIDTH + Pointer.POINTER_WIDTH + Pointer.POINTER_WIDTH;
//((Key.KEY_WIDTH + Pointer.POINTER_WIDTH) * (BplusTree.Ndiv2+1)) + Pointer.POINTER_WIDTH;
boolean movekids = true;
Node[] child = new Node[ BplusTree.N + 2 ]; // N to N/2 children
int[] Keys = new int[BplusTree.N + 1];
int nKeys = 0;
final Font keyFont= new Font( "TimesRoman", Font.BOLD, 18 );
final FontMetrics keyfm = getFontMetrics( keyFont );
/** /////////////////////////////////////
//
// paint
//
*/
public void paint( Graphics g )
{
int i;
// Draw the INode
for(i=0; i < nKeys; i++)
{
g.setColor( Pointer.PointerColor );
g.fillRect( i * ( Pointer.POINTER_WIDTH + Key.KEY_WIDTH) , 0, Pointer.POINTER_WIDTH - 1, INODE_HEIGHT - 1);
g.setColor(LineColor);
g.drawRect( i * ( Pointer.POINTER_WIDTH + Key.KEY_WIDTH) , 0, Pointer.POINTER_WIDTH - 1, INODE_HEIGHT - 1);
g.setColor( INodeColor );
g.fillRect( i * ( Pointer.POINTER_WIDTH + Key.KEY_WIDTH) + Pointer.POINTER_WIDTH, 0, Key.KEY_WIDTH - 1, INODE_HEIGHT - 1);
g.setColor(LineColor);
g.drawRect( i * ( Pointer.POINTER_WIDTH + Key.KEY_WIDTH) + Pointer.POINTER_WIDTH, 0, Key.KEY_WIDTH - 1, INODE_HEIGHT - 1);
g.setColor( Key.KeyColor);
g.setFont( keyFont );
g.drawString( String.valueOf( Keys[i] ),5 + (i * ( Pointer.POINTER_WIDTH + Key.KEY_WIDTH)) + Pointer.POINTER_WIDTH, keyfm.getHeight());
}
g.setColor( Pointer.PointerColor );
g.fillRect( i * ( Pointer.POINTER_WIDTH + Key.KEY_WIDTH) , 0, Pointer.POINTER_WIDTH - 1, INODE_HEIGHT - 1);
g.setColor(LineColor);
g.drawRect( i * ( Pointer.POINTER_WIDTH + Key.KEY_WIDTH) , 0, Pointer.POINTER_WIDTH - 1, INODE_HEIGHT - 1);
}
/////////////////////////////////////
//
// dmove_A
//
public void dmove_A( int dx, int dy )
{
int i;
if ( movekids == true )
{
// Tell Children to Move then call superclass to move us
if ( nKeys > 0 )
{
for(i=0; i <= nKeys; i++)
{
if ( child[i] != null )
{
child[i].dmove_A( dx, dy);
}
else
{
// This is 'likely' a bad situation :)
}
}
}
}
super.dmove_A( dx, dy);
}
/////////////////////////////////////
//
// dmove
//
public void dmove( int dx, int dy )
{
int i;
if ( movekids == true )
{
// Tell Children to Move
for(i=0; i <= nKeys; i++)
{
if ( child[i] != null )
{
child[i].dmove( dx, dy);
}
else
{
// This is 'likely' a bad situation :)
}
}
}
move( bounds().x + dx, bounds().y + dy );
repaint();
}
//////////////////////////////////////////////////////////
//
// resize
//
public void resize()
{
int j = 0;
// Draw any stored edges
reshape( bounds().x, bounds().y, ((Key.KEY_WIDTH + Pointer.POINTER_WIDTH) * nKeys) + Pointer.POINTER_WIDTH, INODE_HEIGHT );
repaint();
}
//////////////////////////////////////////////////////////
//
// preferredSize
//
public Dimension preferredSize()
{
Dimension d = new Dimension();
d.width = ((Key.KEY_WIDTH + Pointer.POINTER_WIDTH) * (nKeys+1)) + Pointer.POINTER_WIDTH;
d.height = INODE_HEIGHT;
return (d);
}
/** //////////////////////////////////////////////////////////
//
// Move our bottom-leftmost child to the left edge, and all bottommost
// children against the right edge returned.
// and then centre ourselves
// between the immediate left child's leftmost edge, and the
// immediate right child's rightmost edge.
//
// If we don't have children, position ourselves at the left edge
//
// This of course constructs a tree shape.
*/
public int Reshape_Tree( int left) // Returns right edge
{
int myleft; // my eventual left edge
int curright;
if ( nKeys < 1 )
{
// We are an INode, and as such, should NEVER, EVER
// be a leaf node. But, in the interest of safety and odd implementation
// vs 'correct' code, I'll let it lie.
// Basic Step
myleft = left;
curright = myleft + bounds().width;
}
else
{
// Recursive Step
curright = left;// curright is technicaly the right edge of
// the last object
int nChild = 1 + nKeys;
for(int j = 0; j < nChild; j++)
{
curright = child[j].Reshape_Tree( curright );
}
// Centre ourself between our left child's left edge and our right child's right edge
int myright = child[nKeys].bounds().x + child[nKeys].bounds().width;
int cleft = child[0].bounds().x;
int centrepos = cleft + ( (myright - cleft) / 2);
myleft = centrepos - ((bounds().width) / 2 );
}
// Just position ourself
// Bottleneck code here in case I want to change to animate this
move( myleft, bounds().y);
return ( curright );
}
/** //////////////////////////////////////////////////////////
//
// Insert
//
// performs a search on the way into the recursion and fixes the tree (if
// necessary) on the way out
//
// if key fits in bucket, then returns NO_PROMOTION
//
// if key does not fit and a new bucket is created, then returns PROMOTION
//
// insert smallest (left) key of new bucket, plus bucket address, into parent (us)
// if we (the parent) are full, split, but middle key goes up (promotes) to parent
// instead of either half. (Repeats until parent need not split)
//
// k - key to search for
// d - data record to insert
// Promo_d contains:
// key - the new key to be inserted (unless NO_PROMOTION)
// rc - pointer to be inserted as the right child of the key
*/
boolean Insert( int k, String d, NodeInfo promo_d )
{
boolean retval; /* Value returned from recursive call to
BTinsert. (PROMOTION or NO_PROMOTION)*/
int i,j; // loop counters, etc
// cycle thru our keys to see if the key is smaller
for(i=0; i < nKeys; i++)
{
if (k < Keys[i])
{
// it's smaller than one of our keys, insert here
break;
// else Key is larger or equal to our largest key
// gets to end of for loop, increments i to nKeys
// i = nKeys happens to be the child we'd want
}
}
// i is the CHILD index
retval = child[i].Insert( k, d, promo_d );
// now the fun part
// if the subnode had to promote a key, we must then deal with it
/*
insert promoted key, plus address
if full
split, but promote middle key to parent instead of either half.
*/
if (retval == PROMOTION)
{
// Okay, we have to add the damn key
// Find out where to insert the key
// i is the CHILD index
// the new key is to be inserted at KEY position i
// the key's child inserts ay CHILD position i+1
// Child i is left alone
// child i+i and key i are shifted up to make space
for(j = nKeys; j > i; j--)
{
// make a space, shift keys up one
Keys[j] = Keys[j - 1];
child[j+1] = child[j];
}
Keys[i] = promo_d.key;
child[i + 1] = promo_d.rc;
nKeys++;
// We are now LONGER
// Ideally we animate ourselves stretching and inserting the
// new key :) :)
resize();
if ( isShowing() )
{
try
{
Thread.sleep( 500 ); // Pause to maintain speed and give time to redraw
}
catch (InterruptedException e)
{}
}
if ( nKeys <= BplusTree.N ) // Are we too big?
{
return(NO_PROMOTION); // Not Overstuffed
}
else
{
// We're Full Up, so Split in two
// middle key Ndiv2 goes up to parent
// The new node goes up as the key's right child
promo_d.key = Keys[BplusTree.Ndiv2];
// Make a new node, and stuff it with Key Ndiv2+1 on
INode newnode = new INode();
promo_d.rc = newnode;
for(j = BplusTree.Ndiv2 + 1, k = 0; j <= BplusTree.N; j++, k++)
{
// stuff the upper half keys into the new node
newnode.Keys[k] = Keys[j];
newnode.child[k] = child[j];
}
newnode.child[k] = child[j];
newnode.nKeys = k;
// We cut off our array BEFORE Key Ndiv2
nKeys = BplusTree.Ndiv2+1; // That 0-1 base thingy goes on here
// Tell our parent to insert the new Inode to it's container
getParent().add ( newnode );
// SET THE Physical LOCATION OF THE NEW Inode!!!
// To exactly where the keys would have been if still in us
// taking into account that the new inode has a pointer on the left
int Keypos = bounds().x + ((BplusTree.Ndiv2 + 1) * ( Pointer.POINTER_WIDTH + Key.KEY_WIDTH ));
newnode.move( Keypos, bounds().y);
newnode.resize(); // Get the node to autosize based on the # of keys it has
// This will cause a repaint, but that's okayt
resize(); // Since we are now shorter
// repaint ourselves, this may leave our new node
// erased briefly because we covered it
// Animate an amoeba split
// The two node's pointers overlap
// and we want a INODE_SPACE inbetween new and old nodes
newnode.speed = SPLIT_SPEED;
newnode.movekids = false;
newnode.dmove_A( Pointer.POINTER_WIDTH + INODE_SPACE, 0);
newnode.movekids = true;
newnode.speed = DEF_SPEED;
// We cut off our array BEFORE Key Ndiv2
if ( isShowing() )
{
try
{
Thread.sleep( 500 ); // Pause to maintain speed and give time to redraw
}
catch (InterruptedException e)
{}
}
nKeys = BplusTree.Ndiv2; // That 0-1 base thingy goes on here
resize();
return(PROMOTION);
} // Too Full?
}
else // Not Promoted
{
// Just Quit
return ( NO_PROMOTION );
} // Promoting?
// Unreachable Code
// ASSERT( FALSE )
} // Insert
} // INode
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -