fast erase-function for arrays

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
Marthog
Posts: 31
Joined: Sun Oct 03, 2010 8:33 pm
Contact:

fast erase-function for arrays

Post by Marthog »

The method array::erase is very slow, because it copies all following elements.
This does not change the order of the elements, but mostly I do not need sorted arrays.

So I wrote new functions which fills the new free element(s) with the the last one.
This is much faster because only a few elements have to be copied instead of shifting all following ones.

Code: Select all

        // array_quickerase erases the element at the given index
        // It erases the element and copies the last 
        // The array will not be sorted afterwards
        template <class T, typename TAlloc >
        static void array_quickerase(irr::core::array<T, TAlloc> &arr, irr::u32 index)
        {
                irr::u32 used = arr.size()-1;
 
                if (index>used)
                        return;
 
                T* data = arr.pointer();
 
                TAlloc allocator;
 
                T* lastElement = &data[used];   // Pointer to the last element
                T* indexElement = &data[index]; // Pointer to the element which will be erased
                allocator.destruct(indexElement);       // Erase the element
                allocator.construct(indexElement, *lastElement);        // Copy the last element to this position
                allocator.destruct(lastElement);        // Erase the last element
 
                arr.set_used(used);
                arr.set_sorted(false);
        }
        
        // array_quickerase erases the element at the given index
        // It swaps the erased element with the last and reduces the size, so that not all following elements need to be copied
        // The array will not be sorted afterwards
        template <class T, typename TAlloc >
        static void array_quickerase(irr::core::array<T, TAlloc> &arr, irr::u32 index, irr::s32 count)
        {
                irr::u32 used = arr.size();
                TAlloc allocator;
 
                if (index>=used || count<1)
                        return;
 
                T* data = arr.pointer();
 
                
                T* endRead = &data[used];
                T* write = &data[index];
 
                if (index+count>=used)          // If all elements until the end of the array are beeing erased
                {
                        used = index;
 
                        for (;write!=endRead; ++write)          // for (u32 i=index; i<used; ++i)
                                allocator.destruct(write);
 
                        return; // break function
                }
 
                T* read = &data[used-count];    // read = &data[index+count]
                T* endWrite = &data[index+count];
 
                if (read<endWrite)
                        read = endWrite;
 
                // Destruct block:
                for (T* ptr = write; ptr!=endWrite; ++ptr) // for (u32 i=index; i<index+count; ++i)
                        allocator.destruct(ptr);        // Erase elements
 
                // Write last elements to the destructed block
                for (; read!=endRead && write!=endWrite; ++write, ++read)
                {
                        allocator.construct(write, *read);      // Copy from read to write
                        allocator.destruct(read);                       // Remove the copied object
                }
 
                arr.set_used(used-count);
                arr.set_sorted(false);
        }
Rust fanboy
mongoose7
Posts: 1227
Joined: Wed Apr 06, 2011 12:13 pm

Re: fast erase-function for arrays

Post by mongoose7 »

You've turned the array into a heap. (Not that I care.)
Post Reply