views:

90

answers:

3

I have to implement a method:

E[] toArray(E[] a) // Pass an array, convert to singly linked list, then return the array. 

from java.util Interface List<E>

As I mentioned, I have to pass an array, convert it to a singly linked list, sort it, then return the array.

In the Node class I have this to work with:

public Node(E v, Node<E> next) {
    // pre: v is a value, next is a reference to remainder of list
    // post: an element is constructed as the new head of list
    data = v;
    nextElement = next;
}

public Node(E v) {
    // post: constructs a new tail of a list with value v
    this(v,null);
}

public Node<E> next() {
    // post: returns reference to next value in list
    return nextElement;
}

public void setNext(Node<E> next)  {
    // post: sets reference to new next value
    nextElement = next;
}

public E value() {
    // post: returns value associated with this element
    return data;
}

public void setValue(E value) {
    // post: sets value associated with this element
    data = value;
}

Am I barking up the wrong tree or can someone help me with this here? Sorry if this is the wrong place for such questions.

A: 

Obvious wrong answer:

    E[] toArray(E[] a)
    { return a; }  // Prove I didn't make the linked list.

I assume there are some side effect to constructing and sorting the linked list that you completely skipped? Or maybe the return is supposed to be the sorted list, not the array, possibly the sorted list coerced back into an array?

Eric Towers
straight from the horse's mouth:
meesh
Returns an array containing all of the elements in this list in proper sequence (from first to last element); the runtime type of the returned array is that of the specified array. If the list fits in the specified array, it is returned therein. Otherwise, a new array is allocated with the runtime type of the specified array and the size of this list.
meesh
If the list fits in the specified array with room to spare (i.e., the array has more elements than the list), the element in the array immediately following the end of the list is set to null. (This is useful in determining the length of the list only if the caller knows that the list does not contain any null elements.)
meesh
The only way it would be smaller is if you're supposed to eliminate duplicates or otherwise drop array members as they pass through this process. So, are you supposed to eliminate array elements as they pass through? The only way it could get larger is if you're supposed to invent new elements that weren't in the array initially, which also hasn't been mentioned up to now.
Eric Towers
That's a good point. I'll do my best to figure out an answer.
meesh
A: 

I hope this does what you want:

/**
 * You need to pass in the class of the object you are creating
 * because you can't instantiate a generic class.
 */
public static <E> E[] toArray(E[] a, Class<E> clazz) {
    Node<E> root = null;
    Node<E> prev = null;
    Node<E> curr = null;

    for (E e : a) {
        curr = new Node<E>(e);
        if (prev != null) {
            prev.setNext(curr);
        }
        else {
            root = curr;
        }
        prev = curr;
    }

    curr =  root;

    // Cast is unsafe. I don't know a better way to do this.
    E[] newArray = (E[]) Array.newInstance(clazz, a.length);
    int i = 0; 
    while (curr != null) {
        newArray[i] = curr.value();
        curr = curr.next();
        i++;
    }

    return newArray;
}

As I say in the code, I don't know how to correctly instantiate a generic class. Can someone correct me?

shoebox639
I would love to be able to correct you but you're way ahead of me, so all I can say do is try to follow the logic. Thanks for the input.
meesh
By the way is this AP comp sci homework? I remember doing stuff like this in high school. I'll take silence as tacit agreement ;)
shoebox639
Sorry to bother. Didn't know if I was in the right place or not.
meesh
Heh, just saying, if I were a teacher I'd troll here days before an assignment is due.
shoebox639
Well, to be honest, they don't seem to care. They encourage us to get help online and from each other and such.
meesh
Okay, I think you correctly instantiate a generic class by using java.lang.reflect.Array.newInstance() which is the only way to create generic array of type E.
meesh
So was your issue that you couldn't instantiate a generic array? Or how to go through a linked list and drop it into an array?
shoebox639
I didn't know if I was supposed to sort the array (as a linked list) then return the original array, or create a new array and return that. There's a level of complexity beyond the Object[] toArray() method, which seems straight forward, but using a generic class is throwing me for a loop. API Docs here for list interface: http://download.oracle.com/javase/6/docs/api/java/util/List.html
meesh
Ahh... so the point is to sort the array? Were there any requirements on the sort? Like the runtime of it? It's easier sorting linked lists so you don't have to recopy the array over and over again if you are doing divide and conquer sorts. Let me know if you are looking for a sorting algo. One of the other answers here is using selection sort and will work, but if you want faster, look up merge sort.
shoebox639
The sorting is actually maintained by the add() and addAll() methods in the List interface. Sorry, I may have just inadvertently wasted y'alls time by not sharing that piece of information. Docs: "Like the toArray() method, this method acts as bridge between array-based and collection-based APIs. Further, this method allows precise control over the runtime type of the output array, and may, under certain circumstances, be used to save allocation costs."
meesh
+1  A: 

The following code will create the single linked list and copy that back to new copy of the array. For the sort you need to make sure you make the \"E"\ type implementes comparable. One way is to change the generic declarator of \"E"\, to <E extends Comparable<? super E>>.


    E[] toArray(E[] a)
    {
        E[] result ;
        Class<?> type ;
        Node<E> head, temp, current ;

        /*
         * Makes a copy of the original array
         */
        type = a.getClass().getComponentType() ;
        result = (E[])java.lang.reflect.Array.newInstance(type, a.length);
        for(int idx = 0; idx < a.length; idx++)
            result[idx] = a[idx] ;

        /*
         * Sort the array (selection copy)
         */
        for(int idx = 0; idx < result.length; idx++)
        {
            int best = idx ;
            for(int jdx = idx + 1; jdx < result.length; jdx++)
            {
                if (result[best].compareTo(result[jdx]) > 0)
                {
                    best = jdx ;
                }
            }
            // swap
            if (best != idx)
            {
                E temporal = result[idx] ;
                result[idx] = result[best] ;
                result[best] = temporal ;
            }
        }

        /*
         * Compose the single linked list (SORTED)
         */
        head = new Node<E>(null, null) ;

        // Create the single linked list
        current = head ;
        for(E element : result)
        {
            temp = new Node<E>(element, null) ;
            current.setNext(temp) ;
            current = current.next();
        }

        /*
         * Copy the single linked list to the array 
         * (Not needed, added just for educational purpose,
             * the result array is already SORTED)
         */

        current = head.next ;
        // copies the values to the result array
        for(int index = 0; current != null ; current = current.next)
            result[index++] = current.value();

        return result ;
    }
XecP277