作者:cleverpig
注释:由于BTree可用于j2me、DB等query场景中,而且原理易懂,自此就不做翻译了。
![image](http://www.matrix.org.cn/resource/upload/forum/2006_10_11_134239_YqcgYGvpos.gif)
What's B-Tree
![image](http://www.matrix.org.cn/resource/upload/forum/2006_10_11_132748_dyKcPkChmw.png)
Sample B-Tree
Tree structures support various basic dynamic set operations including Search, Predecessor, Successor, Minimum, Maximum, Insert, and Delete in time proportional to the height of the tree. Ideally, a tree will be balanced and the height will be log n where n is the number of nodes in the tree. To ensure that the height of the tree is as small as possible and therefore provide the best running time, a balanced tree structure like a red-black tree, AVL tree, or b-tree must be used.
When working with large sets of data, it is often not possible or desirable to maintain the entire structure in primary storage (RAM). Instead, a relatively small portion of the data structure is maintained in primary storage, and additional data is read from secondary storage as needed. Unfortunately, a magnetic disk, the most common form of secondary storage, is significantly slower than random access memory (RAM). In fact, the system often spends more time retrieving data than actually processing data.
B-trees are balanced trees that are optimized for situations when part or all of the tree must be maintained in secondary storage such as a magnetic disk. Since disk accesses are expensive (time consuming) operations, a b-tree tries to minimize the number of disk accesses. For example, a b-tree with a height of 2 and a branching factor of 1001 can store over one billion keys but requires at most two disk accesses to search for any node.
![image](http://www.matrix.org.cn/resource/upload/forum/2006_10_11_132756_fEzghWkwJP.gif)
Searching a B-Tree for Key 21
![image](http://www.matrix.org.cn/resource/upload/forum/2006_10_11_132802_lhLbQSXqsc.gif)
Inserting Key 33 into a B-Tree (w/ Split)
Java Binary Trees and Solutions
In Java, the key points in the recursion are exactly the same as in C or C++. In fact, I created the Java solutions by just copying the C solutions, and then making the syntactic changes. The recursion is the same, however the outer structure is slightly different.
In Java, we will have a BinaryTree object that contains a single root pointer. The root pointer points to an internal Node class that behaves just like the node struct in the C/C++ version. The Node class is private -- it is used only for internal storage inside the BinaryTree and is not exposed to clients. With this OOP structure, almost every operation has two methods: a one-line method on the BinaryTree that starts the computation, and a recursive method that works on the Node objects. For the lookup() operation, there is a BinaryTree.lookup() method that the client uses to start a lookup operation. Internal to the BinaryTree class, there is a private recursive lookup(Node) method that implements the recursion down the Node structure. This second, private recursive method is basically the same as the recursive C/C++ functions above -- it takes a Node argument and uses recursion to iterate over the pointer structure.
Java Binary Tree Structure
To get started, here are the basic definitions for the Java BinaryTree class, and the lookup() and insert() methods as examples...
OOP Style vs. Recursive Style
From the client point of view, the BinaryTree class demonstrates good OOP style -- it encapsulates the binary tree state, and the client sends messages like lookup() and insert() to operate on that state. Internally, the Node class and the recursive methods do not demonstrate OOP style. The recursive methods like insert(Node) and lookup (Node, int) basically look like recursive functions in any language. In particular, they do not operate against a "receiver" in any special way. Instead, the recursive methods operate on the arguments that are passed in which is the classical way to write recursion. My sense is that the OOP style and the recursive style do not be combined nicely for binary trees, so I have left them separate. Merging the two styles would be especially awkward for the "empty" tree (null) case, since you can't send a message to the null pointer. It's possible to get around that by having a special object to represent the null tree, but that seems like a distraction to me. I prefer to keep the recursive methods simple, and use different examples to teach OOP.
Java Solutions
Here are the Java solutions to the 14 binary tree problems. Most of the solutions use two methods:a one-line OOP method that starts the computation, and a recursive method that does the real operation. Make an attempt to solve each problem before looking at the solution -- it's the best way to learn.
1. Build123() Solution (Java)
2. size() Solution (Java)
3. maxDepth() Solution (Java)
4. minValue() Solution (Java)
5. printTree() Solution (Java)
6. printPostorder() Solution (Java)
7. hasPathSum() Solution (Java)
8. printPaths() Solution (Java)
9. mirror() Solution (Java)
10. doubleTree() Solution (Java)
11. sameTree() Solution (Java)
12. countTrees() Solution (Java)
13. isBST1() Solution (Java)
14. isBST2() Solution (Java)