Giter VIP home page Giter VIP logo

libtree's Introduction

Libtree Description

Design

This is yet another implementation of some famous (balanced) binary search trees. As of writing this, BST, AVL, Red-Black and Splay trees are implemented.

Here’s a list of the major points:

  • Nodes of the tree aims to be embedded inside your own structure. This removes the need to do some malloc/free during insertion/removal operations and saves some space since allocation infrastructure (such as object descriptors or object alignment) is not required.

    The idea is borrowed from the Linux kernel.

  • On most architectures (at least the ones I’m using), pointers have some unused bits which can be used to store node’s meta-data. This allows to reduce the size of the node structure, and make them as small as possible on a vast majority of architectures.

    If the hardware you’re working on doesn’t allow such optimisation, the library still provides an implementation which is fully portable (C99), at the cost of an increasing node structure size.

    For now, the optimised (but non portable) version is used if ‘uintptr_t’ is defined on your platform.

  • Traversals in both direction are efficient for all type of trees. When needed, some implementations use threaded trees making the traversal algorithm much simpler.
  • The trees don’t store duplicate keys. It’s fairly easy to implement duplicate from the user point of view (by having a list at the node for instance) and this allows to have a simple but efficient API (see below).

API

You should never actually need to play with the internal members of either tree or node structures.

Nodes are embedded inside your own structure, for example:

struct my_struct {
        int key;
        struct avltree_node node;
};

A tree needs to be initialized before being used. For example, in order to initialize an AVL tree:

struct avltree tree;
/* ... */
avltree_init(&tree, cmp_fn, 0);

The user must provide a comparison function. This function will be called by the library with two arguments that point to the node structures embedded in the user structures being compared.

For instance, the user must provide a function whose prototype is:

int my_cmp(const struct avltree_node *, const struct avltree_node *);

To be usefull, the user must be able to retrieve the pointers on his two structures which embed the 2 nodes pointed by the 2 parameters. For that, the library provides a couple of helpers.

bstree_container_of(node, type, member)
rbtree_container_of(node, type, member)
avltree_container_of(node, type, member)
splaytree_container_of(node, type, member)

Below gives a definition of the comparison function:

int my_cmp(const struct avltree_node *a, const struct avltree_node *b)
{
        struct my_struct *p = avltree_container_of(a, my_struct, node);
        struct my_struct *q = avltree_container_of(b, my_struct, node);

:

        return p->key - q->key;
}

A set of functions is provided to manipulate trees. All of them take only pointers to tree and node structures. They have no idea about the user’s structures which contain them.

Lookup

If you need to search for the node having a specific key then you need to fill up a dummy structure with the key initialized to the value so your compare function will successfully compare the passed dummy structure with the ones inside the tree.

The lookup operation returns the node with the same key if inserted previously otherwise NULL.

Insertion

Trees don’t store duplicate keys, since rotations don’t preserve the binary search tree property in this case. If the user needs to do so, then he can keep a separate list of all records having the same key.

This is the reason why the insertion functions do insert a key only if the key hasn’t been already inserted. Otherwise it’s equivalent to a lookup operation and the insertion operation just returns the node with the same key already inserted, and no insertion happened. At this point the user can use a list and append the new node to the list given by the returned node.

Removal

For speed reasons, the remove operation assumes that the node was already inserted into the tree.

Indeed tree implementations using parent pointers don’t need to do any lookups to retrieve the node’s parent needed during the remove operation.

Therefore you must use the remove operation with an already inserted node.

Replace

Since trees don’t store duplicate keys, the library provides an operation to replace a node with another one whose key is equal to the replaced node.

This operation is faster than remove/insert operations for balanced trees since it doesn’t need to rebalance the tree.

Traversal

The API allows you to walk through the tree in sorted order.

For that, you can retrieve the next or the previous of any inserted nodes. You can also get the first (leftmost) and the last (rightmost) node of a tree.

Installation

The current Makefile has been tested only on Linux system.

To compile and install the library, just do:

$ make
$ make install

By default the library will be installed in ‘/usr/local/lib’ directory.

As usual you change this path by passing ‘prefix=’ option.

You can also change the installation root directory by passing ‘DESTDIR=’ option.

libtree's People

Contributors

fbuihuu avatar rmanfredi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

libtree's Issues

The implementation of bstree_replace() may incorrect

It should maintain "thread" pointers by updating them to point to the new node as well.
For instance:

set_next(new, get_prev(old)); // NOTE: it just telling the point, not necessary to be correct

In my test program, an infinite lookup loop comes up easily with random datasets and with using bstree_replace(). But everything was fine without bstree_replace().

no working sample code

Hello,

