Advertisement
Guest User

Untitled

a guest
Nov 8th, 2013
127
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 9.94 KB | None | 0 0
  1. package prog10;
  2.  
  3. import java.util.*;
  4.  
  5. public class BTree<K extends Comparable<K>, V> extends AbstractMap<K, V>
  6.         implements Map<K, V> {
  7.  
  8.     /**
  9.      * At the bottom of the tree, this is an data entry in the directory list.
  10.      * It is called a leaf and contains the V value in valueOrList. Inside the
  11.      * tree, this is a list entry. Its valueOrList points to list the next level
  12.      * down.
  13.      */
  14.     private class Entry<K extends Comparable<K>, V> implements Map.Entry<K, V> {
  15.         private K key;
  16.         private Object valueOrList;
  17.  
  18.         private Entry(K key, V value) {
  19.             this.key = key;
  20.             valueOrList = value;
  21.         }
  22.  
  23.         private Entry(ArrayList<Entry<K, V>> list) {
  24.             key = list.get(0).key;
  25.             valueOrList = list;
  26.         }
  27.  
  28.         public K getKey() {
  29.             return key;
  30.         }
  31.  
  32.         private boolean bottom() {
  33.             return !(valueOrList != null && valueOrList instanceof ArrayList
  34.                     && getList().size() > 0 && getList().get(0) instanceof Entry);
  35.         }
  36.  
  37.         public V getValue() {
  38.             return (V) valueOrList;
  39.         }
  40.  
  41.         public V setValue(V value) {
  42.             V old = getValue();
  43.             valueOrList = value;
  44.             return old;
  45.         }
  46.  
  47.         public ArrayList<Entry<K, V>> getList() {
  48.             return (ArrayList<Entry<K, V>>) valueOrList;
  49.         }
  50.  
  51.         public String toString() {
  52.             return "" + getKey() + " " + getValue();
  53.         }
  54.     }
  55.  
  56.     // (4) means give it a capacity (length) of 4. size is set to 0.
  57.     private ArrayList<Entry<K, V>> list = new ArrayList<Entry<K, V>>(4);
  58.  
  59.     /**
  60.      * Find the index of the entry that contains key. Remember that if key comes
  61.      * before list.get(i).key, then i is too big. Start with the last index and
  62.      * work backwards. Return -1 if the key is definitely not there.
  63.      */
  64.     private int findIndex(K key, ArrayList<Entry<K, V>> list) {
  65.         int i = list.size() - 1;
  66.         // EXERCISE
  67.         // Decrease i to the correct value.
  68.  
  69.         while (i >= 0) {
  70.             if (key.compareTo(list.get(i).getKey()) >= 0)
  71.                 return i;
  72.             i--;
  73.         }
  74.         return -1;
  75.     }
  76.  
  77.     /**
  78.      * Recursively find the leaf entry for the key in the tree. Return null if
  79.      * not there.
  80.      */
  81.     private Entry<K, V> find(K key, ArrayList<Entry<K, V>> list) {
  82.         // If the list is empty, done.
  83.         if (list.size() == 0)
  84.             return null;
  85.  
  86.         // Find the index i which should contain the key's entry.
  87.         int i = findIndex(key, list);
  88.  
  89.         // If the key comes before everyone, it is not there. (Poor Aaron.)
  90.         if (i < 0)
  91.             return null;
  92.  
  93.         // If the list entries are leaves (contain data not lists):
  94.         if (list.get(0).bottom()) {
  95.             // EXERCISE
  96.             // Check if entry i is the one we want. Be careful!
  97.             // If it is, return it. If not, return null.
  98.             if (key.compareTo(list.get(i).getKey()) == 0)
  99.                 return list.get(i);
  100.             return null;
  101.         }
  102.  
  103.         // List contains lists.
  104.         if (list.get(0).getValue() instanceof ArrayList)
  105.             // Recursively find the key in the list at i.
  106.             return find(key, list.get(i).getList());
  107.         return null;
  108.     }
  109.  
  110.     public boolean containsKey(K key) {
  111.         return find(key, list) != null;
  112.     }
  113.  
  114.     public V get(Object obj) {
  115.         K key = (K) obj;
  116.         return find(key, list).getValue();
  117.     }
  118.  
  119.     /**
  120.      * Split off a right hand list for a list containing four elements. Original
  121.      * list contains [0] and [1] Returned list contains what used to be [2] and
  122.      * [3]. As always, new list capacity should be 4.
  123.      */
  124.     private ArrayList<Entry<K, V>> split(ArrayList<Entry<K, V>> list) {
  125.         ArrayList<Entry<K, V>> right = new ArrayList<Entry<K, V>>(4);
  126.         right.add(list.get(2));
  127.         right.add(list.get(3));
  128.         list.remove(3);
  129.         list.remove(2);
  130.         return right;
  131.     }
  132.  
  133.     public V put(K key, V value) {
  134.         Entry<K, V> entry = find(key, list);
  135.         if (entry != null) {
  136.             V old = entry.getValue();
  137.             entry.setValue(value);
  138.             return old;
  139.         }
  140.  
  141.         insert(key, value, list);
  142.  
  143.         // Look at this!!
  144.         if (list.size() == 4) {
  145.             ArrayList<Entry<K, V>> left = list;
  146.             ArrayList<Entry<K, V>> right = split(list);
  147.             list = new ArrayList<Entry<K, V>>(4);
  148.             list.add(new Entry<K, V>(left));
  149.             list.add(new Entry<K, V>(right));
  150.         }
  151.  
  152.         return null;
  153.     }
  154.  
  155.     /**
  156.      * Recursively insert an entry with key and value into list. Precondition:
  157.      * entry must not be there.
  158.      */
  159.     private void insert(K key, V value, ArrayList<Entry<K, V>> list) {
  160.         int i = findIndex(key, list);
  161.  
  162.         // If we are at the bottom level:
  163.         if (list.size() == 0 || list.get(0).bottom()) {
  164.             // EXERCISE
  165.             // Create a new Entry and insert it. Look at the API for List.
  166.             // You don't need a loop!
  167.             // Remember: this is an ordinary list of entries (leaf not
  168.             // internal).
  169.             // What index do you want to insert the new Entry?
  170.             // (Hint: it's not i, but it is close to it!)
  171.             Entry<K, V> newEntry = new Entry<K, V>(key, value);
  172.             list.add(i + 1, newEntry);
  173.  
  174.             return;
  175.         }
  176.  
  177.         // EXERCISE
  178.         // If key comes before all the keys in the list, what will i equal?
  179.         // In which sublist should the new key go?
  180.         // So what should you set i equal to in this case?
  181.         if (i == -1) {
  182.             i = 0;
  183.         }
  184.  
  185.         Entry<K, V> entry = list.get(i);
  186.         ArrayList<Entry<K, V>> sublist = entry.getList();
  187.  
  188.         insert(key, value, sublist);
  189.         entry.key = sublist.get(0).key;
  190.  
  191.         if (sublist.size() < 4)
  192.             return;
  193.  
  194.         ArrayList<Entry<K, V>> rightlist = split(sublist);
  195.  
  196.         // EXERCISE
  197.         // Create a new Entry with rightlist.
  198.         // Insert it into list. What index? (Hint: to the right of index i!)
  199.         Entry<K, V> theEntry = new Entry(rightlist);
  200.         list.add(i + 1, theEntry);
  201.  
  202.     }
  203.  
  204.     public V remove(K key) {
  205.         Entry<K, V> entry = find(key, list);
  206.  
  207.         if (entry == null)
  208.             return null;
  209.  
  210.         remove(key, list);
  211.  
  212.         // EXERCISE
  213.         // If the list has only one element and that element is not a
  214.         // leaf, then throw away the list and that entry and set list
  215.         // equal to that entry's list.
  216.         if (!entry.bottom() && list.size() == 1) {
  217.             list = entry.getList();
  218.             entry = null;
  219.         }
  220.         return entry.getValue();
  221.     }
  222.  
  223.     /**
  224.      * Recursively remove the entry with key from the list. Precondition: entry
  225.      * must be there.
  226.      */
  227.     private void remove(K key, ArrayList<Entry<K, V>> list) {
  228.         // EXERCISE
  229.         // Use findIndex to find the index to remove from.
  230.         int index = findIndex(key, list);
  231.  
  232.         // If the key comes before everyone, it is not there. (Poor Aaron.)
  233.         if (index == -1)
  234.             return;
  235.  
  236.         // If the Entry at that index is a leaf, then it must be the one
  237.         // we want to remove. Remove it using the remove method of
  238.         // ArrayList. Then you are done.
  239.         if (list.get(index).bottom()) {
  240.             list.remove(index);
  241.             return;
  242.         }
  243.  
  244.         // Otherwise, get the Entry at that index, which is an internal entry.
  245.         Entry<K, V> entry = list.get(index);
  246.  
  247.         // And get its list, call it the sublist.
  248.         ArrayList<Entry<K, V>> sublist = entry.getList();
  249.  
  250.         // Recursively remove the entry with the key from that sublist.
  251.         remove(key, sublist);
  252.  
  253.         // Make sure to update the key field of the entry because the
  254.         // sublist may have a new key at index 0 now.
  255.         entry.key = sublist.get(0).getKey();
  256.  
  257.         // If the size of the sublist is still 2 or 3, then we are done.
  258.         if (sublist.size() == 2 || sublist.size() == 3)
  259.             return;
  260.  
  261.         // Otherwise, we need to merge the sublist with its left or right
  262.         // neighbor in list. To keep things simple, merge it with the one
  263.         // on the right, with index+1, but if the index is the last index,
  264.         // that's not going to work. So in that case, decrement the index
  265.         // and make the entry and sublist be the ones which belong to that
  266.         // one.
  267.         ArrayList<Entry<K, V>> rightSublist;
  268.  
  269.         if (index == list.size() - 1 && index != 0) {
  270.             index--;
  271.             entry = list.get(index);
  272.             sublist = entry.getList();
  273.             rightSublist = list.get(index + 1).getList();
  274.         } else if (this.list.size() == 1) {
  275.  
  276.             /**
  277.              * this is the one case! we need to merge it with its neighbor if it
  278.              * has one if it doesn't then remove it
  279.              *
  280.              * nope wrong
  281.              */
  282.             while (this.list.size() == 1)
  283.                 this.list = this.list.get(0).getList();        
  284.             return;
  285.  
  286.         }
  287.         else
  288.         {
  289.             rightSublist = list.get(index + 1).getList();
  290.         }
  291.  
  292.         // Add all the elements of the sublist to the right to the current
  293.         // sublist. You can just use the addAll method of ArrayList.
  294.         sublist.addAll(rightSublist);
  295.  
  296.         // Remove the entry to the right from list.
  297.         list.remove(index + 1);
  298.        
  299.         // If the size of the sublist is less than 4, then we are done.
  300.         if (sublist.size() < 4)
  301.             return;
  302.  
  303.         // Otherwise, split the sublist. Look at insert to see how this
  304.         // is done.
  305.         ArrayList<Entry<K, V>> rightList = split(sublist);
  306.  
  307.         // Create a new Entry with rightlist.
  308.         // Insert it into list. What index? (Hint: to the right of index i!)
  309.         Entry<K, V> theEntry = new Entry(rightList);
  310.         list.add(index + 1, theEntry);
  311.     }
  312.  
  313.     // Required to implement Map<K, V>. Ignore.
  314.     public Set<Map.Entry<K, V>> entrySet() {
  315.         return null;
  316.     }
  317.  
  318.     public String toString() {
  319.         return "-------------------------\n" + toString(list, 0);
  320.     }
  321.  
  322.     private String toString(ArrayList<Entry<K, V>> list, int indent) {
  323.         String ret = "";
  324.         for (int i = 0; i < list.size(); i++) {
  325.             for (int j = 0; j < indent; j++)
  326.                 ret = ret + "    ";
  327.             ret = ret + list.get(i).key;
  328.             if (list.get(i).bottom())
  329.                 ret = ret + " " + list.get(i).getValue() + "\n";
  330.             else
  331.                 ret = ret + "\n" + toString(list.get(i).getList(), indent + 4);
  332.         }
  333.         return ret;
  334.     }
  335.  
  336.     public static void main(String[] args) {
  337.         BTree<String, Integer> tree = new BTree<String, Integer>();
  338.  
  339.         tree.put("Brad", 46);
  340.         System.out.println(tree);
  341.         tree.put("Hal", 10);
  342.         System.out.println(tree);
  343.         tree.put("Kyle", 6);
  344.         System.out.println(tree);
  345.         tree.put("Lisa", 43);
  346.         System.out.println(tree);
  347.         tree.put("Lynne", 43);
  348.         System.out.println(tree);
  349.         tree.put("Victor", 46);
  350.         System.out.println(tree);
  351.         tree.put("Zoe", 6);
  352.         System.out.println(tree);
  353.         tree.put("Zoran", 76);
  354.         System.out.println(tree);
  355.  
  356.         tree.remove("Zoe");
  357.         System.out.println(tree);
  358.         tree.remove("Kyle");
  359.         System.out.println(tree);
  360.         tree.remove("Brad");
  361.         System.out.println(tree);
  362.         tree.remove("Zoran");
  363.         System.out.println(tree);
  364.         tree.remove("Lisa");
  365.         System.out.println(tree);
  366.     }
  367. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement