diff --git a/configure.ac b/configure.ac index 7d6a738..9c0c695 100644 --- a/configure.ac +++ b/configure.ac @@ -65,5 +65,6 @@ AC_CONFIG_FILES([Makefile src/queue/Makefile src/tree/Makefile src/dynarray/Makefile + src/heap/Makefile include/Makefile]) AC_OUTPUT diff --git a/include/Makefile.am b/include/Makefile.am index 77bec2d..fca79c9 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -5,4 +5,5 @@ nobase_include_HEADERS = trdata.h \ tr/queue.h \ tr/tree.h \ tr/dynarray.h \ + tr/heap.h \ tr/interface/hashable.h diff --git a/include/tr/dynarray.h b/include/tr/dynarray.h index a5db29b..f2b751d 100644 --- a/include/tr/dynarray.h +++ b/include/tr/dynarray.h @@ -36,7 +36,7 @@ TR_CLASSVARS_DECL(TR_Dynarray) {}; size_t TR_darrPut(TR_Dynarray, const void *); void TR_darrPutAt(TR_Dynarray, const void *, size_t); -size_t TR_darrFindLastIndex(TR_Dynarray); +size_t TR_darrFindFirstFree(TR_Dynarray); #define TR_darrGet(this, idx) ((this)->data[(idx)]) diff --git a/include/tr/heap.h b/include/tr/heap.h new file mode 100644 index 0000000..c456b5f --- /dev/null +++ b/include/tr/heap.h @@ -0,0 +1,45 @@ +/** + * \file + * + * \author Georg Hopp + * + * \copyright + * Copyright © 2014 Georg Hopp + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __TR_HEAP_H__ +#define __TR_HEAP_H__ + +#include + +#include "trbase.h" +#include "tr/dynarray.h" + +typedef int (*TR_HeapComp)(const void *, const void *); + +TR_CLASS(TR_Heap) { + TR_EXTENDS(TR_Dynarray); + TR_HeapComp comp; +}; +TR_INSTANCE_INIT(TR_Heap); +TR_CLASSVARS_DECL(TR_Heap) {}; + +void TR_heapPut(TR_Heap, const void *); +const void * TR_heapGet(TR_Heap); + +#endif // __TR_HEAP_H__ + +// vim: set ts=4 sw=4: diff --git a/include/trdata.h b/include/trdata.h index ff10164..98887fb 100644 --- a/include/trdata.h +++ b/include/trdata.h @@ -7,6 +7,7 @@ #include "tr/queue.h" #include "tr/tree.h" #include "tr/dynarray.h" +#include "tr/heap.h" #include "tr/interface/hashable.h" #endif // __TR_DATA_H__ diff --git a/src/Makefile.am b/src/Makefile.am index 5440ac8..c333558 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -8,7 +8,8 @@ TRDATALIBS = cbuf/libcbuf.la \ hash/libhash.la \ queue/libqueue.la \ tree/libtree.la \ - dynarray/libdynarray.la + dynarray/libdynarray.la \ + heap/libheap.la lib_LTLIBRARIES = libtrdata.la @@ -17,4 +18,4 @@ libtrdata_la_CFLAGS = $(AM_CFLAGS) libtrdata_la_LIBADD = $(TRDATALIBS) libtrdata_la_LDFLAGS = -version-info 0:0:0 $(AM_LDFLAGS) -SUBDIRS = cbuf hash queue tree dynarray +SUBDIRS = cbuf hash queue tree dynarray heap diff --git a/src/dynarray/Makefile.am b/src/dynarray/Makefile.am index ad60394..43e81d8 100644 --- a/src/dynarray/Makefile.am +++ b/src/dynarray/Makefile.am @@ -4,7 +4,7 @@ AUTOMAKE_OPTIONS = subdir-objects AM_CFLAGS += -I../../include/ -std=c99 -DREENTRANT -lpthread AM_LDFLAGS += -lpthread -DYNARRAY = dynarray.c put.c find_last_index.c +DYNARRAY = dynarray.c put.c find_first_free.c noinst_LTLIBRARIES = libdynarray.la diff --git a/src/dynarray/dynarray.c b/src/dynarray/dynarray.c index dca554a..e7c7642 100644 --- a/src/dynarray/dynarray.c +++ b/src/dynarray/dynarray.c @@ -41,7 +41,7 @@ _darrResize(TR_Dynarray this, size_t index) static int -darrCtor(void * _this) +darrCtor(void * _this, va_list * params) { return 0; } diff --git a/src/dynarray/find_last_index.c b/src/dynarray/find_first_free.c similarity index 96% rename from src/dynarray/find_last_index.c rename to src/dynarray/find_first_free.c index 1815586..716a2d6 100644 --- a/src/dynarray/find_last_index.c +++ b/src/dynarray/find_first_free.c @@ -26,7 +26,7 @@ #include "tr/dynarray.h" size_t -TR_darrFindLastIndex(TR_Dynarray this) +TR_darrFindFirstFree(TR_Dynarray this) { size_t i = this->size; diff --git a/src/dynarray/put.c b/src/dynarray/put.c index 27e4af4..67cbf88 100644 --- a/src/dynarray/put.c +++ b/src/dynarray/put.c @@ -42,7 +42,7 @@ _darrResize(TR_Dynarray this, size_t index) size_t TR_darrPut(TR_Dynarray this, const void * data) { - size_t i = TR_darrFindLastIndex(this); + size_t i = TR_darrFindFirstFree(this); TR_darrPutAt(this, data, i); diff --git a/src/heap/Makefile.am b/src/heap/Makefile.am new file mode 100644 index 0000000..c3b57c5 --- /dev/null +++ b/src/heap/Makefile.am @@ -0,0 +1,13 @@ +ACLOCAL_AMFLAGS = -I m4 +AUTOMAKE_OPTIONS = subdir-objects + +AM_CFLAGS += -I../../include/ -std=c99 -DREENTRANT -lpthread +AM_LDFLAGS += -lpthread + +HEAP = heap.c put.c get.c + +noinst_LTLIBRARIES = libheap.la + +libheap_la_SOURCES = $(HEAP) +libheap_la_CFLAGS = $(AM_CFLAGS) +libheap_la_LIBADD = $(AM_LDFLAGS) diff --git a/src/heap/get.c b/src/heap/get.c new file mode 100644 index 0000000..65c5b7a --- /dev/null +++ b/src/heap/get.c @@ -0,0 +1,85 @@ +/** + * \file + * + * \author Georg Hopp + * + * \copyright + * Copyright © 2014 Georg Hopp + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "trbase.h" +#include "tr/heap.h" +#include "tr/dynarray.h" + +const void * +TR_heapGet(TR_Heap this) +{ + const void * value = TR_darrGet((TR_Dynarray)this, 0); + size_t left = 1; + size_t right = 2; + size_t idx; + + if (! value) { + return NULL; + } + + idx = TR_darrFindFirstFree((TR_Dynarray)this) - 1; + TR_darrGet((TR_Dynarray)this, 0) = NULL; + + if (0 == idx) { + return value; + } + + SWAP( + void *, + TR_darrGet((TR_Dynarray)this, 0), + TR_darrGet((TR_Dynarray)this, idx)); + idx = 0; + + while (left < ((TR_Dynarray)this)->size && + TR_darrGet((TR_Dynarray)this, left)) { + size_t change = left; + + if (right < ((TR_Dynarray)this)->size && + TR_darrGet((TR_Dynarray)this, right) && + 0 > this->comp ( + TR_darrGet((TR_Dynarray)this, left), + TR_darrGet((TR_Dynarray)this, right))) { + change = right; + } + + if (0 > this->comp( + TR_darrGet((TR_Dynarray)this, idx), + TR_darrGet((TR_Dynarray)this, change))) { + SWAP( + void *, + TR_darrGet((TR_Dynarray)this, idx), + TR_darrGet((TR_Dynarray)this, change)); + idx = change; + left = (idx << 1) + 1; + right = left + 1; + } else { + break; + } + } + + return value; +} + +// vim: set ts=4 sw=4: diff --git a/src/heap/heap.c b/src/heap/heap.c new file mode 100644 index 0000000..e5cbb71 --- /dev/null +++ b/src/heap/heap.c @@ -0,0 +1,49 @@ +/** + * \file + * + * \author Georg Hopp + * + * \copyright + * Copyright © 2014 Georg Hopp + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#include "trbase.h" +#include "tr/heap.h" + +static +int +heapCtor(void * _this, va_list * params) +{ + TR_Heap this = _this; + + this->comp = va_arg(*params, TR_HeapComp); + + return 0; +} + +static +void +heapDtor(void * _this) +{ + TR_PARENTCALL(TR_Heap, _this, TR_Class, dtor); +} + +TR_INIT_IFACE(TR_Class, heapCtor, heapDtor, NULL); +TR_CREATE_CLASS(TR_Heap, TR_Dynarray, NULL, TR_IF(TR_Class)); + +// vim: set ts=4 sw=4: diff --git a/src/heap/put.c b/src/heap/put.c new file mode 100644 index 0000000..3555cfd --- /dev/null +++ b/src/heap/put.c @@ -0,0 +1,52 @@ +/** + * \file + * + * \author Georg Hopp + * + * \copyright + * Copyright © 2014 Georg Hopp + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "trbase.h" +#include "tr/heap.h" +#include "tr/dynarray.h" + +void +TR_heapPut(TR_Heap this, const void * data) +{ + size_t idx = TR_darrPut((TR_Dynarray)this, data); + + while (idx) { + size_t parent = (idx - 1) >> 1; + + if (0 > this->comp( + TR_darrGet((TR_Dynarray)this, parent), + TR_darrGet((TR_Dynarray)this, idx))) { + SWAP( + void *, + TR_darrGet((TR_Dynarray)this, parent), + TR_darrGet((TR_Dynarray)this, idx)); + idx = parent; + } else { + break; + } + } +} + +// vim: set ts=4 sw=4: