2014-12-13 71 views
1

我有一个函数需要一个双向链表。头是第一个节点,尾是最后一个节点。有52个节点(卡牌)我试图做的是执行一个洗牌,就像你用手洗牌一样。所以你把甲板砍下一半,从上半部分拿下底牌,将底牌从另一半上取下,并将其放在顶部。将一个链表重新排序

所以。左半部分是1 2 3右半部分是4 5 6后洗牌4 1 5 2 6 3

我知道我的错误是在指针中,他们相互覆盖。我只是不知道如何正确地对这些列表进行排序,并将它们一个接一个地抽出来,然后将它们粘在一起。

bool Shuffle(deck* &head, deck* &tail, int ShuffleAmnt) 

{

deck* temp_tail = nullptr; 
deck* temp_head = head; 
deck* temp_list = new deck; 
for (int i = 1; i < 26; i++) 
    temp_head = temp_head->next; 

temp_tail = temp_head->next; 

temp_tail->previous = nullptr; 

temp_head->next = nullptr; 


while (head->next != NULL) // get to the bottom of head 
    head = head->next; 

temp_head->previous = nullptr; 
temp_tail->next = nullptr; 

for (int i = 1; i < 26; i++) 
{ 
    temp_list->next = temp_head; 
    temp_head = head->previous; 
    temp_list = temp_list->next; 
    temp_list->next = temp_tail; 
} 

head = temp_list; 



return(true); 

}

+0

你的第三个参数是做什么的? – TheDillo 2014-12-13 08:09:40

+1

这是谁的想法来代表一个链接列表卡组?一个'std :: vector','std :: array'或者一个普通的旧数组更有意义。 – PaulMcKenzie 2014-12-13 08:17:09

+0

洗牌链接列表的最安全方法是将数据复制到数组,将数组随机混洗,然后将数组结果复制回您的列表。假设你有通过你的列表的函数,并且可以将数据复制回你的列表。此外,洗牌应该是随机的,而不是像你的代码似乎暗示的那样“控制”。例如:在洗牌后,甲板上的第一张牌可能会潜在甲板上的任何位置。 – PaulMcKenzie 2014-12-13 08:23:00

回答

2

这个答案可能没有直接回答这个问题,但它是在这里指导和教育如果这是所需的。

C++标准库中已经有(几乎)每个容器类型和逻辑操作的模板实现你永远都需要。这些构建块每天都在数十亿台计算机上使用,并已针对您的编译器效率进行了优化,并由全球最专业的程序员进行了同行评审。简而言之,没有理由考虑编写一个链表(std::list)或编写一个shuffle算法(std::random_shuffle)。

如果你真的想保持卡链表(你不这样做,一个向量是更自然的),你可以重构,以这样的:如果你决定做正确的事(

#include <vector> 
#include <list> 
#include <algorithm> 

struct Card {}; 

typedef std::list<Card> deck; // that's it - a complete linked list implementation 

void shuffle_deck(deck& the_deck) { 
    // c++11 takes advantage of efficiently copying by value. 
    std::vector<Card> temp(std::make_move_iterator(the_deck.begin()), 
          std::make_move_iterator(the_deck.end())); 

    // clear out the zombie objects that will have been left by the move 
    the_deck.clear(); 

    // those clever fellows in the standards committee thought of everything... 
    // even shuffling a deck of cards! 
    std::random_shuffle(temp.begin(), temp.end()); 

    // move the cards back into the linked list in the correct order 
    std::move(temp.begin(), temp.end(), back_inserter(the_deck)); 
} 

TM),使您的扑克牌载体,它的更简单:

typedef std::vector<Card> deck_of_cards; 

void shuffle_deck(deck_of_cards& deck) 
{ 
    std::random_shuffle(deck.begin(), deck.end()); 
} 

如果你正期待着一个有价值的职业写C++,需要时间来全面掌握了标准库 - 许多C++程序员不打扰学习algorithm库 - 这是一个错误。它是优雅,可维护代码的基础。

以下是有关std::random_shuffle文档的链接。 http://en.cppreference.com/w/cpp/algorithm/random_shuffle

你会注意到,它被标记为从C++ 17中删除,因为它正被上级std::shuffle所取代。然而,为了讨论的目的,我认为这可能会导致主要问题的分心 - 这是鼓励你学习和使用标准库:-)

+0

'std :: random_shuffle'已弃用,建议在2017年删除。请改用'std :: shuffle'。 – 2014-12-13 11:58:03

+0

完全同意。回答这样一个问题的难点之一是“我会采取多少步骤”?涉及'std :: shuffle'则引入了我认为与所讨论的问题相切的生成器的概念。 – 2014-12-13 12:08:54

+0

我会说['std :: shuffle'](http://en.cppreference.com/w/cpp/algorithm/random_shuffle)足以供大家谁可以阅读使用,但我明白你的观点和找到它也是合法的。你可以考虑在你的回答中增加一个“std :: random_shuffle”已被弃用的评论。我觉得这是值得提及的。 – 2014-12-13 12:28:32

0

你可以象下面这样:

bool Shuffle(deck* &head, deck* &tail, int ShuffleAmnt = 1) 
{ 
    deck* temp_tail = nullptr; 
    deck* temp_head = head; 
    for (int i = 1; i < 26; i++) 
    temp_head = temp_head->next; 

    temp_tail = temp_head->next; 
    temp_tail->previous = nullptr; 

    temp_head->next = nullptr; 
    temp_head = head; 

    temp_head_next = temp_head->next; 
    temp_head_next->previous = temp_head; 

    temp_tail_next->next = temp_tail->next; 
    temp_tail_next->previous = temp_tail; 

    head = temp_tail; 

    for (int i = 1; i < 26; i++) 
{ 
    temp_tail->next = temp_head; 
    temp_head->previous = temp_tail; 
    temp_head->next = temp_tail->next; 

    temp_tail = temp_head_next; 
    temp_head = temp_head_next; 

    temp_head_next = temp_head->next; 
    temp_head_next->previous = temp_head; 

    temp_tail_next->next = temp_tail->next; 
    temp_tail_next->previous = temp_tail; 
    } 
tail = temp_head; 
return(true); 

}