简体   繁体   中英

Splitting a linked list into two lists and interleaving their nodes together into one linked list

I am attempting to split a list of nodes in two and merge the two linked lists back into a single list. For example {"KH","4C","8C","QC","3D","7D","JD"} becomes {"KH","4C","8C","QC"} {"3D","7D","JD"} (if as in this case the lists have an odd number of nodes then the first list is longer) and returns the list {"KH","3D","4C","7D","8C","JD","QC"} . Looking through my errors it seems I am not merging the lists back together properly in my if statement.

I have to use the provided node class and cannot use static variables, arrays or Java collections. Could you explain how I should be merging my two lists of nodes back together?

my code

public class ListShuffleExample {

public static Node<String> shuffle(Node<String> deck) {
    if(deck == null){
        return null;
    }
    int decklength = length(deck);
    if(decklength % 2 == 0){
        Node<String> first = deck;
        Node<String> second = deck;
        int halflength = decklength / 2;
        int i;
        for(i = 0; i < halflength; i++){
            second = second.next;
        }
        while(second.next != null){
            first.next = second;
            second = second.next;
        }

        return first;

    }
    else{
        Node<String> first = deck;
        Node<String> second = deck;
        int halflength = (decklength / 2) + 1;
        int i;
        for(i = 0; i < halflength; i++){
            second = second.next;
        }
        while(second.next != null){
            first.next = second;
            second = second.next;
        }

        return first;

    }

}

public static int length(Node<String> adeck){
    int length = 0;

    while(adeck.next != null){
        length++;
        adeck = adeck.next;
    }

    return length;
}
}

Node class

public final class Node<T> {
public final T       value;
public       Node<T> next;

public Node(T _value) {
    this( _value, null );
}
public Node(T _value, Node<T> _next) {
    value = _value;
    next  = _next;
}
@Override
public String toString() {
    return "" + value;
}
}

my test case

@Test
public void testMany() {
    @SuppressWarnings("unchecked")
    Node<String> input  = makeList( _AH, _5H, _9H, _KH, _4C, _8C, _QC, _3D, _7D, _JD, _2S, _6S, _TS );
    Node<String> actual = ListShuffleExample.shuffle( input );
//                                           _AH,      _5H,      _9H,      _KH,      _4C,      _8C,      _QC
//                                                _3D,      _7D,      _JD,      _2S,      _6S,      _TS
    for (Object expected : new Object[]{ _AH, _3D, _5H, _7D, _9H, _JD, _KH, _2S, _4C, _6S, _8C, _TS, _QC }) {
        assertEquals( "Incorrect value", expected, actual );
        actual = actual.next;
    }
    assertNull( "Incorrect result", actual );
}

From what I understood you are not really shuffling, but you are interleaving the two lists together. So its like when you get to decks of cards and join them into one deck, alternating them one from each deck.

The problem in your code is here:

  while(second.next != null){
            first.next = second;
            second = second.next;
        }

You are never updating the first reference to move to the next node, and you are never updating the second reference to point to the one after the first. You are always overwriting the same first.next .

What about:

 Node<String> curFirst = first;
 Node<String> curSecond = second;

 while(curFirst != null && curSecond != null)
 {
    //save the next one of the first list
    Node<String> nextFirst = curFirst.next;

    //set the next one of the first list to the first one of the second list
    curFirst.next = curSecond;

    //save the next one of the second list
    Node<String> nextSecond = curSecond.next;

    //set the next one after the inserted item to the previous next of the first list
    curSecond.next = nextFirst;

    //set the current references to the next ones
    curFirst = nextFirst;
    curSecond = nextSecond;
 }
 //once any of the pointers becomes null it means we're done because the rest of the list should be still intact

You might need to check for some corner cases when the list is empty, or when the list only has 1 item etc., but I leave that to you!

UPDATE After comments below

The length calcuation is also wrong, it will throw a NullPointerException if the list is empty (ie aDeck is null ), and will return one less item if it contains any items. You should change the condition to while(adeck != null) .

Furthermore, don't have repeated code. Move the part where you are traversing to the halflength and merging the list to after the else finishes. Its the same for both when the length is even or when it is odd.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM