Self-Balancing Binary Search Tree (BST) in Pure VB6 Code
(no dependencies, no typelib)
This is a pure VB6 self-balancing binary search tree (BST) developed in the vein of Adelson-Velsky and Landis's (AVL) work. If you're familiar with the VB6 Collection object, it has many similarities. With respect to speed, it competes well with a VB6 Collection, and offers several advantages. It's intended to be used without the need for any error trapping. The only error it should produce is possibly an out-of-memory error, but even here, each node should take less memory than a VB6 Collection node.
Also, one of the large advantages over the VB6 Collection, is that we can rather easily create nodes with any type key, and/or any type value. The initial release is the "String Key" and "no Value" category. I will develop other categories, with other types of keys and/or values, possibly upon request. See post #2 for the list of the ones currently developed.
Another advantage, regardless of the category, is that we have easy access to the keys, and they'll always be sorted. So, if you like, you can use this as a sort algorithm, to which additional keys can be added, maintaining your sorting.
And, if the key is a string, this one is full Unicode case-sensitive. The fact that the Collection is case-insensitive has been a source of consternation for me on many occasions.
To use any of them, just include the two associated classes in your project, anv voilà, you're up and running. For example, for the "String Key" and "no Value" category, drop both the BST_StrKey_NoVal.cls and Nod_StrKey_NoVal.cls into your project, create an object variable of BST_StrKey_NoVal type, instantiate it, and you're up and running. Don't do anything with the Nod_StrKey_NoVal class, as it's only used internally by the BST_StrKey_NoVal class (and that's true regardless of the key/value type category you chose).
Once you've got the classes in your project, you can instantiate as many different BST_StrKey_NoVal objects (i.e., trees) as you need. They will be maintained as separate BST trees.
The following are the exposed procedures available for production code. (For illustration purposes, I'll assume your instantiated object variable is named "BST".):
- BST.Insert(Key)
Key must be a non-empty string. No duplicates allowed. Returns TRUE if successfully added, or FALSE if it's a DUPE. - BST.Delete(Key)
Key must exist in the tree. Returns TRUE if deleted, or FALSE if not found. - BST.KeyExists(Key)
Returns TRUE or FALSE. - BST.Count
Returns the number of nodes currently in the tree. - BST.Clear
Clears out all the nodes, without any need for re-instantiating the BST object. - BST.KeyArray
This returns a sorted string array of all the nodes in the tree. There is an optional "descending" argument. A 0 to -1 array is returned if the tree is empty. - BST.NextKey
This provides a way to loop through the keys in the tree (sorted). - BST.PrevKey
Same as BST.NextKey, but in descending order. - BST.Reset
If you're actively using either BST.NextKey or BST.PrevKey, this provides a way to start the internal loop over.
And if it's a category that has a value, you also get these procedures:
- BST.Insert(Key, Value)
If there's a value associated with the BST, this one replaces the BST.Insert(Key), as you must supply the value when inserting nodes into the tree. - BST.Value(Key)
This is a "Get" property for fetching the value for a known key. It returns vbNullString if the key isn't found. Although, it can also be a vbNullString value for a known key. So, you may need to use BST.KeyExists to differentiate. - BST.Value(Key) = Value
A "Let" property for the value so the value can be changed without Delete/Insert being needed. This one isn't available if the value can only accept an object. - Set BST.Value(Key) = Value
A "Set" property for the value so the value can be changed without Delete/Insert being needed. This one is available only if/when the value can accept an object. - BST.ValueArray
Returns a string array of the values, sorted based on the keys. A 0 to -1 array is returned if the tree is empty.
A few more notes about these procedures:
- The way BST.NextKey and BST.PrevKey are designed, they can be used in conjunction with each other. For example, if we call BST.NextKey: BST.PrevKey: BST.NextKey, those two NextKey calls will return the same key.
- Anytime BST.Insert or BST.Delete are called, the BST.NextKey and/or BST.PrevKey will be reset.
- If both BST.KeyArray and BST.ValueArray are fetched, they will be synchronized.
- If you'd like to use the For Each... syntax, it can be done with the KeyArray property. Although, doing this will create a memory copy of all the keys while the For Each loop is executing. It's recommended to use the BST.NextKey instead for large collections:
Code:
Dim v As Variant
For Each v In BST.KeyArray
Debug.Print v ' Prints the keys.
Next
' And, if there's a value, these are also possibilities.
For Each v In BST.KeyArray
Debug.Print v, BST.Value(CStr(v)) ' Prints both keys and values.
Next
For Each v In BST.ValueArray
Debug.Print v ' Prints the values, sorted based on the keys.
Next
Enjoy. :)