📄 bucket.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's Leaf node */
class Bucket extends Node
{
final Color BucketColor = Color.gray;
static int BUCKET_HEIGHT = 45;
static final int BUCKET_WIDTH = 40; // Size of an individual bucket element ie. new bucket
static final int BUCKET_SPACE = 5; // Not much since we are overextended and will shrink in a sec
static int NEW_BUCKET_WIDTH = BUCKET_WIDTH * (BplusTree.Ndiv2+1); // Size of an individual bucket element ie. new bucket
static final int PREFERRED_BUCKET_SPACING = BUCKET_WIDTH + BUCKET_SPACE + BUCKET_SPACE;
static final int MIN_BUCKET_SPACING = 5;
static int BUCKET_SPACING = PREFERRED_BUCKET_SPACING;
// = (BUCKET_WIDTH * (N + 1)) + (BUCKET_SPACE * 2);// This is the preferred amt of space, regardless of existing widths
Bucket next_Bucket = null; // For sequential Access (Fully Implemented)
int[] Keys = new int[BplusTree.N + 1];
String[] myData = new String[BplusTree.N + 1];
int nKeys = 0;
final Font keyFont = new Font( "TimesRoman", Font.BOLD, 18 );
final FontMetrics keyfm = getFontMetrics( keyFont );
final Font dataFont = new Font( "TimesRoman", Font.PLAIN, 14 );
final FontMetrics datafm = getFontMetrics( dataFont );
//setBackground(BackgroundColor);
public Bucket()
{
setBackground(BucketColor);
}
//////////////////////////////////////////////////////////
//
// paint
//
public void paint( Graphics g )
{
int j = 0;
int i;
// Draw the Bucket Keys
//g.drawRect( i * BUCKET_WIDTH, 0, BUCKET_WIDTH , BUCKET_HEIGHT );
for(i=0; i < nKeys; i++)
{
g.setColor(LineColor);
g.drawRect( i * BUCKET_WIDTH, 0, BUCKET_WIDTH - 1, BUCKET_HEIGHT - 1);
g.setColor( Key.KeyColor );
g.setFont( keyFont );
g.drawString( String.valueOf( Keys[i] ), i * BUCKET_WIDTH +5, keyfm.getHeight());
g.setColor( Data.DataColor );
g.setFont( dataFont );
g.drawString( myData[i], i * BUCKET_WIDTH +5, keyfm.getHeight() + datafm.getHeight() );
}
}
/** /////////////////////////////////////
//
// dmove_A - move a certain distance - in an animated manner though
//
*/
/////////////////////////////////////
//
// move
//
public void dmove( int dx, int dy )
{
Rectangle bounds = bounds();
reshape( bounds.x + dx, bounds.y + dy, bounds.width , bounds.height );
repaint();
}
//////////////////////////////////////////////////////////
//
// resize
//
public void resize()
{
int j = 0;
// Draw any stored edges
reshape( bounds().x, bounds().y, BUCKET_WIDTH * nKeys, BUCKET_HEIGHT );
repaint();
}
//////////////////////////////////////////////////////////
//
// preferredSize
//
public Dimension preferredSize()
{
Dimension d = new Dimension();
d.width = ( BUCKET_WIDTH * nKeys ) + BUCKET_SPACE;
d.height = BUCKET_HEIGHT;
return (d);
}
/** //////////////////////////////////////////////////////////
//
// We are always a leaf, so just move to the left edge given
// and return our right edge
//
// This of course constructs a tree shape.
*/
public int Reshape_Tree( int left) // Returns right edge
{
// Basic Step
// Just position ourself
move( left, bounds().y);
return ( left + bounds().width + BUCKET_SPACING);
}
/////////////////////////////////////////////////////////
//
// insert
//
/* performs a search, if key found, just pretend we did insert and result NO_PROMOTION
fits key into bucket where appropriate
if not overstuffed, return NO_PROMOTION
if overstuffed, a new bucket is created and we put the right half into it,
and return PROMOTION with the Key of the far left of the new bucket, and the new bucket
*/
// k - key to search for
// d - data record to insert
// promo_key - the new key to be inserted (unless NO_PROMOTION)
// promo_rc - pointer to be inserted as the right child of the key
boolean Insert( int k, String d, NodeInfo promo_d )
{
int i,j; // loop counters, etc
if ( nKeys > 0 )
{
// 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
}
else if ( k == Keys[i] ) // Check for Dupe Key
{
//It's a Dupe, We don't want dupe keys
//But we will happily update it's data value
myData[i] = d;
repaint();
return(NO_PROMOTION);
}
}
}
else // We have NO keys
{
i = 0; // Insert Key at position Zero
}
// Key is not in the list, insert it at position i
// Shove over keys from pos i on
for (j = nKeys; j > i; j--)
{
// make a space, shift keys up one
Keys[j] = Keys[j - 1];
myData[j] = myData[j - 1];
}
Keys[i] = k;
myData[i] = d;
nKeys++;
// We are now LONGER
// Ideally we animate ourselves stretching and inserting the
// new record :) :)
resize();
if ( isShowing() )
{
try
{
Thread.sleep( 500 ); // Pause to maintain speed and give time to redraw
}
catch (InterruptedException e)
{}
}
// now the fun part
// Did we overstuff ourselves by Adding that Key?
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 bucket goes up as the key's right child
// Ideally we move the key object up, out of us, sitting slightly above the top
// and then shrink
promo_d.key = Keys[BplusTree.Ndiv2];
// Make a new bucket, and stuff it with Keys & Data Ndiv2 on
Bucket newnode = new Bucket();
// We keep track of the next bucket, so it is possible
// To rapidly cruise on directly across the Buckets
newnode.next_Bucket = next_Bucket;
next_Bucket = newnode;
promo_d.rc = newnode;
for(j = BplusTree.Ndiv2, k = 0; j <= BplusTree.N; j++, k++)
{
// stuff the upper half keys into the new node
newnode.Keys[k] = Keys[j];
newnode.myData[k] = myData[j];
}
newnode.nKeys = k;
// We cut off our array BEFORE Key Ndiv2
nKeys = BplusTree.Ndiv2; // That 0-1 base thingy goes on here
// Tell our parent to insert the new node in it's container
getParent().add ( newnode );
// SET THE Physical LOCATION OF THE NEW BUCKET!!!
// To exactly where the records would have been if still in us
int Recordpos = bounds().x + (nKeys * BUCKET_WIDTH);
newnode.move( Recordpos, 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 a separation
// and we want a BUCKET_SPACE inbetween new and old nodes
newnode.speed = SPLIT_SPEED;
newnode.dmove_A( BUCKET_SPACE, 0);
newnode.speed = DEF_SPEED;
if ( isShowing() )
{
try
{
Thread.sleep( 500 ); // Pause to maintain speed and give time to redraw
}
catch (InterruptedException e)
{}
}
// Tell our parent to insert the new Key & Bucket
return(PROMOTION);
} // Too Full?
// Unreachable Code
// ASSERT( FALSE )
} /* insert. **********************/
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -