如何对链表中的节点进行洗牌



我刚刚为我的Java2类开始了一个项目,我已经完全停止了。我就是搞不懂我对这个方法很感兴趣。特别是当赋值不允许我们使用任何其他数据结构或从java中shuffle方法时。

所以我有一个deck .类,我已经在其中创建了一个链表,包含52个节点,其中包含52张牌。

public class Deck {
    private Node theDeck;
    private int numCards;
    public Deck () 
    {
        while(numCards < 52)
        {
            theDeck = new Node (new Card(numCards), theDeck);
            numCards++;
        }
    }
    public void shuffleDeck()
    {           
        int rNum;
        int count = 0;
        Node current = theDeck;
        Card tCard;
        int range = 0;  
        while(count != 51)
        {   
            // Store whatever is inside the current node in a temp variable
               tCard = current.getItem();
            // Generate a random number between 0 -51      
                rNum = (int)(Math.random()* 51);
            // Send current on a loop a random amount of times
               for (int i=0; i < rNum; i ++)
                current = current.getNext();   ******<-- (Btw this is the line I'm getting my error, i sort of know why but idk how to stop it.)
            // So wherever current landed get that item stored in that node and store it in the first on
            theDeck.setItem(current.getItem());
            // Now make use of the temp variable at the beginning and store it where current landed
            current.setItem(tCard);
            // Send current back to the beginning of the deck
            current = theDeck;
            // I've created a counter for another loop i want to do     
            count++;
            // Send current a "count" amount of times for a loop so that it doesn't shuffle the cards that have been already shuffled.   
            for(int i=0; i<count; i++)
             current = current.getNext();  ****<-- Not to sure about this last loop because if i don't shuffle the cards that i've already shuffled it will not count as a legitimate shuffle? i think? ****Also this is where i sometimes get a nullpointerexception****
        }
    }
}

现在我得到了不同类型的错误当我调用这个方法时:

  • 它有时会洗2张牌,但有时它会洗3 - 5张牌,然后给我一个NullPointerException。我已经指出了它在

  • 上面的代码中给我这个星号错误的地方
  • 有一次我让它洗13张牌,但每次它这样做的时候,它都没有按正确的方式洗牌。有一张牌总是重复。

  • 在另一个点,我让所有52张卡片通过while循环,但它再次重复一张卡片多次。

所以我真的需要有人告诉我我做错了什么。在我的代码结束时,我认为我的逻辑是完全错误的,但我似乎无法找到一种方法。

似乎很啰嗦。

我想这样写:

public void shuffleDeck() {
    for(int i=0; i<52; i++) {
        int card = (int) (Math.random() * (52-i));
        deck.addLast(deck.remove(card));
    }
}

所以每张牌都被随机移动到牌堆的后面

如果您被授权使用二级数据结构,一种方法是简单地在剩余的卡数中计算一个随机数,选择该卡,将其移动到二级结构的末尾,直到为空,然后将您的列表替换为二级列表。

我的实现使用分治算法对链表进行洗牌

public class LinkedListShuffle
{
    public static DataStructures.Linear.LinkedListNode<T> Shuffle<T>(DataStructures.Linear.LinkedListNode<T> firstNode) where T : IComparable<T>
    {
        if (firstNode == null)
            throw new ArgumentNullException();
        if (firstNode.Next == null)
            return firstNode;
        var middle = GetMiddle(firstNode);
        var rightNode = middle.Next;
        middle.Next = null;
        var mergedResult = ShuffledMerge(Shuffle(firstNode), Shuffle(rightNode));
        return mergedResult;
    }
    private static DataStructures.Linear.LinkedListNode<T> ShuffledMerge<T>(DataStructures.Linear.LinkedListNode<T> leftNode, DataStructures.Linear.LinkedListNode<T> rightNode) where T : IComparable<T>
    {
        var dummyHead = new DataStructures.Linear.LinkedListNode<T>();
        DataStructures.Linear.LinkedListNode<T> curNode = dummyHead;
        var rnd = new Random((int)DateTime.Now.Ticks);
        while (leftNode != null || rightNode != null)
        {
            var rndRes =  rnd.Next(0, 2);
            if (rndRes == 0)
            {
                if (leftNode != null)
                {
                    curNode.Next = leftNode;
                    leftNode = leftNode.Next;
                }
                else
                {
                    curNode.Next = rightNode;
                    rightNode = rightNode.Next;
                }
            }
            else
            {
                if (rightNode != null)
                {
                    curNode.Next = rightNode;
                    rightNode = rightNode.Next;
                }
                else
                {
                    curNode.Next = leftNode;
                    leftNode = leftNode.Next;
                }
            }
            curNode = curNode.Next;                     
        }
        return dummyHead.Next;
    }
    private static DataStructures.Linear.LinkedListNode<T> GetMiddle<T>(DataStructures.Linear.LinkedListNode<T> firstNode) where T : IComparable<T>
    {
        if (firstNode.Next == null)
            return firstNode;
        DataStructures.Linear.LinkedListNode<T> fast, slow;
        fast = slow = firstNode;
        while (fast.Next != null && fast.Next.Next != null)
        {
            slow = slow.Next;
            fast = fast.Next.Next;
        }
        return slow;
    }
}

刚刚遇到这个问题,决定发布一个更简洁的解决方案,允许你指定你想要做多少洗牌。

对于答案的目的,您有一个包含PlayingCard对象的链表;

LinkedList<PlayingCard> deck = new LinkedList<PlayingCard>();

然后像这样洗牌;

public void shuffle(Integer swaps) {    
    for (int i=0; i < swaps; i++) {
        deck.add(deck.remove((int)(Math.random() * deck.size())));
    }                       
}

你做的交换越多,列表就越随机

相关内容

  • 没有找到相关文章

最新更新