struct btNode {
uint16_t key;
void* data;
btNode* left;
btNode* right;
};
btNode* root = NULL;
struct observed {
float temp;
float airPress;
float humidity;
};
struct lNode {
uint16_t key;
void* data;
lNode* next;
};
lNode *lStart = NULL, *lEnd = NULL;
bool btInsert(uint16_t key, btNode** leaf, observed* dta) {
if (*leaf == NULL) {
*leaf = (btNode*)malloc(sizeof(btNode));
if (!*leaf) { return false; }
(*leaf)->key = key;
(*leaf)->left = (*leaf)->right = NULL;
(*leaf)->data = malloc(sizeof(observed));
memcpy((*leaf)->data, dta, sizeof(observed));
return true;
}
if (key < (*leaf)->key) {
return btInsert(key, &(*leaf)->left, dta);
}
return btInsert(key, &(*leaf)->right, dta);
}
observed* btSearch(uint16_t key, btNode* leaf) {
if (leaf) {
if (leaf->key == key) {
return (observed*)leaf->data;
}
if (key < leaf->key) {
return btSearch(key, leaf->left);
}
else
return btSearch(key, leaf->right);
}
else {
return NULL;
}
}
void btDeleteTree(btNode* leaf) {
if (leaf) {
btDeleteTree(leaf->left);
btDeleteTree(leaf->right);
free(leaf->data);
free(leaf);
}
}
void btPrint(btNode* leaf) {
if (leaf) {
btPrint(leaf->left);
observed* found = (observed*)leaf->data;
cout << "key: " << leaf->key << " Temp: " << found->temp << " Press: " <<
found->airPress << " Hum: " << found->humidity << '\n';
btPrint(leaf->right);
}
}
int btHeight(btNode* leaf) {
if (leaf) {
return 1 + btMax(btHeight(leaf->left), btHeight(leaf->right));
}
return 0;
}
int btMax(int a, int b) {
return (a <= b) ? b : a;
}
int btCount(btNode* leaf) {
if (leaf) {
return 1 + btCount(leaf->left) + btCount(leaf->right);
}
return 0;
}
bool appendToList(uint16_t key, void* data) {
lNode* nNode = (lNode*)malloc(sizeof(lNode));
if (!nNode) { return false; }
nNode->key = key;
nNode->data = data;
nNode->next = NULL;
if (!lEnd) {
lStart = lEnd = nNode;
}
else {
lEnd = lEnd->next = nNode;
}
return true;
}
lNode* readListItem(int item) {
lNode* rNode = lStart;
for (int i = 0; i < item; i++) {
rNode = rNode->next;
}
return rNode;
}
void deleteList() {
lNode* dNode = lStart;
while (dNode) {
lStart = dNode->next;
free(dNode);
dNode = lStart;
}
lStart = lEnd = NULL;
}
void btExtractKey(btNode* leaf) {
if (leaf) {
btExtractKey(leaf->left);
appendToList(leaf->key, leaf->data);
btExtractKey(leaf->right);
free(leaf); // delete the tree leaf
}
}
void resetTree(btNode** leaf, int iFrom, int iTo) {
if (iFrom > iTo) { return; }
int iMid = (iFrom + iTo) / 2;
lNode* rNode = readListItem(iMid);
btReset(leaf, rNode);
resetTree(leaf, iFrom, iMid - 1);
resetTree(leaf, iMid + 1, iTo);
}
bool btReset(btNode** leaf, lNode* rNode) {
if (*leaf == NULL) {
*leaf = (btNode*)malloc(sizeof(btNode));
(*leaf)->key = rNode->key;
(*leaf)->left = (*leaf)->right = NULL;
(*leaf)->data = rNode->data;
return true;
}
else if (rNode->key < (*leaf)->key) {
return btReset(&(*leaf)->left, rNode);
}
return btReset(&(*leaf)->right, rNode);
}
void reBuildTree() {
int nCount = btCount(root);
btExtractKey(root);
root = NULL; //restart the tree
resetTree(&root, 0, nCount - 1);
deleteList(); //recover the linked list memory;
}
#include "stdafx.h"
#include <stdint.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
void btPrint(btNode*);
bool btInsert(uint16_t, btNode**, observed*);
observed* btSearch(uint16_t, btNode*);
void btDeleteTree(btNode*);
int btMax(int, int);
int btHeight(btNode*);
int btCount(btNode*);
bool appendToList(uint16_t, void*);
lNode* readListItem(int);
void deleteList();
void btExtractKey(btNode*);
void resetTree(btNode**, int, int);
bool btReset(btNode**, lNode*);
void reBuildTree();
int main()
{
int keys[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
for (int i = 0; i < 9; i++) {
observed obs = { rand() % 10,rand() % 20, rand() % 30 };
btInsert(keys[i], &root, &obs);
}
btPrint(root);
observed * found = btSearch(6, root);
if (found) {
cout << "Key 6 lookup = Temp: " << found->temp << " Press: " << found->airPress
<< " Hum: " << found->humidity << '\n';
}
else {
cout << "Nope\n";
}
cout << "B-Tree height: " << btHeight(root) << '\n';
cout << "Optimal height <= " << (int)log2(btCount(root)) + 1 << '\n';
reBuildTree();
cout << "B-Tree height now: " << btHeight(root) << '\n';
btDeleteTree(root);
cin.get();
return 0;
}
template<class T> inline Print &operator <<(Print &obj, T arg) { obj.print(arg); return obj; }
void setup() {
Serial.begin(115200);
int keys[] = {5, 3, 8, 2, 7, 6, 4, 9, 1};
//int keys[] = {1,2,3,4,5,6,7,8,9}; // an unbalanced insertion
for(int i = 0; i < 9; i++) {
observed obs = {random(1,10), random(11, 20), random(30, 40)};
if(btInsert(keys[i], &root, &obs)) {
Serial << "Inserted: " << '\n';
}
}
observed * found = btSearch(6, root);
if(found) {
Serial << "Key 6 = Temp: " << found->temp << " Press: " << found->airPress << " Hum: " << found->humidity << '\n';
} else {
Serial << "Nope\n";
}
btPrint(root); // display the tree values
Serial << "B-Tree height: " << btHeight(root) << '\n';
Serial << "Node Count: " << btCount(root) << '\n';
Serial << "Optimal height <= " << (int)(log(btCount(root)) / log(2) + 0.5) << '\n';
reBuildTree();
btPrint(root);
Serial << "B-Tree height: " << btHeight(root) << '\n';
btDeleteTree(root);
}
#ifndef BTree_h
#define BTree_h
// T is the data type and K is the key type
// K must support == and < operators
template<typename T, typename K>
class BTree {
public:
using BTIter = void(*)(K, T*);
BTree();
~BTree();
bool insert(K, T*, bool=false);
size_t count();
size_t height();
T* search(K);
T* searchGE(K);
void iterate(BTIter);
bool isBalanced();
void balanceTree();
private:
struct btNode {
K key;
void* data;
btNode* left;
btNode* right;
};
btNode* root = NULL;
size_t tSize, nSize;
bool btInsert(K, btNode**, T*, bool);
void btDelete(btNode*);
size_t btCount(btNode*);
size_t btHeight(btNode*);
size_t btMax(size_t, size_t);
T* btSearch(K, btNode*);
T* btSearchGE(K, btNode*);
void btIterate(btNode*, BTIter);
void rightRotate(btNode**);
void leftRotate(btNode**);
void vineToTree(btNode**);
void treeToVine(btNode**);
void compress(btNode**, int);
void rotateOrCompress(btNode**, int);
void dswTreeBalance(btNode**);
};
//constructor
template<typename T, typename K>
BTree<T, K>::BTree() {
tSize = sizeof(T);
nSize = sizeof(btNode);
}
// destructor
template<typename T, typename K>
BTree<T, K>::~BTree() {
btDelete(root);
}
template<typename T, typename K>
bool BTree<T, K>::insert(K key, T* data, bool updateValue=false) {
return btInsert(key, &root, data, updateValue);
}
template<typename T, typename K>
size_t BTree<T, K>::count() {
return btCount(root);
}
template<typename T, typename K>
size_t BTree<T, K>::height() {
return btHeight(root);
}
template<typename T, typename K>
T* BTree<T, K>::search(K key) {
return btSearch(key, root);
}
template<typename T, typename K>
T* BTree<T, K>::searchGE(K key) {
return btSearchGE(key, root);
}
template<typename T, typename K>
void BTree<T, K>::iterate(BTIter callback) {
btIterate(root, callback);
}
template<typename T, typename K>
bool BTree<T, K>::isBalanced() {
return btHeight(root) <= (int)log2(btCount(root)) + 1;
}
template<typename T, typename K>
void BTree<T, K>::balanceTree() {
dswTreeBalance(&root);
}
//private methods
template<typename T, typename K>
bool BTree<T, K>::btInsert(K key, btNode** leaf, T* data, bool uV) {
if (*leaf == NULL) {
*leaf = (btNode*)malloc(nSize);
if (!*leaf) { return false; }
(*leaf)->key = key;
(*leaf)->left = (*leaf)->right = NULL;
(*leaf)->data = malloc(tSize);
if ((*leaf)->data) {
memcpy((*leaf)->data, data, tSize);
return true;
}
else {
return false;
}
}
if (key == (*leaf)->key) {
if (uV) {
// can update the data for this key so
memcpy((*leaf)->data, data, tSize);
return true;
}
else {
return false; // duplicate key update not allowed
}
}
if (key < (*leaf)->key) {
return btInsert(key, &(*leaf)->left, data, uV);
}
return btInsert(key, &(*leaf)->right, data, uV);
}
template<typename T, typename K>
void BTree<T, K>::btDelete(btNode* leaf) {
if (leaf) {
btDelete(leaf->left);
btDelete(leaf->right);
free(leaf->data);
free(leaf);
}
}
template<typename T, typename K>
size_t BTree<T, K>::btCount(btNode* leaf) {
if (leaf) {
return 1 + btCount(leaf->left) + btCount(leaf->right);
}
return 0;
}
template<typename T, typename K>
size_t BTree<T, K>::btMax(size_t a, size_t b) {
return (a <= b) ? b : a;
}
template<typename T, typename K>
size_t BTree<T, K>::btHeight(btNode* leaf) {
if (leaf) {
return 1 + btMax(btHeight(leaf->left), btHeight(leaf->right));
}
return 0;
}
template<typename T, typename K>
T* BTree<T, K>::btSearch(K key, btNode* leaf) {
if (leaf) {
if (leaf->key == key) {
return (T*)leaf->data;
}
if (key < leaf->key) {
return btSearch(key, leaf->left);
}
else {
return btSearch(key, leaf->right);
}
}
return NULL;
}
template<typename T, typename K>
T* BTree<T, K>::btSearchGE(K key, btNode* leaf) {
if (leaf) {
if (leaf->key == key) {
return (T*)leaf->data;
}
if (key < leaf->key) {
return btSearchGE(key, leaf->left);
}
if (leaf->right) {
if (leaf->right->key >= key) {
return (T*)leaf->right->data;
}
return btSearchGE(key, leaf->right);
}
}
return NULL;
}
template<typename T, typename K>
void BTree<T, K>::btIterate(btNode*leaf, BTIter callback) {
if (leaf) {
btIterate(leaf->left, callback);
callback(leaf->key, (T*)leaf->data);
btIterate(leaf->right, callback);
}
}
template<typename T, typename K>
void BTree<T, K>::dswTreeBalance(btNode** rootP) {
btNode *root = *rootP;
treeToVine(&root);
vineToTree(&root);
*rootP = root;
}
template<typename T, typename K>
void BTree<T, K>::rightRotate(btNode** root) {
btNode *oldLeft, *oldLeftRight;
oldLeft = (*root)->left;
oldLeftRight = (*root)->left->right;
oldLeft->right = *root;
oldLeft->right->left = oldLeftRight;
*root = oldLeft;
}
template<typename T, typename K>
void BTree<T, K>::leftRotate(btNode** root) {
btNode *oldRight, *oldRightLeft;
oldRight = (*root)->right;
oldRightLeft = (*root)->right->left;
oldRight->left = *root;
oldRight->left->right = oldRightLeft;
*root = oldRight;
}
template<typename T, typename K>
void BTree<T, K>::treeToVine(btNode** tree) {
btNode* root = *tree;
if (!root) {
return;
}
while (root->left) {
rightRotate(&root);
}
if (root->right) {
treeToVine(&(root->right));
}
*tree = root;
}
template<typename T, typename K>
void BTree<T, K>::vineToTree(btNode **vine) {
btNode *root = *vine;
int n = btCount(root);
// M is one less than largest power of 2 <= (n+1)
int M = pow(2, floor((log(n + 1) / log(2)))) - 1;
// or int M = pow(2, floor(log2(n + 1))) - 1;
compress(&root, n - M);
while (M > 1) {
M = floor(M / 2);
compress(&root, M);
}
*vine = root;
}
template<typename T, typename K>
void BTree<T, K>::compress(btNode **root, int times) {
for (int i = 0; i < times; i++) {
rotateOrCompress(&(*root), i);
}
}
template<typename T, typename K>
void BTree<T, K>::rotateOrCompress(btNode **root, int times) {
if (times == 0) {
leftRotate(&(*root));
}
else {
rotateOrCompress(&((*root)->right), times - 1);
}
}
#endif
#include "stdafx.h"
#include <stdint.h>
#include <stdlib.h>
#include "BTree.h"
#include <iostream>
using namespace std;
struct observed {
float temp;
float airPress;
float humidity;
};
void btPrint(int, observed*);
int main()
{
BTree<observed, int> bTree;
int keys[] = {5, 3, 8, 2, 7, 6, 4, 9, 1, 12, 15, 21, 11, 26};
for (int i = 0; i < 14; i++) {
observed obs = { rand() % 10,rand() % 20, rand() % 30 };
if (bTree.insert(keys[i], &obs)) {
cout << "Inserted: " << '\n';
}
}
bTree.iterate(btPrint);
btPrint(11, bTree.searchGE(11));
btPrint(5, bTree.searchGE(5));
cout << (bTree.isBalanced() ? "Tree is balanced\n" : "Tree not balanced\n");
bTree.balanceTree();
cout << (bTree.isBalanced() ? "Tree is balanced\n" : "Tree not balanced\n");
cin.get();
return 0;
}
void btPrint(int key, observed* obs) {
cout << "Key: " << key << " Temp: " << obs->temp << " Press: " << obs->airPress << " Hum: " << obs->humidity << '\n';
}
#include "BTree.h"
template<class T> inline Print &operator <<(Print &obj, T arg) { obj.print(arg); return obj; }
int tst = 0;
void setup() {
Serial.begin(115200);
BTree<observed, int> bTree;
//int keys[] = {5, 3, 8, 2, 7, 6, 4, 9, 1};
int keys[] = {1,2,3,4,5,6,7,8,9};
for(int i = 0; i < 9; i++) {
observed obs = {random(1,10), random(11, 20), random(30, 40)};
if(bTree.insert(keys[i], &obs)) {
Serial << "Inserted: " << '\n';
}
}
bTree.iterate(btPrint);
Serial << "Tree height: " << bTree.height() << '\n';
Serial << (bTree.isBalanced() ? "Tree is balanced\n" : "Tree not balanced\n");
observed* fo = bTree.search(5);
btPrint(5, fo);
bTree.balanceTree();
Serial << "Tree height: " << bTree.height() << '\n';
tst = 0;
bTree.iterate(btPrint);
}
bool btPrint(int key, observed* obs) {
Serial << "Key: " << key << " Temp: " << obs->temp << " Press: " << obs->airPress << " Hum: " << obs->humidity << '\n';
}
Read the chapter in my book C++ Data Structures with immediate download from Amazon