views:

608

answers:

5

The requirement I have is for every type T, I have a number of elements (between 1-30+) and at first I need random item, then I need the next, and when I reach the last item, it should return the first one and so on.

So say T is Icon, and the collection is Images (instance).

I want to have:

// program start:

Icon icon = RandomIcon(); // say 5th one for this case

// user clicks next icon:

icon = current++; (6, 7, 8, 1, 2, ...)

To me a circular linked list makes sense, except that I have to do O(n) where n is the random index.

I want to have the cleanest, best implemenation, hence the question.

+5  A: 

Another possible solution is to create a linked list with the underlying data structure being an array. This way you can index in at O(1) while maintaining your "circularity"

public class myLL
{
    private T[] items;
    private int i;
    private int max_size;

    public T GetCurrent() {
        return items[i];
    }

    public T GetNext() {
        i = i++ % max_size;
        return items[i];
    }
}
Gavin Miller
If (for some reason) the list size is variable, and not known ahead of time, List<T> will have similar behaviour
Nader Shirazie
+1  A: 
  • Circular list is good
  • Since you have around 30 elements (and not like 3000, say), you could consider an indexed table rather than a linked list
    • This will work straight away if your elements do not keep getting added and removed
  • If you have dynamically inserted and deleted elements, you could still write some code to handle that (coz, small list)
  • If all this works for you, all that remains is a random between 1-N.


  • If your item count per list is small, it would be an over kill to implement a lined list
  • However, if you choose to do so, you could still afford a first traversal down the list to the randomly picked start point
nik
+1  A: 

Why use a linked list at all? Use an array and store the index of the current item. When a function is called to get the next item, increment the index. If the index is greater than the number of elements, set the index to zero.

Eyal
++ Simple is best. It's amazing how complicated simple things can be made.
Mike Dunlavey
+2  A: 

I would consider using a custom class containing an array or a List<T> internally, and making a custom enumerator that starts at any index, and enumerates around the loop.

The main reason I think this would be better than a LinkedList has to do with this line:

Icon icon = RandomIcon(); // say 5th one for this case

It is much easier and more performant to get a random item from an indexible collection than a linked list.... And with 30 elements, enumerating will be quick in either case.

To handle the iteration in a circle, all you need is something like this:

class CircularlyEnumerableList<T>
{
    private List<T> list;

    // Implement whatever you need for list...

    IEnumerable<T> EnumerateFromElement(int index)
    {
        for (int i=index; i<list.Count; ++i)
             yield return list[i];

        for (int i=0; i<index; ++i)
             yield return list[i];
    }
}
Reed Copsey
Thanks Reed. How would the "GetNextItem" would be called in this case? I have to call the internal IEnumerable methods?
Joan Venge
Joan: No. I'll edit my answer to show you.
Reed Copsey
Thanks Reed. I somehow thought you were gonna use foreach. So in this case, 2 for loops is better than putting the random index code, inside the enumerator, right? Should the random index code be in the constructor? That's what I think.
Joan Venge
Joan: I'd leave it out, so you can have your icon list, and just do something where you fill one single icon list, and just randomly pull from it. That way you don't need to make a new collection every time - just use the same one, with a new random start point. - I think this is much cleaner (and much faster) than trying to use foreach and randomize the indexing that way.
Reed Copsey
Thanks Reed. If I understand you correctly, you thought the icon list is fixed for all, right? Every item has an icon list that's different than others. If that's different than what you thought, would it change your reply/thoughs? Thanks.
Joan Venge
Not necessarily. You could easily compute the randomized index in the constructor, though, if you wanted. The nice thing then would be that you wouldn't need to pass in the index anymore - it'd just be there. I'd still use the same approach for the collection, though, as well as the enumeration.
Reed Copsey
A: 

Hi Can you help me with a circular list structure I need an example. delete, and search jobs make additions. delete, and search jobs make additions. I'm using c + + and Visual Studio 2008. thanks

serpil
This is not the place for a question.
bentsai