【问题标题】:Java, LinkedList of Strings. Insert in alphabetical orderJava,字符串的链表。按字母顺序插入
【发布时间】:2010-04-24 09:41:06
【问题描述】:

我有一个简单的链表。该节点包含一个字符串(值)和一个整数(计数)。

在我插入时,我需要在链表中按字母顺序插入新节点。如果列表中存在具有相同值的节点,那么我只是增加节点的计数。

我觉得我的方法真的搞砸了。

 public void addToList(Node node){
        //check if list is empty, if so insert at head
        if(count == 0 ){
            head = node;
            head.setNext(null);
            count++;
        }
        else{
            Node temp = head;
            for(int i=0; i<count; i++){
                //if value is greater, insert after
                if(node.getItem().getValue().compareTo(temp.getItem().getValue()) > 0){
                    node.setNext(temp.getNext());
                    temp.setNext(node);                   
                }
                //if value is equal just increment the counter
                else if(node.getItem().getValue().compareTo(temp.getItem().getValue()) == 0){
                    temp.getItem().setCount(temp.getItem().getCount() + 1);
                }
                //else insert before
                else{
                    node.setNext(temp);
                }
            }
        }      

    }

好的,这是插入我所有的字符串,但不是按字母顺序。有没有发现错误?

 public Node findIsertionPoint(Node head, Node node){
        if( head == null)
            return null;

        Node curr = head;
        while( curr != null){
            if( curr.getValue().compareTo(node.getValue()) == 0)
                return curr;
            else if( curr.getNext() == null || curr.getNext().getValue().compareTo(node.getValue()) > 0)
                return curr;
            else
                curr = curr.getNext();
        }

        return null;
    }

    public void insert(Node node){
        Node newNode = node;
        Node insertPoint = this.findIsertionPoint(this.head, node);
        if( insertPoint == null)
            this.head = newNode;
        else{
            if( insertPoint.getValue().compareTo(node.getValue()) == 0)
                insertPoint.getItem().incrementCount();
            else{
                newNode.setNext(insertPoint.getNext());
                insertPoint.setNext(newNode);
            }
        }
        count++;
    }

【问题讨论】:

  • @user69:我看到您已将我的伪代码改编为 Java。到目前为止做得很好,但是由于某种原因,当head 不是null 并且插入的值小于head 的值时,您仍然忽略了在head 之前插入的逻辑。请再次查看我的伪代码。如果你不明白,问。一切都在那里是有原因的。

标签: java insert linked-list


【解决方案1】:

您的代码存在一些错误:

  • head 之前/之前插入实际上需要在两种不同的情况下发生:
    • 如果列表为空,head 变为 node
    • 如果列表不为空,但node小于第一个元素,head也变成node
      • 在任何一种情况下,node 都链接到 head 之前指向的任何内容(null 或真实节点),head 现在指向 node
  • 如果您没有插入之前 head,那么您必须插入之后 某个节点。我们只需要找到这个地方在哪里。有两种情况:
    • node.getValue() &gt; temp.getValue()node.getValue() &lt; temp.getNext().getValue()
    • node.getValue() &gt; temp.getValue()temp.getNext() == null
      • 在任何一种情况下,node 都插入在 temptemp.getNext() 之间

我建议将 after 插入点搜索封装在自己的函数中。也就是说,给定列表和值,它需要返回一个节点。如果该节点与搜索值具有相同的值,则只需递增;否则,在 之后插入。作为特例,返回null 表示插入点在之前 head


在伪代码中,它看起来像这样:

FUNCTION findInsertionPoint(Node head, V value) RETURNS Node
  // return null if value needs to be inserted before head
  IF head == null OR value < head.getValue()
     RETURN null;

  // otherwise, either return a node with the given value,
  // or return a node after which value should be inserted
  Node curr = head;
  REPEAT
     IF curr.value == value
        RETURN curr;
     ELSEIF curr.getNext() == null OR curr.getNext().getValue() > value
        RETURN curr;
     ELSE
        curr = curr.getNext();

