0

What I am trying to do is to implement a heuristic approach to NP complete problem: I have a list of objects (matches) each has a double score. I am taking the first element in the list sorted by the score desc and then remove it from the list. Then all elements bound to the first one are to be removed. I iterate through the list till I have no more elements.

I need a data structure which can efficiently solve this problem, so basically it should ahve the following properties:
1. Generic
2. Is always sorted
3. Has a fast key access

Right now SortedSet<T> looks like the best fit.

The question is: is it the most optimal choice for in my case?

List result = new List();
while (sortedItems.Any())
{
var first = sortedItems.First();
result.Add(first);
sortedItems.Remove(first);
foreach (var dependentFirst in first.DependentElements)
{
sortedItems.Remove(dependentFirst);
}
}

What I need is something like sorted hash table.

BanditoBunny
  • 3,086
  • 5
  • 26
  • 39
  • Which elements are bound to the first element in the list? How do you maintain this binding? – zmbq May 04 '12 at 09:59
  • I use a dictionary. something happned to SO :( – BanditoBunny May 04 '12 at 10:01
  • Obviously you do something with all those removed items, or you could just cleared sortedItems in the first place... – zmbq May 04 '12 at 11:18
  • Unfortunately I cannot clear sortedItems - it is not empty after only one iteration. – BanditoBunny May 04 '12 at 11:30
  • They *are* empty after you get out of the top `while`. If you're not doing anything besides removing the items, you might as well skip the whole thing. – zmbq May 04 '12 at 15:43

3 Answers3

2

I assume you're not just wanting to clear the list, but you want to do something with each item as it's removed.

var toDelete = new HashSet<T>();
foreach (var item in sortedItems)
{
    if (!toDelete.Contains(item))
    {
        toDelete.Add(item);
        // do something with item here
    }
    foreach (var dependentFirst in item.DependentElements)
    {
        if (!toDelete.Contains(item))
        {
            toDelete.Add(dependentFirst);
            // do something with item here
        }
    }
}
sortedItems.RemoveAll(i => toDelete.Contains(i));
Bryce Wagner
  • 2,496
  • 1
  • 23
  • 41
  • I realized I don't really want to remove anything, since it would be more expensive just hit and run (search and add) – BanditoBunny May 04 '12 at 12:12
1

I think you should use two data structures - a heap and a set - heap for keeping the sorted items, set for keeping the removed items. Fill the heap with the items, then remove the top one, and add it and all its dependents to the set. Remove the second one - if it's already in the set, ignore it and move to the third, otherwise add it and its dependents to the set.

Each time you add an item to the set, also do whatever it is you plan to do with the items.

The complexity here is O(NlogN), you won't get any better than this, as you have to sort the list of items anyway. If you want to get better performance, you can add a 'Removed' boolean to each item, and set it to true instead of using a set to keep track of the removed items. I don't know if this is applicable to you.

zmbq
  • 35,452
  • 13
  • 80
  • 153
  • I am currently having a similar idea: I will use a hash set to store all avaliable matches and a list which will be sorted by score. I will iterate over the list (and check if the element is still in the hashset, if yes -> remove, otherwise do nothing. – BanditoBunny May 04 '12 at 11:37
  • It looks like you gave the same answer I did, but it took me longer. But why would you claim it's O(NlogN)? Assuming HashSet doesn't degenerate into a linked list, it should be O(N) where N is the total number of DependentElements (instead of the main SortedItems). – Bryce Wagner May 04 '12 at 11:41
  • Adding the items to the heap (or SortedSet) and then taking them out is O(NlogN) – zmbq May 04 '12 at 15:14
0

If im not mistake, you want something like this

            var dictionary = new Dictionary<string, int>();
            dictionary.Add("car", 2);
            dictionary.Add("apple", 1);
            dictionary.Add("zebra", 0);
            dictionary.Add("mouse", 5);
            dictionary.Add("year", 3);
            dictionary = dictionary.OrderBy(o => o.Key).ToDictionary(o => o.Key, o => o.Value);
Likurg
  • 2,726
  • 15
  • 21
  • @BanditoBunny Comment please if this help or not – Likurg May 04 '12 at 10:41
  • what i need to do is: while (dictionary.Any()) { first = dictionary.First(); dictionary.Remove(first); foreach (var dependentFirst in first.DependentElements) { dictionary.Remove(dependentFirst); } } and do it very efficiently – BanditoBunny May 04 '12 at 11:06
  • @BanditoBunny why don't you use dictionary.Clear() ? – Likurg May 04 '12 at 11:18