mirror of
https://github.com/owntone/owntone-server.git
synced 2025-03-29 16:53:43 -04:00
187 lines
6.6 KiB
C
187 lines
6.6 KiB
C
/*****************************************************************************
|
|
|
|
avl.h - Source code for the AVL-tree library.
|
|
|
|
Copyright (C) 1998 Michael H. Buselli <cosine@cosine.org>
|
|
Copyright (C) 2000-2002 Wessel Dankers <wsl@nl.linux.org>
|
|
|
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
Augmented AVL-tree. Original by Michael H. Buselli <cosine@cosine.org>.
|
|
|
|
Modified by Wessel Dankers <wsl@nl.linux.org> to add a bunch of bloat to
|
|
the sourcecode, change the interface and squash a few bugs.
|
|
Mail him if you find new bugs.
|
|
|
|
*****************************************************************************/
|
|
|
|
#ifndef _AVL_H
|
|
#define _AVL_H
|
|
|
|
/* We need either depths, counts or both (the latter being the default) */
|
|
#if !defined(AVL_DEPTH) && !defined(AVL_COUNT)
|
|
#define AVL_DEPTH
|
|
#define AVL_COUNT
|
|
#endif
|
|
|
|
/* User supplied function to compare two items like strcmp() does.
|
|
* For example: cmp(a,b) will return:
|
|
* -1 if a < b
|
|
* 0 if a = b
|
|
* 1 if a > b
|
|
*/
|
|
typedef int (*avl_compare_t)(const void *, const void *);
|
|
|
|
/* User supplied function to delete an item when a node is free()d.
|
|
* If NULL, the item is not free()d.
|
|
*/
|
|
typedef void (*avl_freeitem_t)(void *);
|
|
|
|
typedef struct avl_node_t {
|
|
struct avl_node_t *next;
|
|
struct avl_node_t *prev;
|
|
struct avl_node_t *parent;
|
|
struct avl_node_t *left;
|
|
struct avl_node_t *right;
|
|
void *item;
|
|
#ifdef AVL_COUNT
|
|
unsigned int count;
|
|
#endif
|
|
#ifdef AVL_DEPTH
|
|
unsigned char depth;
|
|
#endif
|
|
} avl_node_t;
|
|
|
|
typedef struct avl_tree_t {
|
|
avl_node_t *head;
|
|
avl_node_t *tail;
|
|
avl_node_t *top;
|
|
avl_compare_t cmp;
|
|
avl_freeitem_t freeitem;
|
|
} avl_tree_t;
|
|
|
|
/* Initializes a new tree for elements that will be ordered using
|
|
* the supplied strcmp()-like function.
|
|
* Returns the value of avltree (even if it's NULL).
|
|
* O(1) */
|
|
extern avl_tree_t *avl_init_tree(avl_tree_t *avltree, avl_compare_t, avl_freeitem_t);
|
|
|
|
/* Allocates and initializes a new tree for elements that will be
|
|
* ordered using the supplied strcmp()-like function.
|
|
* Returns NULL if memory could not be allocated.
|
|
* O(1) */
|
|
extern avl_tree_t *avl_alloc_tree(avl_compare_t, avl_freeitem_t);
|
|
|
|
/* Frees the entire tree efficiently. Nodes will be free()d.
|
|
* If the tree's freeitem is not NULL it will be invoked on every item.
|
|
* O(n) */
|
|
extern void avl_free_tree(avl_tree_t *);
|
|
|
|
/* Reinitializes the tree structure for reuse. Nothing is free()d.
|
|
* Compare and freeitem functions are left alone.
|
|
* O(1) */
|
|
extern void avl_clear_tree(avl_tree_t *);
|
|
|
|
/* Free()s all nodes in the tree but leaves the tree itself.
|
|
* If the tree's freeitem is not NULL it will be invoked on every item.
|
|
* O(n) */
|
|
extern void avl_free_nodes(avl_tree_t *);
|
|
|
|
/* Initializes memory for use as a node. Returns NULL if avlnode is NULL.
|
|
* O(1) */
|
|
extern avl_node_t *avl_init_node(avl_node_t *avlnode, void *item);
|
|
|
|
/* Insert an item into the tree and return the new node.
|
|
* Returns NULL and sets errno if memory for the new node could not be
|
|
* allocated or if the node is already in the tree (EEXIST).
|
|
* O(lg n) */
|
|
extern avl_node_t *avl_insert(avl_tree_t *, void *item);
|
|
|
|
/* Insert a node into the tree and return it.
|
|
* Returns NULL if the node is already in the tree.
|
|
* O(lg n) */
|
|
extern avl_node_t *avl_insert_node(avl_tree_t *, avl_node_t *);
|
|
|
|
/* Insert a node in an empty tree. If avlnode is NULL, the tree will be
|
|
* cleared and ready for re-use.
|
|
* If the tree is not empty, the old nodes are left dangling.
|
|
* O(1) */
|
|
extern avl_node_t *avl_insert_top(avl_tree_t *, avl_node_t *avlnode);
|
|
|
|
/* Insert a node before another node. Returns the new node.
|
|
* If old is NULL, the item is appended to the tree.
|
|
* O(lg n) */
|
|
extern avl_node_t *avl_insert_before(avl_tree_t *, avl_node_t *old, avl_node_t *new);
|
|
|
|
/* Insert a node after another node. Returns the new node.
|
|
* If old is NULL, the item is prepended to the tree.
|
|
* O(lg n) */
|
|
extern avl_node_t *avl_insert_after(avl_tree_t *, avl_node_t *old, avl_node_t *new);
|
|
|
|
/* Deletes a node from the tree. Returns immediately if the node is NULL.
|
|
* The item will not be free()d regardless of the tree's freeitem handler.
|
|
* This function comes in handy if you need to update the search key.
|
|
* O(lg n) */
|
|
extern void avl_unlink_node(avl_tree_t *, avl_node_t *);
|
|
|
|
/* Deletes a node from the tree. Returns immediately if the node is NULL.
|
|
* If the tree's freeitem is not NULL, it is invoked on the item.
|
|
* If it is, returns the item.
|
|
* O(lg n) */
|
|
extern void *avl_delete_node(avl_tree_t *, avl_node_t *);
|
|
|
|
/* Searches for an item in the tree and deletes it if found.
|
|
* If the tree's freeitem is not NULL, it is invoked on the item.
|
|
* If it is, returns the item.
|
|
* O(lg n) */
|
|
extern void *avl_delete(avl_tree_t *, const void *item);
|
|
|
|
/* If exactly one node is moved in memory, this will fix the pointers
|
|
* in the tree that refer to it. It must be an exact shallow copy.
|
|
* Returns the pointer to the old position.
|
|
* O(1) */
|
|
extern avl_node_t *avl_fixup_node(avl_tree_t *, avl_node_t *new);
|
|
|
|
/* Searches for a node with the key closest (or equal) to the given item.
|
|
* If avlnode is not NULL, *avlnode will be set to the node found or NULL
|
|
* if the tree is empty. Return values:
|
|
* -1 if the returned node is smaller
|
|
* 0 if the returned node is equal or if the tree is empty
|
|
* 1 if the returned node is greater
|
|
* O(lg n) */
|
|
extern int avl_search_closest(const avl_tree_t *, const void *item, avl_node_t **avlnode);
|
|
|
|
/* Searches for the item in the tree and returns a matching node if found
|
|
* or NULL if not.
|
|
* O(lg n) */
|
|
extern avl_node_t *avl_search(const avl_tree_t *, const void *item);
|
|
|
|
#ifdef AVL_COUNT
|
|
/* Returns the number of nodes in the tree.
|
|
* O(1) */
|
|
extern unsigned int avl_count(const avl_tree_t *);
|
|
|
|
/* Searches a node by its rank in the list. Counting starts at 0.
|
|
* Returns NULL if the index exceeds the number of nodes in the tree.
|
|
* O(lg n) */
|
|
extern avl_node_t *avl_at(const avl_tree_t *, unsigned int);
|
|
|
|
/* Returns the rank of a node in the list. Counting starts at 0.
|
|
* O(lg n) */
|
|
extern unsigned int avl_index(const avl_node_t *);
|
|
#endif
|
|
|
|
#endif
|