[subset] Add a basic priority queue datastructure (binary heap).
This commit is contained in:
parent
dd8e5d0e1b
commit
5c4e0ffd97
|
@ -342,7 +342,7 @@ test_gsub_would_substitute_SOURCES = test-gsub-would-substitute.cc
|
||||||
test_gsub_would_substitute_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS)
|
test_gsub_would_substitute_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS)
|
||||||
test_gsub_would_substitute_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS)
|
test_gsub_would_substitute_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS)
|
||||||
|
|
||||||
COMPILED_TESTS = test-algs test-array test-iter test-meta test-number test-ot-tag test-unicode-ranges test-bimap test-repacker
|
COMPILED_TESTS = test-algs test-array test-iter test-meta test-number test-ot-tag test-priority-queue test-unicode-ranges test-bimap test-repacker
|
||||||
COMPILED_TESTS_CPPFLAGS = $(HBCFLAGS) -DMAIN -UNDEBUG
|
COMPILED_TESTS_CPPFLAGS = $(HBCFLAGS) -DMAIN -UNDEBUG
|
||||||
COMPILED_TESTS_LDADD = libharfbuzz.la $(HBLIBS)
|
COMPILED_TESTS_LDADD = libharfbuzz.la $(HBLIBS)
|
||||||
check_PROGRAMS += $(COMPILED_TESTS)
|
check_PROGRAMS += $(COMPILED_TESTS)
|
||||||
|
@ -356,6 +356,10 @@ test_array_SOURCES = test-array.cc
|
||||||
test_array_CPPFLAGS = $(HBCFLAGS)
|
test_array_CPPFLAGS = $(HBCFLAGS)
|
||||||
test_array_LDADD = libharfbuzz.la $(HBLIBS)
|
test_array_LDADD = libharfbuzz.la $(HBLIBS)
|
||||||
|
|
||||||
|
test_priority_queue_SOURCES = test-priority-queue.cc hb-static.cc
|
||||||
|
test_priority_queue_CPPFLAGS = $(HBCFLAGS)
|
||||||
|
test_priority_queue_LDADD = libharfbuzz.la $(HBLIBS)
|
||||||
|
|
||||||
test_repacker_SOURCES = test-repacker.cc hb-static.cc
|
test_repacker_SOURCES = test-repacker.cc hb-static.cc
|
||||||
test_repacker_CPPFLAGS = $(HBCFLAGS)
|
test_repacker_CPPFLAGS = $(HBCFLAGS)
|
||||||
test_repacker_LDADD = libharfbuzz.la libharfbuzz-subset.la $(HBLIBS)
|
test_repacker_LDADD = libharfbuzz.la libharfbuzz-subset.la $(HBLIBS)
|
||||||
|
|
|
@ -167,6 +167,7 @@ HB_BASE_sources = \
|
||||||
hb-unicode.hh \
|
hb-unicode.hh \
|
||||||
hb-utf.hh \
|
hb-utf.hh \
|
||||||
hb-vector.hh \
|
hb-vector.hh \
|
||||||
|
hb-priority-queue.hh \
|
||||||
hb.hh \
|
hb.hh \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,149 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2020 Google, Inc.
|
||||||
|
*
|
||||||
|
* This is part of HarfBuzz, a text shaping library.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, without written agreement and without
|
||||||
|
* license or royalty fees, to use, copy, modify, and distribute this
|
||||||
|
* software and its documentation for any purpose, provided that the
|
||||||
|
* above copyright notice and the following two paragraphs appear in
|
||||||
|
* all copies of this software.
|
||||||
|
*
|
||||||
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||||
|
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||||
|
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
* DAMAGE.
|
||||||
|
*
|
||||||
|
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||||
|
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||||
|
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
*
|
||||||
|
* Google Author(s): Garret Rieger
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HB_PRIORITY_QUEUE_HH
|
||||||
|
#define HB_PRIORITY_QUEUE_HH
|
||||||
|
|
||||||
|
#include "hb.hh"
|
||||||
|
#include "hb-vector.hh"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* hb_priority_queue_t
|
||||||
|
*
|
||||||
|
* Priority queue implemented as a binary heap. Supports extract minimum
|
||||||
|
* and insert operations.
|
||||||
|
*/
|
||||||
|
struct hb_priority_queue_t
|
||||||
|
{
|
||||||
|
HB_DELETE_COPY_ASSIGN (hb_priority_queue_t);
|
||||||
|
hb_priority_queue_t () { init (); }
|
||||||
|
~hb_priority_queue_t () { fini (); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef hb_pair_t<unsigned, unsigned> item_t;
|
||||||
|
hb_vector_t<item_t> heap;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void init () { heap.init (); }
|
||||||
|
|
||||||
|
void fini () { heap.fini (); }
|
||||||
|
|
||||||
|
void reset () { heap.resize (0); }
|
||||||
|
|
||||||
|
bool in_error () const { return heap.in_error (); }
|
||||||
|
|
||||||
|
void insert (unsigned value, unsigned priority)
|
||||||
|
{
|
||||||
|
heap.push (item_t (value, priority));
|
||||||
|
bubble_up (heap.length - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
item_t extract_minimum ()
|
||||||
|
{
|
||||||
|
item_t result = heap[0];
|
||||||
|
|
||||||
|
heap[0] = heap[heap.length - 1];
|
||||||
|
heap.shrink (heap.length - 1);
|
||||||
|
bubble_down (0);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const item_t& minimum ()
|
||||||
|
{
|
||||||
|
return heap[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_empty () const { return heap.length == 0; }
|
||||||
|
|
||||||
|
/* Sink interface. */
|
||||||
|
hb_priority_queue_t& operator << (item_t item)
|
||||||
|
{ insert (item.first, item.second); return *this; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
unsigned parent (unsigned index)
|
||||||
|
{
|
||||||
|
return (index - 1) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned left_child (unsigned index)
|
||||||
|
{
|
||||||
|
return 2 * index + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned right_child (unsigned index)
|
||||||
|
{
|
||||||
|
return 2 * index + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bubble_down (unsigned index)
|
||||||
|
{
|
||||||
|
unsigned left = left_child (index);
|
||||||
|
unsigned right = right_child (index);
|
||||||
|
|
||||||
|
bool has_left = left < heap.length;
|
||||||
|
if (!has_left)
|
||||||
|
// If there's no left, then there's also no right.
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool has_right = right < heap.length;
|
||||||
|
if (heap[index] <= heap[left]
|
||||||
|
&& (!has_right || heap[index] <= heap[right]))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!has_right || heap[left] < heap[right])
|
||||||
|
{
|
||||||
|
swap (index, left);
|
||||||
|
bubble_down (left);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
swap (index, right);
|
||||||
|
bubble_down (right);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bubble_up (unsigned index)
|
||||||
|
{
|
||||||
|
if (index == 0) return;
|
||||||
|
|
||||||
|
unsigned parent_index = parent (index);
|
||||||
|
if (heap[parent_index].second <= heap[index].second)
|
||||||
|
return;
|
||||||
|
|
||||||
|
swap (index, parent_index);
|
||||||
|
bubble_up (parent_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void swap (unsigned a, unsigned b)
|
||||||
|
{
|
||||||
|
item_t temp = heap[a];
|
||||||
|
heap[a] = heap[b];
|
||||||
|
heap[b] = temp;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* HB_PRIORITY_QUEUE_HH */
|
|
@ -0,0 +1,89 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2020 Google, Inc.
|
||||||
|
*
|
||||||
|
* This is part of HarfBuzz, a text shaping library.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, without written agreement and without
|
||||||
|
* license or royalty fees, to use, copy, modify, and distribute this
|
||||||
|
* software and its documentation for any purpose, provided that the
|
||||||
|
* above copyright notice and the following two paragraphs appear in
|
||||||
|
* all copies of this software.
|
||||||
|
*
|
||||||
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||||
|
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||||
|
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
* DAMAGE.
|
||||||
|
*
|
||||||
|
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||||
|
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||||
|
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
*
|
||||||
|
* Google Author(s): Garret Rieger
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "hb.hh"
|
||||||
|
#include "hb-priority-queue.hh"
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_insert ()
|
||||||
|
{
|
||||||
|
hb_priority_queue_t queue;
|
||||||
|
assert (queue.is_empty ());
|
||||||
|
|
||||||
|
queue.insert (0, 10);
|
||||||
|
assert (!queue.is_empty ());
|
||||||
|
assert (queue.minimum () == hb_pair (0, 10));
|
||||||
|
|
||||||
|
queue.insert (1, 20);
|
||||||
|
assert (queue.minimum () == hb_pair (0, 10));
|
||||||
|
|
||||||
|
queue.insert (2, 5);
|
||||||
|
assert (queue.minimum () == hb_pair (2, 5));
|
||||||
|
|
||||||
|
queue.insert (3, 15);
|
||||||
|
assert (queue.minimum () == hb_pair (2, 5));
|
||||||
|
|
||||||
|
queue.insert (4, 1);
|
||||||
|
assert (queue.minimum () == hb_pair (4, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_extract ()
|
||||||
|
{
|
||||||
|
hb_priority_queue_t queue;
|
||||||
|
queue.insert (0, 0);
|
||||||
|
queue.insert (6, 60);
|
||||||
|
queue.insert (3, 30);
|
||||||
|
queue.insert (4, 40);
|
||||||
|
queue.insert (2, 20);
|
||||||
|
queue.insert (5, 50);
|
||||||
|
queue.insert (7, 70);
|
||||||
|
queue.insert (1, 10);
|
||||||
|
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
assert (!queue.is_empty ());
|
||||||
|
assert (queue.minimum () == hb_pair (i, i * 10));
|
||||||
|
assert (queue.extract_minimum () == hb_pair (i, i * 10));
|
||||||
|
}
|
||||||
|
|
||||||
|
assert (queue.is_empty ());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_extract_empty ()
|
||||||
|
{
|
||||||
|
hb_priority_queue_t queue;
|
||||||
|
assert (queue.extract_minimum () == hb_pair (0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
test_insert ();
|
||||||
|
test_extract ();
|
||||||
|
test_extract_empty ();
|
||||||
|
}
|
Loading…
Reference in New Issue