【问题标题】:linked list C++ , question selflearning链表C++,问题自学
【发布时间】:2011-04-16 20:33:56
【问题描述】:
        #include <iostream>
    using namespace std;



    struct Node
    {
        int item;   // storage for the node's item
        Node* next;   // pointer to the next node 
    };

  Node* addNode(Node*& head, int data , int& count) 
{
    Node * q;     // new node
    q = new Node;  // allocate memory for the new mode
    q->item = data;  // inserting data for the new node
    q->next = head;   // point to previous node ?? how would i do that? ( am i doing it correctly?)
    count++; // keep track of number of node
    head = q;
    return q;
}



    int main()
    {
        int a, count=0;
        int data;
        bool repeat;
        Node *head= NULL;   
        //^^ assuming thats creating the first node ^^
        do
        {
        cout << "please enter the data for the next node" <<endl;
        cin >> data;
        addNode(head, data, count);
        cout << "do you wish to enter another node? (enter true or false)" << endl;
        cin >>repeat;
        }
       while (repeat == true);


       // assuming this is the print function  
          while(head != NULL)
        {
            cout << "output" << temp->item << endl;
            cout << temp->next << endl;
        }

        system("pause");
        return 0; 
    }

好吧,我尝试在列表中添加一个新元素,我将如何像 LIFO 内存(堆栈)一样移动头部,所以最后一个元素位于最顶部..

任何帮助将不胜感激!指针和节点最近在搞乱我的大脑......

【问题讨论】:

  • 要使用代码按钮{},您必须选择所有代码。
  • 下次请使用更合适的语言。
  • 一个简单的 google 搜索可以显示很多 C++ 已经完成的示例
  • 我想自己做,所以我知道如何从头开始做
  • 更新了...试图把所有东西都放在一个函数中

标签: c++ linked-list self


【解决方案1】:

temp 是一个未初始化的指针。所以——

temp-> item = a;  // temp is not initialized or pointing to a memory location
                  // that has Node object to use operator ->

首先,temp 需要使用new 分配内存位置。

temp = new Node;
temp -> item = a;

现在分配它head。同样在while 循环中也为子节点分配内存。并在程序终止前使用delete将所有从child获得的资源返回给head。

【讨论】:

  • 哦,我的糟糕,我是在飞行中做的,没有注意数据类型
【解决方案2】:

你这里好像有些误会:

你的“头”是列表的开始。这永远是开始。

您通过将元素分配给最后一个节点的next 指针来add 将元素附加到链表。

第三,你没有分配任何东西。

Node *head= new Node();   
Node *temp = new Node();
cout<<"enter something into data"<<endl;
cin >> a ;
temp->item = a;
head->next = temp;

现在...要添加下一个,要么需要跟踪最后一个节点(tail),要么遍历列表找到最后一个节点。

Node *nextNode = new Node();
nextNode->item = 0.0;
Node *i;
for (i = head; i->next != null; i = i->next);
i->next = nextNode;

这是 O(n) 的执行时间。通过跟踪尾巴,您可以使它成为 O(1):

Node *head= new Node();
Node *tail = head;   
Node *temp = new Node();
cout<<"enter something into data"<<endl;
cin >> a ;
temp->item = a;
tail->next = temp;
tail = temp;

Node *nextNode = new Node();
nextNode->item = 0.0;
tail->next = nextNode;
tail = nextNode;

编辑:正如所指出的,如果您想添加到列表中,您会:

temp->next = head;
head = temp;

【讨论】:

  • 我不同意。如果你重复你的代码,你会造成内存泄漏,因为你会多次覆盖 head-&gt;next 的项目。 Ricedragon 做的大部分是正确的,因为他在列表的开头插入,然后将头部设置为新值。这基本上是 std::list 的 push_front()。编辑:对不起,第一次没有看到你的最后一句话。但是,我仍然认为 Ricedragons 方式有效,除了缺少分配。
  • 如果你想要push 功能,我同意你的看法。我正在描述附加 ::shrug:: 取决于您要查找的内容。回到过去,我总是只跟踪尾巴,以便轻松做到这一点。
  • @Thilo 我稍微修改了原始代码,但无法弄清楚如何向头部添加新元素。 @Brian Roach ty 这对我很有帮助,现在我添加了新代码(对原始代码的修改,您可以看一下吗?)
【解决方案3】:

由于我不确定每个答案都完全回答了它,这里有一个链表实现(没有测试:

// your (correct) structure
struct Node
{
    float item;   // storage for the node's item
    Node* next;   // pointer to the next node 
};

现在我们需要两个指针来处理列表:

/* some pointers */
struct List
{
    Node* head;
    Node* tail;
};

现在我们需要创建一些元素。正如其他人所说,您可以使用 new 来做到这一点:

/* create some elements we want to link in */
Node* elem1 = new Node();
Node* elem2 = new Node();
Node* elem3 = new Node();
/* maybe even set their properties! */
elem1->item = 3.14;
elem2->item = 3.14;
elem3->item = 3.14;

注意到我还没有尝试将这些元素添加到列表中吗?那是因为我想到了一个看起来像这样的函数:

void addtolist(List &list, Node* node)
{
    /* if no head, initialise the list */
    if ( list->head == NULL )
    {
        list->head = node;
        list->tail = node;
    }
    else if ( list->head != NULL && list->tail != NULL )
    {
        /* access the tail element and set its 
           next to this ptr. 
           Move tail to this node */
        list->tail->next = node;
        list->tail = node;
    }
    else
    {
        /* probably raise an exception! */
    }
}

你可以这样调用它:

List l;
addtolist(l, elem1); /* etc */

删除元素有点棘手,因为你必须去那个元素,记住它的前一个元素,抓住它的下一个元素,将它们连接起来并删除你所在的 Node*。

现在对于遍历列表...您的术语HEAD|TAIL 让我想起了 Erlang 和尾递归,其中当前元素称为头部,其余元素称为尾部。如果我写:

Node* cur = l.head;
while ( cur != NULL )
{
    // do something with cur.item ? 
    cur = cur->next;
}

您可以看到这种情况发生。多亏了List 结构,在这里用head 替换cur 是无害的。

最后,我在这里使用了一种非常类似于 C 的方法,但还有模板的范围:

template<typename T>
struct node
{
    T item;   // storage for the node's item
    Node<T>* next;   // pointer to the next node 
};

并将List 结构封装为一个类:

template<typename T>
class List
{
protected:
    Node<T>* head;
    Node<T>* tail;
public:

    void addtolist(Node<T>* node);
    Node<T>* gethead();
    Node<T>* gettail();
}

这会让你更接近std::list

【讨论】:

  • 非常好的解释,但我不喜欢递归。递归一直在弄乱我的大脑......
  • @ricedragon 那段特定的代码不是递归。递归涉及使用函数。只是您使用了与 Erlang 的列表尾递归概念非常相似的术语。但是那个while循环不是递归,它只是不断地查找下一项。
  • @Ninefiningure 我今天早些时候正在学习递归,是的,我意识到不是。但这是我第一次在新节点中看到尾部和头部。我仍然是一个初学者,暂时不了解基本情况,请您回复
【解决方案4】:

另外请注意,您正在执行从 intfloat 的隐式转换

temp-> item = a;

因为aint,而temp-&gt;itemdouble

解决您的问题:您想在访问temp之前分配一个新结构,因此

temp = new Node();

【讨论】:

  • 好吧,我先试试看,如果我有更多问题再回帖
猜你喜欢
  • 2021-03-14
  • 1970-01-01
  • 1970-01-01
  • 2021-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-29
  • 2013-07-28
相关资源
最近更新 更多