如何在链表前添加和返回节点

时间:2018-04-11 18:52:23

标签: c++ pointers linked-list

我正在使用linked_list制作一款小游戏。我有班级电话卡

class card
{
public:
    int number;
    int suit;
    static int uniquenumber;
    card();
    void showcard();
    card * next;
};

然后对于以下的linked_list结构,我想将卡添加到linked_list的前面。

void collection::add(card a)
{
    card *temp = new card(a);
    temp->next = start;
    start = temp;
}

但我无法得到我想要的结果。此外,还有另一个功能需要从linked_list的前面删除卡,并返回卡。我不知道如何从linked_list返回一个节点。

card collection::deal(){
card *temp = start->next;
start->next = nullptr;
start = temp;
return start;
}

这种方式只会给我一个错误,说“无法转换”卡*“到”卡“”

3 个答案:

答案 0 :(得分:2)

添加

参观的时间:

void collection::add(card a) // pass by value. a is a copy 
{
    card *temp = new card(a); // makes a dynamically allocated copy of the copy.
    temp->next = start; // looks right
    start = temp; // looks right
}

此功能没有明显错误,但如果你想要

myCollection.add(mycard);

然后期望使用mycard,就好像它在myCollection中一样,你运气不好。 mycard的副本位于mycollection。我们可以略微改进以减少复制量,

void collection::add(const card & a) // pass by reference. a is the source. One less copy
                                     // Look up const correctness for more information 
                                     // on the use of const here 
{
    card *temp = new card(a); // makes a dynamically allocated copy of the copy.
    temp->next = start; 
    start = temp;
}

但是如果你希望mycard在列表中而不是它的副本中,你需要以非常不同的方式做事

void collection::add(card * a) // pass by reference via a pointer
{
    a->next = start;
    start = a;
}

并使用类似:

card * mycard = new card()
// set members of *mycard. Or better, make a smarter constructor to set them for you
myCollection.add(mycard);

去除

card collection::deal(){
    card *temp = start->next; //temp points to the second item on the list
    start->next = nullptr; // cur off start from the rest of the list
    start = temp; // whups! Just lost the first item in the list
    return start; // start is a pointer. The return type is not. Need to dereference
}

修复一个:deference指针返回它。

card collection::deal(){
    card *temp = start->next; 
    start->next = nullptr; 
    start = temp; 
    return *start; // returns a copy of the second card in the list
}

下一步修复:返回正确的卡

card collection::deal(){
    card *temp = start; //temp points to the first item on the list
    start = start->next; // advance start to second item on the list
    temp->next = nullptr; // cut former first item off from from the list
    return *temp; // returns a copy of the former first item. But what of temp?
}

下一步修正:temp被泄露了。没有人指出它,记忆永远不会被释放。

card collection::deal(){
    card *temp = start; 
    start = start->next; 
    temp->next = nullptr; 
    card rval(*temp); // copy former first node
    delete temp; // free former first node
    return rval; // return copy.
}

您还可以返回指向已删除项目的指针,并将其释放给调用者。这有点狡猾。

card * collection::deal(){
    card *temp = start; //temp points to the first item on the list
    start = start->next; // advance start to second item on the list
    temp->next = nullptr; // cut former first item off from from the list
    return temp; // returns former first item 
}

on click作为确保调用者释放返回的card指针的工具。

另一种可能性是将链接列表与card分开。这样collection的用户只会看到card,并且不知道card是如何存储的在collection内。

答案 1 :(得分:1)

您的add()看起来不错,但您的deal()完全错了。它应该看起来更像是这样:

card collection::deal()
{
    if (!start) throw std::runtime_error("deck is empty!");
    card *temp = start;
    start = temp->next;
    card theCard = *temp;
    c.next = nullptr;
    delete temp;
    return theCard;
}

您可以使用更具创意的编码来简化代码,例如:

class card
{
public:
    int number;
    int suit;
    card * next;

    static int uniquenumber;

    card();
    card(const card &src, card *n = nullptr);
    card& operator=(const card &rhs);

    void showcard();
};

#include <memory>

card::card()
    : number(0), suit(0), next(nullptr)
{
}

card::card(const card &src, card *n)
    : number(src.number), suit(src.suit), next(n)
{
}

card& card::operator=(const card &rhs)
{
    if (&rhs != this)
    {
        number = rhs.number;
        suit = rhs.suit;
        // don't copy 'next'!
        next = nullptr;
    }
    return *this;
}

void collection::add(const card &a)
{
    start = new card(a, start);
}

card collection::deal()
{
    if (!start) throw std::runtime_error("deck is empty!");
    std::unique_ptr<card> temp(start);
    start = start->next;
    return *temp;
}

但是,话虽如此,从设计的角度来看,card根本不应该有next成员。您应该将card与链接列表的实现分开(这将允许您稍后更改列表的实现,而无需更改card以匹配)。您需要一个包含卡对象的列表,而不是 卡对象的列表。

您应该使用std::list进行分离,例如:

#include <list>

class card
{
public:
    int number;
    int suit;

    static int uniquenumber;

    card();
    void showcard();
};

class collection
{
private:
    std::list<card> cards;

public:
    void add(const card &a);
    card deal();
};

void collection::add(const card &a)
{
    cards.push_front(a);
}

card collection::deal()
{
    if (cards.empty()) throw std::runtime_error("deck is empty!");
    card theCard = cards.front();
    cards.pop_front();
    return theCard;
}

但是,如果你不能使用std::list,那么你可以使用更像这样的东西:

class card
{
public:
    int number;
    int suit;

    static int uniquenumber;

    card();
    void showcard();
};

class collection
{
private:
    struct collectionItem
    {
        card theCard;
        collectionItem *next;

        collectionItem(const card &a, collectionItem *n);
    };

    collectionItem *start;

public:
    collection();
    ~collection();

    void add(const card &a);
    card deal();
};

#include <memory>

collection::collection()
    : start(nullptr)
{
}

collection::collectionItem::collectionItem(const card &a, collectionItem *n)
    : theCard(a), next(n)
{
}

collection::~collection()
{
    collectionItem *item = start;
    while (item)
        item = std::unique_ptr<collectionItem>(item)->next;
}

void collection::add(const card &a)
{
    start = new collectionItem(a, start);
}

card collection::deal()
{
    if (!start) throw std::runtime_error("deck is empty!");
    std::unique_ptr<collectionItem> temp(start);
    start = temp->next;
    return temp->theCard;
}

答案 2 :(得分:0)

如果你有指针变量,你可以得到指针取消引用指针引用的实际值。

尝试return *start;