B树索引

package cn.hit.sqlLab2;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;


/**
 * B树索引
 *
 */
public class BtreeIndex {
  private static int cnt = 7; //每个B树节点的键值个数
  private static int t = (cnt + 1) / 2; 
  private static BtreeNode root = null; //根节点
  private static BufferedReader in = null;
  private static BufferedWriter out = null;
  private static int outnumber = 0; 

  public static void run() {
    // 随机生成1000000条记录并存入文本文件
    // Generator.generator();
    // System.out.println(Generator.messages.size());

    long startTime = System.nanoTime();
    FileWriter write = null;
    try {
      write = new FileWriter(new File("res/output-" + cnt + ".txt"));
      out = new BufferedWriter(write);
    } catch (FileNotFoundException e1) {
      e1.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }

    List messages = new ArrayList();

    FileReader reader;
    try {
      reader = new FileReader(new File("res/input.txt"));
      in = new BufferedReader(reader);
      String inLine = null;
      while ((inLine = in.readLine()) != null) {
        Message message = new Message(Integer.parseInt(inLine.split(" ")[0]), inLine.split(" ")[1]);
        messages.add(message);
      }
      System.out.println("messages number:"+messages.size());
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    } catch (NumberFormatException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
    BtreeIndex.buildBtree(messages);
    System.out.println("build success!");
    printNode(root);
    System.out.println("outnumber:" + outnumber);
    long endTime = System.nanoTime();
    long duration = (endTime - startTime) / 1000000;
    try {
      out.write("<<<<<>>>>>");
      System.out.println("<<<<<>>>>>");
    } catch (IOException e) {
      e.printStackTrace();
    }
    try {
      out.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
    // 对每条记录执行查找和删除操作
    boolean delete = true;
    for (Message message : messages) {
     // System.out.print(message.getNum());
      if (!root.isLeaf() && root.getEntryNumber() == 1
          && root.getChildren().get(0).getEntryNumber() < t
          && root.getChildren().get(1).getEntryNumber() < t) {
        root =
            merge(root.getChildren().get(0), root.getChildren().get(1), root.getEntries().get(0));
      }
      /*
       * if (search(message.getNum()) != null) {
       *  System.out.print(":find it!"); 
       * } else {
       *    System.out.print(":not find it.!"); 
       * }
       */
      boolean deleteone = delete(root, message.getNum());
    //  System.out.println(" delete" + deleteone + "!");
      if (deleteone == false) {
        delete = false;
      }
      if (!delete) {
        return;
      }
      
    }
    System.out.println("all delete!");
    try {
      write = new FileWriter(new File("res/delete-output" + ".txt"));
      out = new BufferedWriter(write);
    } catch (FileNotFoundException e1) {
      e1.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
    
    outnumber = 0;
    printNode(root);
    System.out.println("outnumber:" + outnumber);
    System.out.println(delete);
    try {
      in.close(); 
      out.close();
    } catch (IOException e1) {
      e1.printStackTrace();
    }
  }

  private static BtreeNode merge(BtreeNode leftNode, BtreeNode rightNode, Entry middle) {
    leftNode.addEntry(middle);
    for (int i = 0; i < rightNode.getEntryNumber(); i++) {
      Entry entry = rightNode.getEntries().get(i);
      leftNode.addEntry(entry);
    }
    BtreeNode childNode = null;
    for (int i = 0; i < rightNode.getChildrenNumber(); i++) {
      childNode = rightNode.getChildren().get(i);
      leftNode.addChild(childNode);
    }
    return leftNode;
  }

  /**
   * build the B-tree index
   * 
   * @param messages
   */
  public static void buildBtree(List messages) {
    root = new BtreeNode();
    for (Message message : messages) {
      insert(message, root);
    }
  }

  private static void printNode(BtreeNode node) {
    if (node.isLeaf()) {
      for (int i = 0; i < node.getEntryNumber(); i++) {
        Entry entry = node.getEntries().get(i);
        try {
          out.write(entry.key + " " + entry.value);
          out.newLine();
          outnumber++;
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    } else {
      for (int i = 0; i < node.getChildrenNumber(); i++) {
        printNode(node.getChildren().get(i));
        if (node.getEntryNumber() <= i) continue;
        Entry entry = node.getEntries().get(i);
        try {
          out.write(entry.key + " " + entry.value);
          out.newLine();
          outnumber++;
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
  }

  /**
   * insert a new node in 'node'
   * 
   * @param message
   * @param node
   */
  private static void insert(Message message, BtreeNode node) {
    // node是叶子节点
    if (node.isLeaf()) {
      node.addEntry(new Entry(message.getNum(), message.getString()));
      // node空间未满
      if (node.getEntryNumber() <= cnt) {
        return;
      } else {
        // node空间满了,需要分裂
        balence(node);
      }
    } else {
      // node不是叶子节点,插入合适的子节点中
      List entries = node.getEntries();
      boolean flag = false;
      for (int i = 0; i < entries.size(); i++) {
        int key = entries.get(i).key;
        if (message.getNum() <= key) {
          insert(message, node.getChildren().get(i));
          flag = true;
          break;
        }
      }
      if (!flag) {
        insert(message, node.getChildren().get(node.getEntryNumber()));
      }
    }
  }

  /**
   * the node is overflow,needs split
   * 
   * @param node
   */
  private static void balence(BtreeNode node) {
    int middleIndex = (cnt) / 2;
    List entries = node.getEntries();

    // 分裂;
    BtreeNode fatherNode = new BtreeNode();
    BtreeNode leftChild = new BtreeNode();
    BtreeNode rightChild = new BtreeNode();
    for (int i = 0; i < middleIndex; i++) {
      leftChild.addEntry(entries.get(i));
      if (i < node.getChildrenNumber()) {
        leftChild.addChild(node.getChildren().get(i));
      }
    }
    if (middleIndex < node.getChildrenNumber()) {
      leftChild.addChild(node.getChildren().get(middleIndex));
    }
    for (int i = middleIndex + 1; i <= cnt; i++) {
      rightChild.addEntry(entries.get(i));
      if (i < node.getChildrenNumber()) {
        rightChild.addChild(node.getChildren().get(i));
      }
    }
    if (cnt + 1 < node.getChildrenNumber()) {
      rightChild.addChild(node.getChildren().get(cnt + 1));
    }
    // node有父节点,上移至父节点
    if (node.getFather() != null) {
      fatherNode = node.getFather();
      fatherNode.getChildren().remove(node);
      fatherNode.addEntry(entries.get(middleIndex));
      fatherNode.addChild(leftChild);
      fatherNode.addChild(rightChild);
    } else {// node无父节点,更新root
      fatherNode.addEntry(entries.get(middleIndex));
      fatherNode.addChild(leftChild);
      fatherNode.addChild(rightChild);
      root = fatherNode;
    }
    // 父节点溢出,继续分裂
    if (fatherNode.getEntryNumber() <= cnt) {
      return;
    } else {
      balence(fatherNode);
    }
  }

  /**
   * search in the B-tree
   * 
   * @param key
   * @return
   */
  private static List search(Integer key) {
    return search(root, key);
  }

  /**
   * search in one node
   * 
   * @param node
   * @param key
   * @return
   */
  private static List search(BtreeNode node, Integer key) {
    SearchResult result = node.searchKey(key);
    if (result.isExist()) {
      return result.getValue();
    } else {
      if (node.isLeaf()) {
        return null;
      } else {
        boolean flag = false;
        List entries = node.getEntries();
        for (int i = 0; i < entries.size(); i++) {
          if (key < entries.get(i).key) {
            flag = true;
            return search(node.getChildren().get(i), key);
          }
        }
        if (!flag) {
          return search(node.getChildren().get(node.getChildrenNumber() - 1), key);
        }
      }
    }
    return null;
  }

  /**
   * 找到以node为根节点的子树里最大的一项
   * 
   * @param node
   * @return the max entry found
   */
  private static Entry findAndDeletePrev(BtreeNode node) {
    Entry entry = null;
    while (!node.isLeaf()) {
      node = node.getChildren().get(node.getChildrenNumber() - 1);
    }

    entry = node.getEntries().get(node.getEntryNumber() - 1);
    // node.getEntries().remove(node.getEntryNumber()-1);
    return entry;
  }

  /**
   * 找到以node为根节点的子树里最小的一项
   * 
   * @param node
   * @return the min entry found
   */
  private static Entry findAndDeleteNext(BtreeNode node) {
    Entry entry = null;
    while (!node.isLeaf()) {
      node = node.getChildren().get(0);
    }
    entry = node.getEntries().get(0);
    // node.getEntries().remove(0);
    return entry;
  }

  private static boolean delete(BtreeNode node, Integer key) {
    // 1.待删除的key在叶子节点,直接删除就好
    if (node.isLeaf()) {
      List entries = node.getEntries();
      for (int i = 0; i < entries.size(); i++) {
        Entry entry = entries.get(i);
        if (entry.key == key) {
          node.getEntries().remove(entry);
          return true;
        }
      }
      return false;
    }
    // x不是叶子节点
    boolean isExist = false;
    int position = node.getEntryNumber();
    for (int i = 0; i < node.getEntryNumber(); i++) {
      Entry entry = node.getEntries().get(i);
      if (entry.key > key) {
        position = i;
        break;
      }
      // 2.要删除的key在内部节点x
      if (entry.key == key) {
        isExist = true;
        BtreeNode leftChildNode = node.getChildren().get(i);
        BtreeNode rightChildNode = node.getChildren().get(i + 1);
        // 2.(a)如果x的左分支结点y至少包含t个关键字,则找出以y为根的子树的最右的关键字prev,并替换target,并在y中递归删除prev。
        if (leftChildNode.getEntryNumber() >= t) {
          Entry prev = findAndDeletePrev(leftChildNode);
          if (prev == null) {
            return false;
          }
          node.getEntries().set(i, prev);
          return delete(leftChildNode, prev.key);
        }
        // 2.(b) 如果x的右分支结点z至少包含t个关键字,则找出以z为根的子树的最左的关键字next,并替换target,并在z中递归删除next.
        if (rightChildNode.getEntryNumber() >= t) {
          Entry next = findAndDeleteNext(rightChildNode);
          if (next == null) {
            return false;
          }
          node.getEntries().set(i, next);
          return delete(rightChildNode, next.key);
        }

        // 2.(c) 否则,如果y和z都只有t-1个关键字,则将target与z合并到y中,使得y有2t-1个关键字,再从y中递归删除target.
        node.getEntries().remove(entry);
        node.getChildren().remove(rightChildNode);
        leftChildNode = merge(leftChildNode, rightChildNode, entry);
        return delete(leftChildNode, key);
      }
    }
    // (3) 如果关键字不在内部结点x中,则必然在x的某个分支结点p[i]为根的子树中,
    // 执行3a、3b或者3c以保证我们降至一个包含至少t个关键字的结点,然后通过对x的某个合适的子结点递归而结束。
    if (!isExist) {
      BtreeNode childNode = node.getChildren().get(position); // p[i];
      if (childNode.getEntryNumber() >= t) {
        return delete(childNode, key);
      }
      BtreeNode leftChildNode = null;
      BtreeNode rightChildNode = null;
      if (position > 0) {
        leftChildNode = node.getChildren().get(position - 1);
      }
      if (position < node.getChildrenNumber() - 1) {
        rightChildNode = node.getChildren().get(position + 1);
      }
      // (a) 如果p[i-1]拥有至少t个关键字,则将x[i-1]的关键字降至p[i]中,将p[i-1]的最大结点上升至x中。
      if (leftChildNode != null && leftChildNode.getEntryNumber() >= t) {
        Entry x = node.getEntries().get(position - 1);
        Entry y = leftChildNode.getEntries().get(leftChildNode.getEntryNumber() - 1);
        node.getEntries().remove(x);
        leftChildNode.getEntries().remove(y);
        node.addEntry(y);
        childNode.addEntry(x);
        if (leftChildNode.getChildrenNumber() > 0) {
          BtreeNode changeChild =
              leftChildNode.getChildren().get(leftChildNode.getChildrenNumber() - 1);
          leftChildNode.getChildren().remove(leftChildNode.getChildrenNumber() - 1);
          childNode.addChild(changeChild);
        }
        return delete(childNode, key);
      }
      // (b) 如果p[i+1]拥有至少t个关键字,则将x[i]的关键字降至p[i]中,将p[i+1]的最小关键字上升至x中。
      if (rightChildNode != null && rightChildNode.getEntryNumber() >= t) {
        Entry x = node.getEntries().get(position);
        Entry y = rightChildNode.getEntries().get(0);
        node.getEntries().remove(x);
        rightChildNode.getEntries().remove(y);
        node.addEntry(y);
        childNode.addEntry(x);
        if (rightChildNode.getChildrenNumber() > 0) {
          BtreeNode changeChild = rightChildNode.getChildren().get(0);
          rightChildNode.getChildren().remove(0);
          childNode.addChild(changeChild);
        }
        return delete(childNode, key);
      }
      // (c) 否则将p[i]与其中一个兄弟合并,将x[i-1]或x[i]的关键字降至合并的结点中,成为中间关键字。
      if (leftChildNode != null) {
        Entry x = node.getEntries().get(position - 1);
        node.getEntries().remove(x);
        leftChildNode = merge(leftChildNode, childNode, x);
        node.getChildren().remove(childNode);
        return delete(leftChildNode, key);
      }
      if (rightChildNode != null && leftChildNode == null) {
        Entry x = node.getEntries().get(position);
        node.getEntries().remove(x);
        childNode = merge(childNode, rightChildNode, x);
        node.getChildren().remove(rightChildNode);
        return delete(childNode, key);
      }
    }
    return false;
  }
}


 

你可能感兴趣的:(数据库,B树)