Add ability for List to be ordered/unordered

This fixes a "bug" with List where remove_nth() can be an O(n) operation when it doesn't
need to be. remove_nth for lists that don't necessarily need to keep an order can be an
O(1) operation instead.
This commit is contained in:
Tim Wojtulewicz 2020-04-30 13:26:00 -07:00
parent 0558a7bfed
commit 28e5100842
2 changed files with 38 additions and 12 deletions

View file

@ -114,3 +114,17 @@ TEST_CASE("plists")
delete v; delete v;
list.clear(); list.clear();
} }
TEST_CASE("unordered list operation")
{
List<int, LIST_UNORDERED> list({1, 2, 3, 4});
CHECK(list.size() == 4);
// An unordered list doesn't maintain the ordering of the elements when
// one is removed. It just swaps the last element into the hole.
list.remove(2);
CHECK(list.size() == 3);
CHECK(list[0] == 1);
CHECK(list[1] == 4);
CHECK(list[2] == 3);
}

View file

@ -29,7 +29,9 @@
// TODO: this can be removed in v3.1 when List::sort() is removed // TODO: this can be removed in v3.1 when List::sort() is removed
typedef int (*list_cmp_func)(const void* v1, const void* v2); typedef int (*list_cmp_func)(const void* v1, const void* v2);
template<typename T> enum list_order { LIST_ORDERED, LIST_UNORDERED };
template<typename T, list_order Order = LIST_ORDERED>
class List { class List {
public: public:
@ -195,13 +197,11 @@ public:
bool remove(const T& a) // delete entry from list bool remove(const T& a) // delete entry from list
{ {
for ( int i = 0; i < num_entries; ++i ) int pos = member_pos(a);
if ( pos != -1 )
{ {
if ( a == entries[i] ) remove_nth(pos);
{ return true;
remove_nth(i);
return true;
}
} }
return false; return false;
@ -212,10 +212,22 @@ public:
assert(n >=0 && n < num_entries); assert(n >=0 && n < num_entries);
T old_ent = entries[n]; T old_ent = entries[n];
--num_entries;
for ( ; n < num_entries; ++n ) // For data where we don't care about ordering, we don't care about keeping
entries[n] = entries[n+1]; // the list in the same order when removing an element. Just swap the last
// element with the element being removed.
if ( Order == LIST_ORDERED )
{
--num_entries;
for ( ; n < num_entries; ++n )
entries[n] = entries[n+1];
}
else
{
entries[n] = entries[num_entries - 1];
--num_entries;
}
return old_ent; return old_ent;
} }
@ -332,8 +344,8 @@ protected:
// Specialization of the List class to store pointers of a type. // Specialization of the List class to store pointers of a type.
template<typename T> template<typename T, list_order Order = LIST_ORDERED>
using PList = List<T*>; using PList = List<T*, Order>;
// Popular type of list: list of strings. // Popular type of list: list of strings.
typedef PList<char> name_list; typedef PList<char> name_list;