2014-12-13 64 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); 

}