简体   繁体   English

Java,字符串的LinkedList。 按字母顺序插入

[英]Java, LinkedList of Strings. Insert in alphabetical order

I have a simple linked list. 我有一个简单的链表。 The node contains a string (value) and an int (count). 该节点包含一个字符串(值)和一个int(计数)。

In the linkedlist when I insert I need to insert the new Node in alphabetical order. 在插入时,在链表中,我需要按字母顺序插入新的Node。 If there is a node with the same value in the list, then I simply increment the count of the node. 如果列表中有一个具有相同值的节点,那么我只需增加该节点的计数即可。

I think I got my method really screwed up. 我想我的方法真的搞砸了。

 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);
                }
            }
        }      

    }

Ok so this is inserting all my strings, but not in alphabetical order. 好的,这是插入我所有的字符串,但不是按字母顺序。 Do you see any error? 看到错误了吗?

 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++;
    }

There are a few bugs with your code: 您的代码有一些错误:

  • Inserting at/before head actually needs to happen in two different scenarios: 实际上,需要在两种不同的情况下在head插入/插入head
    • If the list is empty, head becomes node 如果列表为空,则head成为node
    • If the list is not empty, but node is less than the first element, head also becomes node 如果列表不为空,但node小于第一个元素,则head也将成为node
      • In either case, node links to whatever head was pointing to before ( null or a real node), and head now points to node . 无论哪种情况, node链接到head之前指向的任何对象( null或实节点),而head现在指向node
  • If you're not inserting before head , then you must be inserting after some node. 如果您没有 head 之前插入,那么您必须某个节点之后插入。 We just need to find where this place is. 我们只需要找到这个地方在哪里。 There are two scenarios: 有两种情况:
    • node.getValue() > temp.getValue() , and node.getValue() < temp.getNext().getValue() node.getValue() > temp.getValue()node.getValue() < temp.getNext().getValue()
    • node.getValue() > temp.getValue() and temp.getNext() == null node.getValue() > temp.getValue()temp.getNext() == null
      • In either case, node is inserted between temp and temp.getNext() 无论哪种情况,都将node插入temptemp.getNext()

I suggest encapsulating the after insertion point search in its own function. 我建议在封装自身的功能插入点搜索。 That is, given the list and a value, it needs to return a node. 也就是说,给定列表和值,它需要返回一个节点。 If that node has the same value as the search value, then simply increment; 如果该节点与搜索值具有相同的值,则只需递增; otherwise, insert after . 否则,在之后插入。 As a special case, return null to indicate that the insertion point is before head . 作为一种特殊情况,返回null表示插入点 head 之前


In pseudocode, it'll look like this: 在伪代码中,它将如下所示:

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);

Update : I see that you've translated my pseudocode to Java, but for some reason you've omitted codes that deals with inserting before head when head is not empty. 更新 :我看到你翻译我的伪代码到Java,但由于某种原因你省略与之前插入涉及码head时, head不为空。 Specifically, you have inexplicably omitted this part: 具体来说,您莫名其妙地省略了这一部分:

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

and this part: 这部分:

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

Both of these are essential ; 两者都是必不可少的 ; it's what allows "A" to be inserted before the head in [ "B", "C", "D" ] . 这就是允许在[ "B", "C", "D" ]head前面插入"A"的原因。

You need to understand why they're important, and really ask yourself why you chose to remove them. 您需要了解它们为什么很重要,并真正问自己为什么选择删除它们。 Explain to us, to me, to yourself, why you did that; 向我们,对我,对自己解释为什么这么做; realize the mistake and learn from it. 意识到错误并从中学习。

