[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_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_LDADD = libharfbuzz.la $(HBLIBS)
|
||||
check_PROGRAMS += $(COMPILED_TESTS)
|
||||
@ -356,6 +356,10 @@ test_array_SOURCES = test-array.cc
|
||||
test_array_CPPFLAGS = $(HBCFLAGS)
|
||||
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_CPPFLAGS = $(HBCFLAGS)
|
||||
test_repacker_LDADD = libharfbuzz.la libharfbuzz-subset.la $(HBLIBS)
|
||||
|
@ -167,6 +167,7 @@ HB_BASE_sources = \
|
||||
hb-unicode.hh \
|
||||
hb-utf.hh \
|
||||
hb-vector.hh \
|
||||
hb-priority-queue.hh \
|
||||
hb.hh \
|
||||
$(NULL)
|
||||
|
||||
|
149
src/hb-priority-queue.hh
Normal file
149
src/hb-priority-queue.hh
Normal file
@ -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 */
|
89
src/test-priority-queue.cc
Normal file
89
src/test-priority-queue.cc
Normal file
@ -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
Block a user