PROCEDURE insert(V value) {
  Node newNode = NEW Node(value);
  Node insertPoint = findInsertionPoint(this.head, value);
  IF insertPoint == null // insert before head
     newNode.setNext(this.head);
     this.head = newNode;
  ELSE
     IF insertPoint.getValue() == value
        insertPoint.incrementCounter();
     ELSE // insert after insertPoint
        newNode.setNext(insertPoint.getNext());
        insertPoint.setNext(newNode);

更新:我看到您已将我的伪代码翻译成 Java,但由于某种原因,当 head 不为空时,您省略了处理在 head 之前插入的代码。具体来说,你莫名其妙地省略了这部分:

IF head == null OR value < head.getValue()
             // ^^^^^^^^^^^^^^^^^^^^^^^^^^

这部分:

IF insertPoint == null 
   newNode.setNext(this.head); // <<<<<<<<<<<
   this.head = newNode;

这两个都是必不可少的;它允许在[ "B", "C", "D" ] 中的head 之前插入"A"

您需要了解为什么它们很重要,并且真的问问自己为什么选择删除它们。向我们、向我、向你自己解释你为什么这样做;意识到错误并从中吸取教训。

【讨论】:

  • 嘿,你是对的......实际上我错过了一行代码......不知道我为什么这样做,没有注意。
  • @user69:充分利用伪代码,即学习:(i)如何解决所有“不同”的场景,看看它们是否可以简化为几个(ii)如何自己封装辅助逻辑,可测试和可重用。
【解决方案2】:

为了实现这一点,我不会从头开始开发自己的排序列表,而是实现 Queue 接口或扩展已经存在的 PriorityQueue(或任何其他可能更适用的排序集合)。我会将 Node 类定义为 Comparable 接口的实现,或者使用 Comparator 实例实例化我的队列,并覆盖 PriorityQueue add 方法以仅在队列中没有另一个对象时添加新节点,否则增加计数器。如果使用 java >5.0 来保证类型安全,我会使用泛型来只允许队列中的 Node 对象。

【讨论】:

    【解决方案3】:

    我认为您想使用 Google Collections 中的 Multiset 实现之一。

    Multiset 的工作方式类似于 Set,但允许重复(并计算它们!)。看TreeMultiset

    一个多重集,它维护 其元素的排序,根据 他们的自然秩序或 显式比较器。

    【讨论】:

    • 不,我想创建自己的链表
    • @user69514: 这不是最好的主意。但无论如何,如果您想自己维护它,请使用标准Map,其中每个key 是您的字符串之一,value 是一个柜台。 LinkedList 可能是维护您所描述的数据结构的最糟糕的选择。
    • 这是功课,他要自己写list实现,就这么简单。
    【解决方案4】:

    如果没有看到完整的代码,就很难进行调试。 我认为问题在于你设置了

     Node temp = head; 
    

    在循环之前,但是您需要在遍历列表到当前元素时重新分配temp。在这种情况下,您将继续与head 进行比较。

    【讨论】:

      【解决方案5】:
      • 您已经处理好这个案子了 list 最初是空的。你 还应该照顾特殊的 新节点位于 be 的情况 列表的开头。如果你的清单 是B-&gt;C-&gt;D,而您正在插入A
      • 最好将node.next 设置为null(如果尚未完成)。所以 如果节点被插入 最后,我们将null 作为下一个 最后一个节点。
      • 您需要更新温度才能移动 如果没有插入,则到下一个节点 可能的。所以你错过了temp = temp.next;

      【讨论】:

        【解决方案6】:

        由于这是家庭作业,我不会给你任何源代码。我看到代码存在一个大问题:

        假设您的列表已经有两个不同的项目,并且您正在插入一个新项目。在您的代码中,您正在检查 node 是否大于 head,如果是,则立即插入它,忽略列表中的其余项目。

        你的代码做这样的事情。有一些遗漏的细节可以自己填写。

        1. 如果列表为空,设置head = nodehead-&gt;next = NULL,就完成了。

        2. 否则如果node-&gt;value &lt; head-&gt;value,则设置node-&gt;next = head, head = node

        3. 否则,如果node-&gt;value == head-&gt;valuehead-&gt;count++

        4. 否则,设置tmp = head。当tmp-&gt;next-&gt;value &lt; node-&gt;value 时,设置tmp=tmp-&gt;next。 (检查空值!)。

        5. 如果tmp-&gt;next == NULL,(即您到达列表末尾)然后设置tmp-&gt;next = node,您就完成了。

        6. 否则如果tmp-&gt;next-&gt;value == node-&gt;value,(即您到达具有相同值的节点)tmp-&gt;next-&gt;count++

        7. 否则,如果node-&gt;next = tmp-&gt;next, tmp-&gt;next = node,则退出

        【讨论】:

          猜你喜欢
          • 2019-01-25
          • 2019-09-23
          • 2018-08-01
          • 1970-01-01
          • 1970-01-01
          • 2013-09-17
          • 1970-01-01
          • 2012-10-21
          • 1970-01-01
          相关资源
          最近更新 更多