1. 程式人生 > >(第12講)234樹和2-3樹

(第12講)234樹和2-3樹

2-3-4樹:2-3-4 樹在電腦科學中是階為4 的B樹。它可以

2-3-4樹 在O(log n)時間內查詢、插入和刪除。 2-3-4 樹把資料儲存在叫做元素的單獨單元中。它們組合成節點。每個節點都是下列之一: 2-節點,就是說,它包含 1 個元素和 2 個兒子; 3-節點,就是說,它包含 2 個元素和 3 個兒子; 4-節點,就是說,它包含 3 個元素和 4 個兒子。

package com.ten;

import java.io.*;

public class Tree234App{

        public static void main(String[] args) throws IOException

           {

           Tree234 theTree =newTree234();

           theTree.insert(50);

           theTree.insert(40);

           theTree.insert(60);

           theTree.insert(30);

           theTree.insert(10);

           theTree.insert(90);

           theTree.insert(20);

           theTree.insert(80);

          theTree.insert(70);  theTree.displayTree();

      int value = 11;

           int found=theTree.find(value);

           if(found != -1)

              System.out.println("Found"+value);

           else

              System.out.println("Could not find"+value);

          

}

//2-3樹的節點中的資料

class Data234

{

        public int data;//資料類中只含有一個數據項

        public Data234(int data)

        {

                  this.data = data;

        }

        public void display(){

                  System.out.print("/"+data+"");

        }

}

//2-3樹中的節點類

class Node234//因為建立物件時,引用自動設定為null,數字為0,因此Node23不用設定構造器

{

        private static final int NUM = 4;//定義一個常量為最大的子節點數,則資料項最大為NUM-1

        private Data234 dataArr[] = newData234[NUM-1];//建立每個節點中的資料項,型別為Data23

        private Node234 childArr[] = newNode234[NUM];//建立一個父節點的子節點,最多有4個,或者3,2

        private int dataNum = 0;//當前資料項個數

        private Node234 parent ;//設定父節點,

        public void connectChild(int childIndex,Node234 child)//初始化子節點

        {

                  childArr[childIndex] = child;

                  if(child!=null)

                           child.parent = this;

        }

        public Node234 disconnectChild(int childIndex)//斷開子節點和父節點的連結

        {

                  Node234 child = childArr[childIndex];

                  childArr[childIndex] = null;

                  return child;

        }

        //根據子節點序號,得到子節點

        public Node234 getChild(int childIndex){                returnchildArr[childIndex]; }

        //得到父節點

        public Node234 getParent(){                return parent; }

        //判斷節點是否為葉子節點

        public booleanisLeaf()                     return(childArr[0]==null)?true:false;      }

        //獲得當前資料項個數

        public intgetNumData()                   returndataNum;     }

        //根據下標得到一個結點中的資料項

        public Data234 getData(intdataIndex)                   return dataArr[dataIndex];  }

        //判斷節點是否滿

        public booleanisFull()                     return(dataNum==NUM-1)?true:false;  }

        public int findData(intkey)    

  for(intj=0; j

             if(dataArr[j]==null) 

                break;

             elseif(dataArr[j].data == key)

                return j; 

   }

           return -1;

 

        public int insertData(Data234value)//插入資料之後仍是有序的        {

           //節點未滿

          dataNum++; 

           int newKey=value.data; 

           //若節點是非空,就從後往前找適當的位置

           for(int j=NUM-2;j>=0; j--){ 

             if(dataArr[j] ==null)//如果節點中右邊的資料項為空,則繼續檢視其左邊的資料項 

                continue; 

             else //得到最右邊的非空資料中的關鍵值            

                int itsKey =dataArr[j].data;

                if(newKey< itsKey)//如果新插入的關鍵值比此關鍵值小 

                    dataArr[j+1] = dataArr[j];//將此關鍵值右移

                else

                   {//若新插入的關鍵值比此關鍵值大,則直接插入

                    dataArr[j+1] = value; 

                   returnj+1; //返回插入的下標 

                   

                

             

           dataArr[0] =value;//如果結點是空的 

           return 0;

           }

        public Data234 removeData()//刪除關鍵值最大的資料項            {

           Data234 temp=dataArr[dataNum-1]; 

           dataArr[dataNum-1]=null; 

          dataNum--; 

           returntemp; 

           }

        public void displayNode()  {

                  for(int i=0;i

                           dataArr[i].display();

                  }

                  System.out.println("/");

        }

}

//2-3-4樹類

class Tree234{

        private Node234 root = new Node234();

