链接列表的代码检查add(i,x)方法

时间:2011-07-08 19:49:25

标签: java data-structures linked-list implementation abstract-data-type

我目前正试图了解ADT实现,特别是链接列表的实现(我使用Java 5来实现这一点)。

我有两个问题:

(1)我为add(i,x)写的这个实现是否正确有效?

public void add(int i, Object x) {

    // Possible Cases:
    //
    //     1. The list is non-empty, but the requested index is out of
    //        range (it must be from 0 to size(), inclusive)
    //
    //     2. The list itself is empty, which will only work if i = 0
    //
    // This implementation of add(i, x) relies on finding the node just before
    // the requested index i.

    // These will be used to traverse the list
    Node currentNode = head;
    int indexCounter = 0;

    // This will be used to mark the node before the requested index node
    int targetIndex = i - 1;

    // This is the new node to be inserted in the list
    Node newNode = new Node(x);

    if (currentNode != null) {

        while (indexCounter < targetIndex && currentNode.getNext() != null) {

            indexCounter++;
            currentNode = currentNode.getNext();
        }

        if (indexCounter == targetIndex) {

            newNode.setNext(currentNode.getNext());
            currentNode.setNext(newNode);

        } else if (i == 0) {

            newNode.setNext(head);
            head = newNode;
        }

    } else if (i == 0) {

        head = newNode;
    }     
}

(2)我发现这种方法很难实施。说实话,我花了好几天。这很难承认,因为我喜欢编程并且在几种语言和平台中考虑自己处于中级水平。我从13岁开始编程(苹果IIc上的Applesoft BASIC!)并拥有CS学位。我目前是一名软件测试人员,并计划在某些时候成为开发人员。所以我的问题的第二部分是:我是在欺骗自己,这是我擅长的工作类型,还是几乎每个人都发现这种问题具有挑战性?有些东西告诉我,即使是经验丰富的开发人员,面对实施这种方法,也会发现它具有挑战性。

感谢您对第二部分的反馈和建议。

3 个答案:

答案 0 :(得分:4)

我认为这是一个好的开始......一些建议:

  • 我认为你的currentNode == null案例应该在开始时处理,然后返回。我不喜欢“if(currentNode!= null)”
  • 中的所有内容
  • 您应该在某个地方跟踪链接列表的大小,以便您可以轻松检查我是否&gt; list_size
  • 我不打算将“i-1”重命名为targetIndex
  • 在您需要
  • 之前不要创建newNode
  • 编写单元测试,然后您可以轻松更改内容,并知道您的实现仍然有效。
  • 不要简单地忽略非法论点。如果索引i&lt; 0或&gt;大小,抛出IllegalArgumentException或IndexOutOfBoundsException(感谢@JB Nizet)

答案 1 :(得分:1)

我建议你先写一些单元测试。特别是,尝试在列表末尾添加一个节点,看看会发生什么。 ;)

我认为大多数开发人员会发现编写LinkedList很困难,因为a)有很多方法可以实现它,而b)它不是你通常自己写的东西。您通常会使用其中一个有效的现有实现。 ;)

作为一项练习,这是一个好主意。我建议你阅读内置LinkedList的代码,并思考如何以不同的方式做事。例如如何简化它可能是一个开始。

答案 2 :(得分:1)

此实现效率不高,但这部分是因为操作add(i,x)在普通链表上效率不高。链接列表不适用于随机访问。我想如果你创建了一个哈希表或其他东西,你可能会在列表中创建一个更有效的索引。例如,考虑Map。然后你的map.ContainsKey(i-1)map.get(i-1)的插入例程(显然有i = 0的特殊情况)你立即得到了先前的索引。如果我!= 0并且您没有该索引的密钥,那么您就会立即知道错误。如果没有太多的冲突,Map理论上是O(1),所以这比每次迭代列表更有效(但是以某些磁盘空间为代价)。这又真的取决于因为纯链表对于add(i,x)来说效率不高。

我不是特别喜欢这种方法,因为如果你说添加(32,x)并且列表中只有15个项目它会无声地失败。它应该至少抛出一个异常,返回false或某些东西,以表明插入失败。

你也可以合并两个特例。假设newNode.setNext(NULL)有效,你只需要检查i == 0,然后你可以执行newNode.setNext(head),head = newNode,因为列表是否为空,这是否有效。如果列表为空,则将下一个指针设置为NULL。这至少消除了重复的代码。

花一个星期看起来确实有点多,但是有些人在首先围绕指针(javaspeak中的类引用......)时遇到了很多麻烦。你最终得到了一些工作的事实是朝着正确方向迈出的一大步。