mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 537339 - Add heap functions to nsTArray, r=roc
This commit is contained in:
parent
e941d691f4
commit
91093439df
@ -877,7 +877,7 @@ class nsTArray : public nsTArray_base {
|
|||||||
|
|
||||||
// This method sorts the elements of the array. It uses the LessThan
|
// This method sorts the elements of the array. It uses the LessThan
|
||||||
// method defined on the given Comparator object to collate elements.
|
// method defined on the given Comparator object to collate elements.
|
||||||
// @param c The Comparator to used to collate elements.
|
// @param comp The Comparator used to collate elements.
|
||||||
template<class Comparator>
|
template<class Comparator>
|
||||||
void Sort(const Comparator& comp) {
|
void Sort(const Comparator& comp) {
|
||||||
NS_QuickSort(Elements(), Length(), sizeof(elem_type),
|
NS_QuickSort(Elements(), Length(), sizeof(elem_type),
|
||||||
@ -891,6 +891,77 @@ class nsTArray : public nsTArray_base {
|
|||||||
Sort(nsDefaultComparator<elem_type, elem_type>());
|
Sort(nsDefaultComparator<elem_type, elem_type>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Binary Heap
|
||||||
|
//
|
||||||
|
|
||||||
|
// Sorts the array into a binary heap.
|
||||||
|
// @param comp The Comparator used to create the heap
|
||||||
|
template<class Comparator>
|
||||||
|
void MakeHeap(const Comparator& comp) {
|
||||||
|
if (!Length()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
elem_type *elem = Elements();
|
||||||
|
index_type index = (Length() - 1) / 2;
|
||||||
|
do {
|
||||||
|
SiftDown(index, comp);
|
||||||
|
} while (index--);
|
||||||
|
}
|
||||||
|
|
||||||
|
// A variation on the MakeHeap method defined above.
|
||||||
|
void MakeHeap() {
|
||||||
|
MakeHeap(nsDefaultComparator<elem_type, elem_type>());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adds an element to the heap
|
||||||
|
// @param item The item to add
|
||||||
|
// @param comp The Comparator used to sift-up the item
|
||||||
|
template<class Item, class Comparator>
|
||||||
|
elem_type *PushHeap(const Item& item, const Comparator& comp) {
|
||||||
|
if (!nsTArray_base::InsertSlotsAt(Length(), 1, sizeof(elem_type))) {
|
||||||
|
return nsnull;
|
||||||
|
}
|
||||||
|
// Sift up the new node
|
||||||
|
elem_type *elem = Elements();
|
||||||
|
index_type index = Length() - 1;
|
||||||
|
index_type parent_index = (index - 1) / 2;
|
||||||
|
while (index && comp.LessThan(elem[parent_index], item)) {
|
||||||
|
elem[index] = elem[parent_index];
|
||||||
|
index = parent_index;
|
||||||
|
parent_index = (index - 1) / 2;
|
||||||
|
}
|
||||||
|
elem[index] = item;
|
||||||
|
return &elem[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
// A variation on the PushHeap method defined above.
|
||||||
|
template<class Item>
|
||||||
|
elem_type *PushHeap(const Item& item) {
|
||||||
|
return PushHeap(item, nsDefaultComparator<elem_type, Item>());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the root of the heap and restore the heap
|
||||||
|
// @param comp The Comparator used to restore the heap
|
||||||
|
template<class Comparator>
|
||||||
|
void PopHeap(const Comparator& comp) {
|
||||||
|
if (!Length()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
index_type last_index = Length() - 1;
|
||||||
|
elem_type *elem = Elements();
|
||||||
|
elem[0] = elem[last_index];
|
||||||
|
TruncateLength(last_index);
|
||||||
|
if (Length()) {
|
||||||
|
SiftDown(0, comp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A variation on the PopHeap method defined above.
|
||||||
|
void PopHeap() {
|
||||||
|
PopHeap(nsDefaultComparator<elem_type, elem_type>());
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// This method invokes elem_type's destructor on a range of elements.
|
// This method invokes elem_type's destructor on a range of elements.
|
||||||
@ -915,6 +986,36 @@ class nsTArray : public nsTArray_base {
|
|||||||
elem_traits::Construct(iter, *values);
|
elem_traits::Construct(iter, *values);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This method sifts an item down to its proper place in a binary heap
|
||||||
|
// @param index The index of the node to start sifting down from
|
||||||
|
// @param comp The Comparator used to sift down
|
||||||
|
template<class Comparator>
|
||||||
|
void SiftDown(index_type index, const Comparator& comp) {
|
||||||
|
elem_type *elem = Elements();
|
||||||
|
elem_type item = elem[index];
|
||||||
|
index_type end = Length() - 1;
|
||||||
|
while ((index * 2) < end) {
|
||||||
|
const index_type left = (index * 2) + 1;
|
||||||
|
const index_type right = (index * 2) + 2;
|
||||||
|
const index_type parent_index = index;
|
||||||
|
if (comp.LessThan(item, elem[left])) {
|
||||||
|
if (left < end &&
|
||||||
|
comp.LessThan(elem[left], elem[right])) {
|
||||||
|
index = right;
|
||||||
|
} else {
|
||||||
|
index = left;
|
||||||
|
}
|
||||||
|
} else if (left < end &&
|
||||||
|
comp.LessThan(item, elem[right])) {
|
||||||
|
index = right;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
elem[parent_index] = elem[index];
|
||||||
|
}
|
||||||
|
elem[index] = item;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class E, PRUint32 N>
|
template<class E, PRUint32 N>
|
||||||
|
@ -523,6 +523,45 @@ static PRBool test_indexof() {
|
|||||||
|
|
||||||
//----
|
//----
|
||||||
|
|
||||||
|
template <class Array>
|
||||||
|
static PRBool is_heap(const Array& ary, PRUint32 len) {
|
||||||
|
PRUint32 index = 1;
|
||||||
|
while (index < len) {
|
||||||
|
if (ary[index] > ary[(index - 1) >> 1])
|
||||||
|
return PR_FALSE;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
return PR_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PRBool test_heap() {
|
||||||
|
const int data[] = {4,6,8,2,4,1,5,7,3};
|
||||||
|
nsTArray<int> ary;
|
||||||
|
ary.AppendElements(data, NS_ARRAY_LENGTH(data));
|
||||||
|
// make a heap and make sure it's a heap
|
||||||
|
ary.MakeHeap();
|
||||||
|
if (!is_heap(ary, NS_ARRAY_LENGTH(data)))
|
||||||
|
return PR_FALSE;
|
||||||
|
// pop the root and make sure it's still a heap
|
||||||
|
int root = ary[0];
|
||||||
|
ary.PopHeap();
|
||||||
|
if (!is_heap(ary, NS_ARRAY_LENGTH(data) - 1))
|
||||||
|
return PR_FALSE;
|
||||||
|
// push the previously poped value back on and make sure it's still a heap
|
||||||
|
ary.PushHeap(root);
|
||||||
|
if (!is_heap(ary, NS_ARRAY_LENGTH(data)))
|
||||||
|
return PR_FALSE;
|
||||||
|
// make sure the heap looks like what we expect
|
||||||
|
const int expected_data[] = {8,7,5,6,4,1,4,2,3};
|
||||||
|
PRUint32 index;
|
||||||
|
for (index = 0; index < NS_ARRAY_LENGTH(data); index++)
|
||||||
|
if (ary[index] != expected_data[index])
|
||||||
|
return PR_FALSE;
|
||||||
|
return PR_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----
|
||||||
|
|
||||||
typedef PRBool (*TestFunc)();
|
typedef PRBool (*TestFunc)();
|
||||||
#define DECL_TEST(name) { #name, name }
|
#define DECL_TEST(name) { #name, name }
|
||||||
|
|
||||||
@ -543,6 +582,7 @@ static const struct Test {
|
|||||||
DECL_TEST(test_autoarray),
|
DECL_TEST(test_autoarray),
|
||||||
#endif
|
#endif
|
||||||
DECL_TEST(test_indexof),
|
DECL_TEST(test_indexof),
|
||||||
|
DECL_TEST(test_heap),
|
||||||
{ nsnull, nsnull }
|
{ nsnull, nsnull }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user