【问题标题】:Using references (temporary variables) to manipulate LinkedList?使用引用(临时变量)来操作 LinkedList?
【发布时间】:2013-03-31 04:09:35
【问题描述】:
public void deleteItem(int target) 
{
    int index = 0;
    CarNode item = head;

    while(item != null)
    {

        CarNode next = (item.node).node;
        CarNode previous = item;

        if (index == target)
        {

            previous.setNode(next);

        }

    item = element.node
    index++;

    }
}

是的,我不知道我是否理解得很好,但是我听说你可以使用引用,而不必直接引用链表的对象来对链表进行更改。

一个节点包含Car对象和LinkedList的另一个元素的节点,对吧,所以引用基本上是一个克隆,指向与原始对象相同的对象,但是为什么原始被忽略并且引用被当我们修改引用的节点时优先于原来的?抱歉,这对我来说没有任何意义,为此我已经摸索了好几个小时。

【问题讨论】:

  • 我建议您查看什么是参考并重新表述您的问题。很难弄清楚你遇到了什么麻烦。 “当我们修改引用的节点时,引用优先于原始引用” 似乎没有多大意义,即使在您的代码上下文中也是如此。您可以编辑您的帖子并重新表述具体问题吗?
  • 通过引用我的意思是下一个和上一个,而不是项目。
  • 向我们展示CarNode...的定义,而且CarNode next = (item.node).node; 行似乎都包含错误(其中一个nodes 应该是nextand 也可能暗示下一个指针在存储在列表中的数据中,而不是在列表节点中,这将是一个设计问题。
  • 私家车节点{私家车车;私有 CarNode 节点; }
  • 你想要全班吗?因为它只有典型的 getter 和 setter。

标签: java linked-list nodes


【解决方案1】:

代码应如下所示:

public void deleteItem(int target) 
{
    int index = 0;
    CarNode item = head;
    CarNode prev = null;

    while(item != null)
    {
        if (index == target) {
            if (prev == null) {
                head = item.getNode();
                return; // We've removed the target.
            } else {
                prev.setNode(item.getNode());
                return; // We've removed the target.
            }
        }
        prev = item;
        item = item.getNode();
        index++;
    }
}

让我们分解一下:

int index = 0;
CarNode item = head;
CarNode prev = null;

我们需要两个变量:一个存储我们正在查看的元素,另一个存储前一个元素(一旦我们删除一个元素,我们将使用它重新连接列表)。首先,我们的当前是头部,而我们的前一个不存在。 index 会在我们达到目标时通知我们。

while(item != null)

我们想要迭代直到到达列表的末尾,由 null 节点标记。

if (index == target) {
    if (prev == null) {
        head = item.getNode();
        return; // We've removed the target.
    } else {
        prev.setNode(item.getNode());
        return; // We've removed the target.
    }
}

如果我们找到了目标,我们就会将其移除。如果previous 为null,那么目标是头部,所以我们将头部移动到第二个元素。否则,我们将前一个节点的引用设置为当前节点的引用,这会将当前节点从列表中删除。一旦我们移除目标,我们就完成了,所以我们返回。

prev = item;
item = item.getNode();
index++;

更新先前和当前节点。两者都向前移动一个节点。索引递增。

举个例子:

获取大小为 3 的列表。它看起来像这样:

我们现在调用list.deleteItem(1); 这将实例化一个prev 和一个next 节点。 next 指向第一个节点,prev 为空。

我们的目标是 1,所以我们移动到下一个节点。现在prev 指向next 曾经指向的对象,next 指向列表中的第二个对象(我们要删除的对象)。

我们通过将prev 节点的引用设置为next 节点的引用来删除它。

当我们从方法返回时,java 垃圾收集完成了它的工作,我们得到了:

多田!从列表中删除节点!

【讨论】:

  • 啊,我很难解析它,但是 return 到底是做什么的?
  • prev.node = item.node;和 previous.setNode(next);是等价的,对吧?
  • return 结束当前方法。至于previous.setNode(next),如果node 不公开,这实际上是正确的选择。我会编辑那个。等等。
【解决方案2】:
public void deleteItem(int target) 
{
    int index = 0;
    CarNode item = head;

    CarNode next = null;
    CarNode previous = null;

    // stop when the linked-list ends
    while(item != null)
    {
        // the tail has no next node
        if (item.node != null)
            next = item.node.node;
        else
            next = null;

        // if targetIndex exist, remove it
        //     "logically" from the linekd-list
        if (index == target)
        {
            previous.setNode(next);
            break;
        }

        // today is tomorrow's yesterday
        previous = item;
        item = item.node;
        index++;

    }
}

【讨论】:

  • 谢谢,所以有一些错误,但没有重大的逻辑错误。但是你为什么打破;?
  • 现在检查@user2089523,当我们删除目标时我做了break,因为目标与索引\唯一键相关联,如果它与一个值相关联,我们可以处理多次出现跨度>
  • @user2089523 Khaled 对break 的使用与我对return 的使用相同(至少在这种情况下):它只是用于在我们完成后退出方法。跨度>
  • @user2089523 Jimmy 使用return 是可以的,我个人建议避免使用return 来打破循环,return 在函数中间就像中止,使用break相反,如果将来修改该功能,应该提高可维护性..
  • @user2089523 好的。如果您愿意,您可以在我使用return 的地方替换break。它会做同样的事情。无论哪种方式。
猜你喜欢
  • 2017-03-04
  • 2016-08-12
  • 1970-01-01
  • 2018-09-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-20
  • 1970-01-01
  • 2015-09-05
相关资源
最近更新 更多