DekGenius.com
[ Team LiB ] Previous Section Next Section

Recipe 9.9 Keeping Your ArrayList Sorted

Problem

You will be using the BinarySearch method of the ArrayList to periodically search the ArrayList for specific elements. The addition, modification, and removal of elements will be interleaved with the searches. The BinarySearch method, however, presupposes a sorted array; if the ArrayList is not sorted, the BinarySearch method will possibly return incorrect results. You do not want to have to remember to always call the ArrayList.Sort method before calling the ArrayList.BinarySearch method, not to mention incurring all the overhead associated with this call. You need a way of keeping the ArrayList sorted without always having to call the ArrayList.Sort method.

Solution

The following class enhances the adding and modifying of elements within an ArrayList. These methods keep the array sorted when items are added to it and modified. Note that a DeleteSorted method is not required since this method would not disturb the sorting:

using System;
using System.Collections;

public class SortedArrayList : ArrayList
{
    public void AddSorted(object item)
    {
        int position = this.BinarySearch(item);
        if (position < 0)
        {
            position = ~position;
        }

        this.Insert(position, item);
    }

    public void ModifySorted(object item, int index)
    {
        this.RemoveAt(index);

        int position = this.BinarySearch(item);
        if (position < 0)
        {
            position = ~position;
        }

        this.Insert(position, item);
    }
}

Discussion

Instead of calling ArrayList.Add directly to add elements, use the AddSorted method to add elements while at the same time keeping the ArrayList sorted. The AddSorted method accepts an object (item) to add to source.

Likewise, instead of using the ArrayList indexer directly to modify elements, use the ModifySorted method to modify elements while at the same time keeping the ArrayList sorted. Call this method, passing in the object to replace the existing object (item), and the index of the object to modify (index).

The following code exercises the SortedArrayList class:

class CTest
{
   static void Main( )
   {
        // Create a SortedArrayList and populate it with 
        //    randomly choosen numbers
        SortedArrayList sortedAL = new SortedArrayList( );
        sortedAL.AddSorted(200);
        sortedAL.AddSorted(20);
        sortedAL.AddSorted(2);
        sortedAL.AddSorted(7);
        sortedAL.AddSorted(10);
        sortedAL.AddSorted(0);
        sortedAL.AddSorted(100);
        sortedAL.AddSorted(-20);
        sortedAL.AddSorted(56);
        sortedAL.AddSorted(55);
        sortedAL.AddSorted(57);
        sortedAL.AddSorted(200);
        sortedAL.AddSorted(-2);
        sortedAL.AddSorted(-20);
        sortedAL.AddSorted(55);
        sortedAL.AddSorted(55);

        // Display it
        foreach (int i in sortedAL)
        {
            Console.WriteLine(i);
        }

        // Now modify a value at a particular index
        sortedAL.ModifySorted(0, 5);
        sortedAL.ModifySorted(1, 10);
        sortedAL.ModifySorted(2, 11);
        sortedAL.ModifySorted(3, 7);
        sortedAL.ModifySorted(4, 2);
        sortedAL.ModifySorted(2, 4);
        sortedAL.ModifySorted(15, 0);
        sortedAL.ModifySorted(0, 15);
        sortedAL.ModifySorted(223, 15);

        // Display it
        Console.WriteLine( );
        foreach (int i in sortedAL)
        {
            Console.WriteLine(i);
        }
    }
}

This method automatically places the new item in the ArrayList while keeping its sort order; this is done without having to explicitly call ArrayList.Sort. The reason this works is because the AddSorted method first calls the BinarySearch method and passes it to the object to be added to the ArrayList. The BinarySearch method will either return the index where it found an identical item or a negative number that we can use to determine where the item that we are looking for should be located. If the BinarySearch method returns a positive number, we can use the ArrayList.Insert method to insert our new element at that location, keeping the sort order within the ArrayList. If the BinarySearch method returns a negative number, we can use the bitwise complement operator ~ to determine where the item should have been located, had it existed in the sorted list. Using this number, we can use the ArrayList.Insert method to add the item to the correct location in source while keeping the correct sort order.

You can remove an element from source without disturbing the sort order, but modifying an element's value in the ArrayList most likely will cause source to become unsorted. The ModifySorted method alleviates this problem. This method works similarly to the AddSorted method, except that it will initially remove the element from the ArrayList and then insert the new element into the correct location.

See Also

See the "ArrayList Class" topic in the MSDN documentation.

    [ Team LiB ] Previous Section Next Section