wavlTree

wavl tree: weak AVL Tree
git clone https://noulin.net/git/wavlTree.git
Log | Files | Refs | README | LICENSE

commit fa9df52519f6c34aea9e2ca66f8f8146499e61fc
parent 2b8ee36374b5189c645c0994f41cf63721794c90
Author: Remy Noulin <loader2x@gmail.com>
Date:   Sat, 29 Dec 2018 20:37:12 +0100

add iterator

README.md                  |  10 +++
main.c                     |   8 ++-
wavlTree.c                 | 162 ++++++++++++++++++++++++++++++---------------
wavlTree.h                 |  24 ++++++-
wavlTreeNamespaceCleanup.h |  13 ----
5 files changed, 148 insertions(+), 69 deletions(-)

Diffstat:
AREADME.md | 10++++++++++
Mmain.c | 8+++++++-
MwavlTree.c | 162+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
MwavlTree.h | 24+++++++++++++++++++++---
MwavlTreeNamespaceCleanup.h | 13-------------
5 files changed, 148 insertions(+), 69 deletions(-)

diff --git a/README.md b/README.md @@ -0,0 +1,10 @@ +# this repo +WAVL tree implementation in C, inspired by (dmcmanam/bbst-showdown [JAVA implementation])[https://github.com/dmcmanam/bbst-showdown]. +All tests have passed and there is no memory leak(tested with valgrind). + +# What is WAVL tree + +WAVL tree is an attempt to combine the best characteristics of a AVL trees and red-black trees. Just inserting into a WAVL tree will +build the same tree as an AVL tree - one that is more strictly balanced than a red-black tree so WAVL trees can be expected to +perform better in situations where red-black trees become more unbalanced. Delete in WAVL is slightly simpler than delete for AVL +trees in that WAVL deletes perform only 1 or 2 rotations and stop instead of potentially all the way to the root. diff --git a/main.c b/main.c @@ -31,7 +31,13 @@ int main(int ARGC, char** ARGV) { var n = tree.get(&tree, 10); logVarG(n); - tree.inOrderTraversal(tree.root); + // tree.inOrderTraversal(tree.root); + tree.iterStart(&tree, tree.getFirstEntry(&tree)); + wavlTreenodet *node; + while(node = tree.nextEntry(&tree)) { + logVarG(node->key); + logVarG(node->value); + } logVarG(tree.remove(&tree, 10)); diff --git a/wavlTree.c b/wavlTree.c @@ -16,21 +16,6 @@ free(ptr);\ }while(0) -// namespace -/* #define nodeHeight TOKENPASTE(WAVL_NAMESPACE, nodeHeight) */ -/* #define nodeNew TOKENPASTE(WAVL_NAMESPACE, nodeNew) */ -/* #define getEntry TOKENPASTE(WAVL_NAMESPACE, getEntry) */ -/* #define balanceAfterInsert TOKENPASTE(WAVL_NAMESPACE, balanceAfterInsert) */ -/* #define needToRotateLeft TOKENPASTE(WAVL_NAMESPACE, needToRotateLeft) */ -/* #define needToRotateRight TOKENPASTE(WAVL_NAMESPACE, needToRotateRight) */ -/* #define rotateLeft TOKENPASTE(WAVL_NAMESPACE, rotateLeft) */ -/* #define rotateRight TOKENPASTE(WAVL_NAMESPACE, rotateRight) */ -/* #define removeKV TOKENPASTE(WAVL_NAMESPACE, removeKV) */ -/* #define clear TOKENPASTE(WAVL_NAMESPACE, clear) */ -/* #define height TOKENPASTE(WAVL_NAMESPACE, height) */ -/* #define inOrderTraversal TOKENPASTE(WAVL_NAMESPACE, inOrderTraversal) */ -/* #define put TOKENPASTE(WAVL_NAMESPACE, put) */ -/* #define get TOKENPASTE(WAVL_NAMESPACE, get) */ static int height(t *tree); static int nodeHeight(nodet *node); @@ -46,8 +31,8 @@ static valuet removeKV(t *tree, keyt k); static void deleteEntry(t *tree, nodet *P); static nodet *predecessor(nodet *X); -static void fixAfterDeleteWAVL(t *tree, nodet *parent, nodet *sibling, int8_t nodeRank); -static void fixAfterDeleteAVL(t *tree, nodet *parent, nodet *sibling, int8_t nodeRank); +static void balanceAfterDeleteWAVL(t *tree, nodet *parent, nodet *sibling, int8_t nodeRank); +static void balanceAfterDeleteAVL(t *tree, nodet *parent, nodet *sibling, int8_t nodeRank); static nodet *nodeNew(keyt k, valuet v, nodet *parent) { nodet *r = malloc(sizeof(nodet)); @@ -164,20 +149,22 @@ static valuet put(t *tree, keyt k, valuet v) { static void inOrderTraversal(nodet *X) { if (!X) return; - printf("value %d, rank %d", x.value, x.rank); - if (x.left) { - printf(" left key %d", x.left->key); - } - else - printf(" no left"); - if (x.right) { - printf(" right key %d", x.right->key); - } - else - printf(" no right"); - printf("\n"); + + /* printf("value %d, rank %d", x.value, x.rank); */ + /* if (x.left) { */ + /* printf(" left key %d", x.left->key); */ + /* } */ + /* else */ + /* printf(" no left"); */ + /* if (x.right) { */ + /* printf(" right key %d", x.right->key); */ + /* } */ + /* else */ + /* printf(" no right"); */ + /* printf("\n"); */ + inOrderTraversal(x.left); - //printf("value %d, rank %d\n", x.value, x.rank); + printf("value %d, rank %d\n", x.value, x.rank); inOrderTraversal(x.right); } @@ -338,9 +325,9 @@ static void deleteEntry(t *tree, nodet *P) { p.left = p.right = p.parent = NULL; freeP(P); if (w.deleteWAVL) - fixAfterDeleteWAVL(tree, replacement->parent, sibling, replacement->rank); + balanceAfterDeleteWAVL(tree, replacement->parent, sibling, replacement->rank); else - fixAfterDeleteAVL(tree, replacement->parent, sibling, replacement->rank); + balanceAfterDeleteAVL(tree, replacement->parent, sibling, replacement->rank); } else if (!p.parent) { // return if we are the only node. @@ -365,9 +352,9 @@ static void deleteEntry(t *tree, nodet *P) { int8_t rk = --p.rank; freeP(P); if (w.deleteWAVL) - fixAfterDeleteWAVL(tree, fixPoint, sibling, rk); + balanceAfterDeleteWAVL(tree, fixPoint, sibling, rk); else - fixAfterDeleteAVL(tree, fixPoint, sibling, rk); + balanceAfterDeleteAVL(tree, fixPoint, sibling, rk); } } @@ -388,7 +375,7 @@ static bool nodeIsTwoTwo(nodet *node) { return (n.left->rank == n.right->rank && (n.left->rank + 2 == n.rank)); } -static void fixAfterDeleteWAVL(t *tree, nodet *parent, nodet *sibling, int8_t nodeRank) { +static void balanceAfterDeleteWAVL(t *tree, nodet *parent, nodet *sibling, int8_t nodeRank) { nodet *node; int deltaRank = parent->rank - nodeRank; while (deltaRank == 3 || parent->rank == 1 && nodeIsTwoTwo(parent)) { @@ -455,7 +442,7 @@ static void fixAfterDeleteWAVL(t *tree, nodet *parent, nodet *sibling, int8_t no } } -static void fixAfterDeleteAVL(t *tree, nodet *parent, nodet *sibling, int8_t nodeRank) { +static void balanceAfterDeleteAVL(t *tree, nodet *parent, nodet *sibling, int8_t nodeRank) { nodet *node; int balance; if (!sibling) @@ -533,8 +520,45 @@ static void clear(t *tree) { w.deleteWAVL = false; } -// TODO getFirstEntry... -// TODO add leftMost, rightMost +static nodet *getFirstEntry(t *tree) { + nodet *P = w.root; + if (P) { + while (p.left) + P = p.left; + } + return P; +} + +static nodet *getLastEntry(t *tree) { + nodet *P = w.root; + if (P) { + while (p.right) + P = p.right; + } + return P; +} + +// TODO add leftMost, rightMost pointer in tree + +static nodet *successor(nodet *X) { + if (!X) + return NULL; + else if (x.right != NULL) { + nodet *P = x.right; + while (p.left) + P = p.left; + return P; + } + else { + nodet *P = x.parent; + nodet *ch = X; + while (P && ch == p.right) { + ch = P; + P = p.parent; + } + return P; + } +} static nodet *predecessor(nodet *X) { if (!X) @@ -546,25 +570,59 @@ static nodet *predecessor(nodet *X) { return P; } else { - nodet *P = x.parent; + nodet *P = x.parent; nodet *ch = X; while (P && ch == p.left) { ch = P; - P = p.parent; + P = p.parent; } return P; } } -// TODO iterator +static void iterStart(t *tree, nodet *first) { + w.expectedModCount = w.modCount; + w.lastReturned = NULL; + w.next = first; +} + +static bool hasNext(t *tree) { + return w.next != NULL; +} + +static nodet *nextEntry(t *tree) { + nodet *e = w.next; + if (!e) return NULL; + if (w.modCount != w.expectedModCount) return NULL; + w.next = successor(e); + w.lastReturned = e; + return e; +} + +static nodet *prevEntry(t *tree) { + nodet *e = w.next; + if (!e) return NULL; + if (w.modCount != w.expectedModCount) return NULL; + w.next = predecessor(e); + w.lastReturned = e; + return e; +} + +static bool removeCurrent(t *tree) { + if (!w.lastReturned) return false; + if (w.modCount != w.expectedModCount) return false; + /* // deleted entries are replaced by their successors */ + /* if (w.lastReturned.left && w.lastReturned.right) */ + /* w.next = w.lastReturned; */ + deleteEntry(tree, w.lastReturned); + w.expectedModCount = w.modCount; + w.lastReturned = NULL; + return true; +} /** * initialize tree data */ -/* #undef put */ -/* #undef get */ -/* #undef inOrderTraversal */ -/* #undef clear */ bool init(t *tree) { if (!tree) return false; @@ -574,19 +632,19 @@ bool init(t *tree) { w.deleteWAVL = false; w.root = NULL; - /* w.get = TOKENPASTE(WAVL_NAMESPACE, get); */ - /* w.put = TOKENPASTE(WAVL_NAMESPACE, put); */ - /* w.treeHeight = height; */ - /* w.remove = removeKV; */ - /* w.inOrderTraversal = TOKENPASTE(WAVL_NAMESPACE, inOrderTraversal); */ - /* w.clear = TOKENPASTE(WAVL_NAMESPACE, clear); */ - w.get = get; w.put = put; w.treeHeight = height; w.remove = removeKV; w.inOrderTraversal = inOrderTraversal; w.clear = clear; + w.getFirstEntry = getFirstEntry; + w.getLastEntry = getLastEntry; + w.iterStart = iterStart; + w.hasNext = hasNext; + w.nextEntry = nextEntry; + w.prevEntry = prevEntry; + w.removeCurrent = removeCurrent; return true; } diff --git a/wavlTree.h b/wavlTree.h @@ -34,8 +34,6 @@ #define St TOKENPASTE(WAVL_NAMESPACE, St) #define init TOKENPASTE(WAVL_NAMESPACE, init) -// TODO namespace cleanup - typedef int keyt; typedef int valuet; //typedef char* valuet; @@ -60,6 +58,13 @@ typedef valuet (*putFt) (t *tree, keyt k, valuet v); typedef valuet (*removeKVFt) (t *tree, keyt k); typedef void (*inOrderTraversalFt)(nodet *X); typedef void (*clearFt) (t *tree); +typedef nodet* (*getFirstEntryFt) (t *tree); +typedef nodet* (*getLastEntryFt) (t *tree); +typedef void (*iterStartFt) (t *tree, nodet *first); +typedef bool (*hasNextFt) (t *tree); +typedef nodet* (*nextEntryFt) (t *tree); +typedef nodet* (*prevEntryFt) (t *tree); +typedef bool (*removeCurrentFt) (t *tree); struct St { size_t count; // number of entries in the tree @@ -67,13 +72,26 @@ struct St { size_t rotations; bool deleteWAVL; nodet *root; + + // private iterator + size_t expectedModCount; + nodet *next; + nodet *lastReturned; + // end private iterator + getFt get; putFt put; heightFt treeHeight; removeKVFt remove; inOrderTraversalFt inOrderTraversal; clearFt clear; - + getFirstEntryFt getFirstEntry; + getLastEntryFt getLastEntry; + iterStartFt iterStart; + hasNextFt hasNext; + nextEntryFt nextEntry; + prevEntryFt prevEntry; + removeCurrentFt removeCurrent; }; bool init(t *tree); diff --git a/wavlTreeNamespaceCleanup.h b/wavlTreeNamespaceCleanup.h @@ -4,16 +4,3 @@ #undef t #undef St #undef init -// #undef nodeHeight -// #undef nodeNew -// #undef height -// #undef getEntry -// #undef put -// #undef inOrderTraversal -// #undef fixAfterInsert -// #undef needToRotateLeft -// #undef needToRotateRight -// #undef rotateLeft -// #undef rotateRight -// #undef removeKV -// #undef clear