        //根據給定關鍵字查詢資料項

public int find(int key)  {

   Node234 curNode = root;

   int childNumber;

   while(true)

     {

     if(( childNumber=curNode.findData(key))!= -1)

        returnchildNumber;              // found it

     else if( curNode.isLeaf() )

        return-1;                       // can't find it

     else                                // searchdeeper

        curNode = getNextChild(curNode, key);

     

}

public voidinsert(intdValue)   {

   Node234 curNode = root;

   Data234 tempItem = newData234(dValue);

   while(true)

     {

     if( curNode.isFull())              // if node full,

        {

        split(curNode);                  // split it

        curNode =curNode.getParent(); 

        curNode = getNextChild(curNode,dValue);

        }

     else if( curNode.isLeaf())         // if node is leaf,

        break;                           //go insert

     // node is not full, not a leaf; so go tolower level

     else

        curNode = getNextChild(curNode,dValue);

     

  curNode.insertData(tempItem);      // insert new DataItem

   }

public voidsplit(Node234thisNode)    // split the node

   {

   // assumes node is full

   Data234 itemB, itemC;

   Node234 parent, child2,child3;

   int itemIndex;

   itemC =thisNode.removeData();   // remove items from

   itemB =thisNode.removeData();   // this node

   child2 =thisNode.disconnectChild(2); //remove children

   child3 =thisNode.disconnectChild(3); //from this node

   Node234 newRight = newNode234();      // make new node

  if(thisNode==root)               // if this is theroot,     {

     root = newNode234();               // make new root

     parent =root;                   // root is our parent

     root.connectChild(0, thisNode);  // connect to parent

     }

  else                             // this node notthe root

     parent = thisNode.getParent();

   itemIndex =parent.insertData(itemB); //item B to parent

   int n =parent.getNumData();        // total items?

   for(int j=n-1;j>itemIndex;j--)         // move parent's

                                         // connections

           Node234 temp=parent.disconnectChild(j); // one child

     parent.connectChild(j+1,temp);       // to the right

     }

  parent.connectChild(itemIndex+1, newRight);

  newRight.insertData(itemC);      // item C to newRight

   newRight.connectChild(0,child2); // connectto 0 and 1

   newRight.connectChild(1,child3); // onnewRight

   }

// 以theNode為根的數中的最小點

 public Node234 getNextChild(Node234theNode,long theValue)

   {

   int j=0;

   //如果theNode非空,且不滿,非葉子節點

   int numItems =theNode.getNumData();

   for(;j

                                  // are we less?

     if( theValue < theNode.getData(j).data)

        return theNode.getChild(j);  // return leftchild

                        // we're greater, so

   returntheNode.getChild(j);       // return right child

   }

//封裝recDisplayTree

public void displayTree()

   {

   recDisplayTree(root, 0,0);

   }

//根據結點,所在層,子節點個數來遍歷2-3-4樹(從根開始,從上往下,從左往右開始遍歷)

private voidrecDisplayTree(Node234 thisNode, int level, intchildNumber)

   {

  System.out.print("level="+level+"child="+childNumber+"");

  thisNode.displayNode(); 

  //遍歷每個子節點,numItems為thisNode的資料項個數,numItems+1即為thisNode的子節點個數

   int numItems =thisNode.getNumData();

   for(int j=0; j

     {

     Node234 nextNode = thisNode.getChild(j);

     if(nextNode != null)

        recDisplayTree(nextNode, level+1,j);//遞迴遍歷下一層

     else

        return;

     }

  

結果是:

level=0 child=0 /30 /50 /80 /

level=1 child=0 /10 /20 /

level=1 child=1 /40 /

level=1 child=2 /60 /70 /

level=1 child=3 /90 /

Could not find 11

 2-3樹:是最簡單的B-樹(或-樹)結構,其每個非葉節點都有兩個或三個子女,而且所有葉都在統一層上。2-3樹不是二叉樹,其節點可擁有3個孩子。不過,2-3樹與滿二叉樹相似。高為h的2-3樹包含的節點數大於等於高度為h的滿二叉樹的節點數,即至少有2^h-1個節點。

將資料項放入2-3樹節點中的規則是: (1)2-節點有兩個孩子,必含一個資料項,其查詢關鍵字大於左孩子的查詢關鍵字,而小於右孩子的查詢關鍵字。 (2)3-節點有三個孩子,必含兩個資料項,其查詢關鍵字S和L滿足下列關係:S大於左孩子的查詢關鍵字,而小於中孩子的查詢關鍵字;L大於中孩子的查詢關鍵字,而小於右孩子的查詢關鍵字。 (3)葉子可以包含一個或兩個資料項。 程式如下:

package com.ten;
import java.io.*;
import java.lang.*;

public class TestTree23 {
     public static void main(Stringargs[])throws IOException{
          // FileWriter fw1= newFileWriter("D:\\output.txt");
           FileReader fr=null;
           BufferedReader br=null;
           String s;
           Tree23Node tr= newTree23Node();
           int t=0;
           String str1= newString("insert");
           String str2= newString("search");
           String str3= newString("succ");
           String str4= newString("sort");
           String str5= newString("min");
           String str6= newString("output");
           String str7= newString("delete");
           
           try{
              fr= newFileReader("G:\\IPM_SOURCE\\DataStructLafore\\Tree.txt");
            
              br= newBufferedReader(fr);
           } catch(FileNotFoundExceptionexc){
              System.out.println("Can notopen the file");
              return;
           }