For making this, instead of developing from scratch my own sorted list I would implement the Queue interface or extend the already existing PriorityQueue (or any other sorted collection that may apply better). 为此,我将实现Queue接口或扩展已经存在的PriorityQueue(或可能更适用的任何其他排序集合),而不是从头开始开发自己的排序列表。 I would define the Node class as an implementation of the Comparable interface or instantiate my queue with a Comparator instance and override the PriorityQueue add method to add the new Node only if another object is not already in the queue, incrementing the counter otherwise. 我将Node类定义为Comparable接口的实现,或者使用Comparator实例实例化我的队列,并重写PriorityQueue add方法以仅在队列中还没有另一个对象的情况下添加新的Node,否则增加计数器。 If using java >5.0 for type safety I would use generic to allow just Node objects in the Queue. 如果使用Java> 5.0进行类型安全,我将使用泛型来仅允许Queue中的Node对象。

I think you want to use one of Multiset implementations from Google Collections. 我认为您想使用Google收藏夹中的一种Multiset实现。

A Multiset works similar to a Set, but allows for duplicates (and counts them!). 多重集的工作原理类似于集合,但是允许重复(并计算重复!)。 Look at TreeMultiset : 看一下TreeMultiset

A multiset which maintains the ordering of its elements, according to either their natural order or an explicit Comparator. 根据元素的自然顺序或显式Comparator保持其元素顺序的多重集。

Without seeing the complete code it's hard to do debugging. 没有完整的代码,很难进行调试。 I think the problem is that you set 我认为问题在于

 Node temp = head; 

before the loop, but you need to reassign temp while while traversing the list to the current element. 在循环之前,但在将列表遍历到当前元素时需要重新分配temp In this case you continue to compare against head . 在这种情况下,您将继续与head比较。

  • You've taken care of the case when the list is initially empty. 您已经处理了list最初为空的情况。 You should also take care of the special case when the new node goes at be beginning of the list. 当新节点位于列表的开头时,您还应注意特殊情况。 If your list is B->C->D and you are inserting A . 如果您的列表是B->C->D并且您要插入A
  • Its good to set node.next to null (If not already done). 最好将node.next设置为null (如果尚未完成)。 So that if the node gets inserted at the end, we have null as the next of the last node. 这样,如果该节点插入到末尾,则最后一个节点的下一个null
  • You need to update the temp to move to the next node if no insertion is possible. 如果无法插入,则需要更新临时节点的温度。 So you are missing a temp = temp.next; 因此,您缺少temp = temp.next;

Since this is homework I'm not going to give you any source code. 由于这是家庭作业,因此我不会提供任何源代码。 There is one big issue I see with the code: 我在代码中看到一个大问题:

Suppose your list already has two distinct items, and you're inserting a new item. 假设您的列表已经有两个不同的项目,并且您要插入一个新项目。 In your code, you are checking whether node is greater than head , and if so inserting it immediately after, ignoring the rest of the items in the list. 在您的代码中,您正在检查node是否大于head ,如果是,则立即将其插入之后,忽略列表中的其余项。

You code do something like this. 您编写的代码是这样的。 There are some missing details which you can fill in yourself. 您可以填写一些遗漏的详细信息。

  1. If list is empty, set head = node , head->next = NULL , and you're done. 如果list为空,则设置head = nodehead->next = NULL ,就可以完成了。

  2. Otherwise if node->value < head->value , set node->next = head, head = node . 否则,如果node->value < head->value ,则设置node->next = head, head = node

  3. Otherwise, if node->value == head->value , head->count++ ; 否则,如果node->value == head->valuehead->count++ ;

  4. Otherwise, set tmp = head . 否则,设置tmp = head While tmp->next->value < node->value , set tmp=tmp->next . tmp->next->value < node->value ,设置tmp=tmp->next (check for nulls!). (检查是否为空!)。

  5. If tmp->next == NULL , (ie you reached end of list) then set tmp->next = node , and you're done. 如果tmp->next == NULL ,(即您到达列表的末尾),则设置tmp->next = node ,就可以了。

  6. Otherwise if tmp->next->value == node->value , (ie you reached a node with same value) tmp->next->count++ . 否则,如果tmp->next->value == node->value ,(即您到达具有相同值的节点) tmp->next->count++

  7. Otherwise, if node->next = tmp->next, tmp->next = node , and exit 否则,如果node->next = tmp->next, tmp->next = node并退出

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM