链接列表中的光标无明显变化值

时间:2012-03-31 08:27:21

标签: c++ singly-linked-list

修改

为简单起见: 我只想制作最基本的可能光标,只需通过我的列表而不改变任何方式/形状或形成我的“开始”。我仍然希望在我返回一些东西时开始改变,而不是之前。那么有可能制作一个指针开始,通过列表而不改变任何东西,除非在我想添加一个新节点的最后?

我可以通过一个不是“节点”的简单指针进入列表吗?

/修改

我有一个简单的(单一)链接列表作为我作业的一部分。当然,除此之外我还有很多事情要做,但是在我把清单拿出来后,一切都应该是前进的,但是我已经使用了C ++一段时间了(这是我用的是C ++)我的很多东西知道要么被遗忘了,要么已经过时了。我已经在python中编程了一段时间,但所有这些意味着我一直对指针在C ++中的工作方式感到沮丧。

我的问题是当我尝试将新节点添加到列表中时,我的光标表现异常,我将在下面解释:

编辑: 好的,我更改了:

Node *cursor;
cursor = new Node
cursor = begin;

fiasco,但结果是一样的,在声明游标之后并开始指向同一个内存位置(类似于:0x32ce8)。

/修改

Node *add_node (Node *begin,string type, int sum, int ap_nr) // begin is the first node in the list
{
    // if first node is dummy node

    if (begin->ap_nr == -1)
        {
            begin->type = type;
            begin->ap_nr = ap_nr;
            begin->sum = sum;
            begin->next = 0;
            return begin;
        }

    // else create new node and insert it in sorted position

   else
    {
        // EDIT:
        Node *cursor = begin; // Same problem

        //if node should be inserted before first node (begin)

        if (ap_nr <begin->ap_nr)
        {
            cursor->ap_nr = ap_nr;
            cursor->type = type;
            cursor->sum = sum;
            cursor->next = begin;
            return cursor;
        }

总是当我调试时,开始有一个类似的形式:0x32ce02,当我创建我的“光标”时它有一个非常不同的形式(也更长),但当我这样做:cursor = begin,然后光标变成这样的东西0x32df02。

然而问题是当我到达“if(ap_nr ap_nr)”然后绝对没有可行的原因光标变为:0x32ce02和“cursor - &gt; next = begin”确保无限循环。无论我添加多少个节点,这总是会发生,所以每当我打印列表时,它都是最后添加的节点的无限流。

我做错了吗?它是宣言还是主宰,创造?什么?

另外如果我有一个指针*从另一个模块中的某个地方开始,并且使用这个函数我会返回一个新的开始...应该可以正常工作,对吗?

P.S。我还要感谢一个简单的反制解决方案(如果我的方法不好,另一种方法就是这样做)

另外我应该指出我是如何制作我的清单的。它只是一个简单的节点链接:

struct Node {
    string type;
    int ap_nr;
    int sum;
    Node *next;
};

3 个答案:

答案 0 :(得分:2)

此代码:

cursor = new Node;
cursor = begin;

以下内容:

  • 在堆栈上创建新的Node对象
  • 将该对象的地址放在变量current
  • 立即使用begin包含的地址
  • 覆盖该地址

即。它所做的就是泄漏一个新的Nodecursorbegin之后指向同一事物。

这一行:

cursor->next = begin;

制作一个循环。 cursor->next == begin == cursor

删除cursor = begin;行,然后返回光标将执行您想要的操作。使用new Node创建的节点将成为列表的新头部,begin在函数开头指向的节点将成为该列表中的第二个节点。

现在,当您想要遍历(不添加)该列表时,您可以执行以下操作:

 Node *cursor = begin; // assuming begin is the head of your list
 while (cursor != 0) {
    // process this node
    cursor = cursor->next;
 }

这将访问列表中的每个节点,假设您已正确构建它。

一些注意事项:

  • 调用此函数的代码应该类似于:

    list = add_node(list, ...);
    

    如果你没有,那就得不到你想要的。

  • 如果您在begin中看到的地址非常new返回的地址不同,那么您可能会做错事,即{{ 1}}可以指向堆栈地址。不要将堆栈中的对象放在列表中,请确保使用begin分配它们。 (如果new指向一个全局静态变量,那很好 - 但请确保你没有begin它。

  • 除非你实际上需要一个虚拟节点,否则我建议你删除它 - 这会使你的delete函数变得比它需要的更复杂。

这是一个如何在没有特殊虚拟节点(不完整代码)的情况下执行此操作的框架:

add_node

并使用它:

Node *add_node(Node *list, ...)
{
  Node *new_node = new Node;
  new_node->next = list;
  // fill in other properties
  return new_node;
}

答案 1 :(得分:1)

    Node *cursor;
    cursor = new Node;
    cursor = begin;

在这里准确理解你在使用这三条线做什么 - 可能还有比实际意识更多的事情。

  • 在第一行,您声明一个名为 cursor 的新变量 - 此变量是指针对象的名称,其类型为 Node * 。 (简单来说,Node *表示“指向 Node ”的指针) 存储在指针对象中的数据类型只是数字积分数据,恰好代表存储器中的地址。指针对象与任何其他类型的整数对象实际上没有什么不同 (注意“变量”和“对象”之间的区别 - 对象是存储在内存中的内容,例如数字/字符/内存地址,变量是 名称 < / strong>对象)

  • 在第二行,发生了两件事 - 首先为 Node 对象分配内存,并在分配的内存中构造一个新的 Node 对象 - 这个内存没有变量名,它只是一个免费商店对象(这是新节点的工作原理的简短版本),然后使用=运算符(赋值运算符)来存储地址值(a 游标变量中新分配的节点对象的数字 存储新Node对象的地址值后,访问新分配的Node对象的唯一方法是通过游标变量名。

  • 在第三行,您会立即覆盖游标变量存储的值;它不是存储新节点的地址数据,而是存储另一个对象的地址(从另一个指针变量复制的另一个对象的地址,名为 begin )。这会立即导致新分配的节点被“泄露”。

我试图提出的观点(我相信你可能没有意识到)是在这三行代码中可能有四个不同的对象(即“内存中的项目”)需要考虑。其中两个是名为 cursor begin 的指针对象(整数),另外两个是自由存储对象(节点),它们没有名称,但可以使用地址访问指针对象存储的值。

你可能会发现有很多链接值得一读:

答案 2 :(得分:1)

指针cursorbegin指向相同的内存位置,因为您明确这样说:Node* cursor = begin; 字面上表示“创建一个名为{{的指针变量” 1}}指向与cursor相同的位置。“所以毫不奇怪。

修改:根据错误的猜测删除了建议,并将其更改为更适用的建议

从评论中,我现在明白你想在某个位置插入一个节点,以便字段begin在结果列表中增加,假设它最初在增加(如果它仍然不对,请清楚说明你想要的东西。)

对于这种情况,ap_nr的初始化当然是正确的。但是, 正确无法将对象cursor指向:您希望在该节点之前插入节点。但为此你必须做出一些改变:

首先,您需要另一个指针变量,该变量包含指向新创建节点的指针,如

cursor

然后你必须将那个节点插入到列表中。也就是说,代替Node* new_node = new Node; 等,你必须使用cursor->ap_nr=ap_nr;等。此外,它后面的节点当然列表的第一个节点(指向new_node->ap_nr=ap_nr;)但你找到的那个(由first指出)。

但是,现在您遇到了一个问题:您必须将新节点插入到列表中,这意味着您必须修改上一个节点的current指针(但要点不是next,而是新创建的节点!)。但是你没有更多指向前一个节点的指针,因为你的列表是单链接的,也就是说,你没有从找到的元素到前一个元素的指针。但要插入元素,您来更改begin

所拥有的是指向 next 节点的指针。因此,更好的策略是让您的next指向之前的节点,然后始终使用cursor代替cursor->next(移动{{1}时除外}, 当然)。这样你可以之后设置cursor,写下cursor

您的代码中缺少的其他内容是new_node->next不为空的检查(它将在列表的末尾)和其他代码实际移动cursor->next = new_node;向前(属于内部current的{​​{1}}部分。

实际上我现在注意到您的块没有关闭,因此您的实际代码中可能会有前进的代码。

最后,提出一些一般建议:如果模块化函数代码,那么编写代码可能会更容易:有一个函数在给定函数之后插入一个新节点(只更改{{1}指针,并返回一个指向新插入的代码的指针),有另一个函数来查找应该插入新节点的节点,并让你的函数cursor只调用其他的功能。这样,在每个函数中,您可以专注于其中一个子问题。