I tried to run basic robustness test on libtree inserting 1k random keys comparing the order in a list of these numbers and the tree.

Unfortunately, the compare fails.

Maybe there is some off-by-one error somewhere and I am comparing uninitialized value or there is some issue with my understanding of the walk function in libtree.

Anyway, here is the code I tried git://gist.github.com/2045182.git

Note that I get assert on 5th element for which I have visually inspected my list implementation to produce seemingly correct order with this number sequence.

license problematic

COPYING says LGPL 2.1, source files say Library general public license 2 (a license that does not exist, see http://www.gnu.org/licenses/old-licenses/old-licenses.html#LGPL). This is a problem

Do you mean to license under LGPL 2.1+, if so, change the headers of your source files to the fallowing:

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

inserting 1536452766 2219981191 2013842191 206515713 3973769363 breaks bstree and splay tree

<- 1536452766
1536452766 <- 2219981191
1536452766 2219981191 <- 2013842191
1536452766 2013842191 2219981191 <- 206515713
206515713 1536452766 2013842191 2219981191 <- 3973769363
206515713 1536452766 2013842191 2219981191 3973769363
bs tree: item 0 (3973769363) != 206515713
inserted items:
1536452766 2219981191 2013842191 206515713 3973769363
Aborted

<- 1536452766
1536452766 <- 2219981191
1536452766 2219981191 <- 2013842191
1536452766 2013842191 2219981191 <- 206515713
206515713 1536452766 2013842191 2219981191 <- 3973769363
206515713 1536452766 2013842191 2219981191 3973769363
splay tree: item 0 (3973769363) != 206515713
inserted items:
1536452766 2219981191 2013842191 206515713 3973769363

The sequence for avl and rb tree is longer but again the last inserted item appears first:

1536452766 2219981191 2013842191 206515713 3973769363 2195571548 1470591614 99517740 3346335896 1968000334 2824163306 825862710 593949289 3087228942 9464287 3502443898 1825977738 4200665288

<- 1536452766
1536452766 <- 2219981191
1536452766 2219981191 <- 2013842191
1536452766 2013842191 2219981191 <- 206515713
206515713 1536452766 2013842191 2219981191 <- 3973769363
206515713 1536452766 2013842191 2219981191 3973769363 <- 2195571548
206515713 1536452766 2013842191 2195571548 2219981191 3973769363 <- 1470591614
206515713 1470591614 1536452766 2013842191 2195571548 2219981191 3973769363 <- 99517740
99517740 206515713 1470591614 1536452766 2013842191 2195571548 2219981191 3973769363 <- 3346335896
99517740 206515713 1470591614 1536452766 2013842191 2195571548 2219981191 3346335896 3973769363 <- 1968000334
99517740 206515713 1470591614 1536452766 1968000334 2013842191 2195571548 2219981191 3346335896 3973769363 <- 2824163306
99517740 206515713 1470591614 1536452766 1968000334 2013842191 2195571548 2219981191 2824163306 3346335896 3973769363 <- 825862710
99517740 206515713 825862710 1470591614 1536452766 1968000334 2013842191 2195571548 2219981191 2824163306 3346335896 3973769363 <- 593949289
99517740 206515713 593949289 825862710 1470591614 1536452766 1968000334 2013842191 2195571548 2219981191 2824163306 3346335896 3973769363 <- 3087228942
99517740 206515713 593949289 825862710 1470591614 1536452766 1968000334 2013842191 2195571548 2219981191 2824163306 3087228942 3346335896 3973769363 <- 9464287
9464287 99517740 206515713 593949289 825862710 1470591614 1536452766 1968000334 2013842191 2195571548 2219981191 2824163306 3087228942 3346335896 3973769363 <- 3502443898
9464287 99517740 206515713 593949289 825862710 1470591614 1536452766 1968000334 2013842191 2195571548 2219981191 2824163306 3087228942 3346335896 3502443898 3973769363 <- 1825977738
9464287 99517740 206515713 593949289 825862710 1470591614 1536452766 1825977738 1968000334 2013842191 2195571548 2219981191 2824163306 3087228942 3346335896 3502443898 3973769363 <- 4200665288
9464287 99517740 206515713 593949289 825862710 1470591614 1536452766 1825977738 1968000334 2013842191 2195571548 2219981191 2824163306 3087228942 3346335896 3502443898 3973769363 4200665288
avl tree: item 0 (4200665288) != 9464287
inserted items:
1536452766 2219981191 2013842191 206515713 3973769363 2195571548 1470591614 99517740 3346335896 1968000334 2824163306 825862710 593949289 3087228942 9464287 3502443898 1825977738 4200665288
Aborted

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.