【问题标题】:Inserting into sorted linked list - Java插入排序链表 - Java
【发布时间】:2015-07-10 01:00:10
【问题描述】:

我需要维护一个排序的数据结构,从中可以删除和添加项目。为此,我决定选择一个链表。每个数据项都包含一个字母和一些数字,例如: A1480、A1488、B1297、C3119 这些需要按顺序维护。我已经为它编写了代码,它首先在已经排序的链表中找到需要添加新项目的位置,然后将项目添加到正确的位置,从而维护排序的链表。它可以工作,但有些项目放错了位置,我不知道如何修复我的代码。我知道最后一个循环有问题,但我不确定它是什么。

    public static void main(String[] args) {
    list = new LinkedList<String>();
    add("C3138");
    add("C3119");
    add("A1488");
    add("A1480");
    add("A1517");
    add("B1297");
    add("C2597");
    add("B1356");
    add("C9000");
    add("C3517");
    add("C3729");
    add("C1729");
    add("B1729");
}
 public static void add(String value) {
    // Integer value form the string passed into the method
    int valueInt = getInt(value);

    // If linked list is empty, add value and return from method
    if (list.size() == 0) {
        list.add(value);
        return;
    }

    // Compare this item to be added to the first item
    int firstNode = getInt(list.get(0));
    if (list.get(0).charAt(0) > value.charAt(0) 
            || (list.get(0).charAt(0) == value.charAt(0) && firstNode > valueInt)){
        list.add(0, value);
        return;
    }

    // Compare this item to the last item
    int lastNode = getInt(list.get(list.size() - 1));
    if (list.get(list.size() - 1).charAt(0) < value.charAt(0) || 
            (list.get(list.size() - 1).charAt(0) == value.charAt(0) && lastNode < valueInt)) {
        list.add(list.size(), value);
        return;
    }
    // add the inbetween items
    int i = 1;
    int tempInt = getInt(list.get(i));
    while ((list.get(i).charAt(0) < value.charAt(0)
            || ((list.get(i).charAt(0) == value.charAt(0)) && (valueInt < tempInt)) && i < list.size())) {

        tempInt = getInt(list.get(i));
        i++;
    }
    list.add(i, value);
} 
 public static int getInt(String item) {
    return Integer.parseInt(item.replaceAll("\\D", ""));
}

下面的这段代码给了我输出:

[A1480、A1517、A1488、B1729、B1297、B1356、C1729、C3729、C3517、C2597、 C3119、C3138、C9000]

正如您所见,开始和结束之间的某些值放错了位置,但开始和结束值是正确的。请帮忙

【问题讨论】:

  • 试试这个 :: (list.get(i).charAt(0) &lt; value.charAt(0) || ((list.get(i).charAt(0) == value.charAt(0)) &amp;&amp; (valueInt &gt; tempInt)) &amp;&amp; i &lt; list.size()) 我之前有点困惑.. :P 只是改变了你的比较符号valueInt &gt; tempInt
  • LinkedList 上使用.get()...如果列表变大的话会很慢...

标签: java sorting insert linked-list


【解决方案1】:

尝试这样做 :: 将你的最后一个 while 条件更改为 this::

(list.get(i).charAt(0) &lt; value.charAt(0) || ((list.get(i).charAt(0) == value.charAt(0)) &amp;&amp; (valueInt &gt; tempInt)) &amp;&amp; i &lt; list.size())

您当前正在做的是增加您的i,除非您达到小于varInt 的值tempInt,这就是为什么在A1488 之前插入A1517。 你应该增加你的i直到tempInt的值小于`varInt,这样你就达到了当前元素可以达到的最大位置。我希望我能说清楚。

工作代码 Ideone 链接 :: http://ideone.com/ZafWEO

此外,最好在访问链表项之前检查i 的值。所以,条件应该是这样的::

(i &lt; list.size() &amp;&amp; (list.get(i).charAt(0) &lt; value.charAt(0) || ((list.get(i).charAt(0) == value.charAt(0)) &amp;&amp; (valueInt &gt; tempInt)))

【讨论】:

    【解决方案2】:

    看看Why is there no SortedList in Java?

    如果您的值是唯一的,您可以使用TreeSet。一般来说,如果你想要一个排序的集合,你可能不想从 LinkedList 开始。

    【讨论】:

    • 我以前从未使用过treeSet,但根据我的研究,它实现了Set接口,所以它不能有多个相同的元素,但我的程序可以有副本。而且这个问题也是我正在做的事情的一个子问题。我需要根据不同的属性对对象进行排序
    • 从提供的信息中很难准确判断您的需求是什么,请尝试另一个 SO 问题中的解决方案之一。最简单的事情可能是使用 ArrayList 并在添加数据后需要对其进行排序时对其进行排序。对几乎排序的列表进行排序非常快。您还可以使用Collections.binarySearch 实现您尝试实现的方法,如果它没有找到该元素,它将为您提供一个插入索引。但同样,您很有可能只需根据需要进行排序。
    【解决方案3】:

    你为什么不使用Comparable

    滚动到底部查看实现的类 Comparable

    这是对您问题的回答:

    private static LinkedList<SuperRosie> list;
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        list = new LinkedList<SuperRosie>();
    
        add("C3138");
        add("C3119");
        add("A1488");
        add("A1480");
        add("A1517");
        add("B1297");
        add("C2597");
        add("B1356");
        add("C9000");
        add("C3517");
        add("C3729");
        add("C1729");
        add("B1729");
    
        for (int i = 0; i < list.size(); i++)
            System.out.println(list.get(i).getValue());
    
    }
    
    private static void add(String value) {
        SuperRosie myNewRs = new SuperRosie(value);
        int listSize = list.size();
        // If linked list is empty, add value and return from method
        if (listSize == 0) {
            list.add(myNewRs);
            return;
        }
    
        // Compare this item to be added to the first item
        SuperRosie element = list.getFirst();
        if (myNewRs.compareTo(element) <= 0) {
            list.addFirst(myNewRs);
            return;
        }else{
            if(listSize == 1){
                list.addLast(myNewRs);
                return;
            }
        }
    
        // Compare this item to the last item
        element = list.getLast();
        if (myNewRs.compareTo(element) >= 0) {
            list.addLast(myNewRs);
            return;
        }else{
            if(listSize == 1){
                list.addFirst(myNewRs);
                return;
            }
        }
    
        // add the inbetween items
        int compare = 0;
        for (int i = 1; i < listSize; i++) {
            element = list.get(i);
            compare = myNewRs.compareTo(element);
            if (compare <= 0) {
                list.add(i, myNewRs);
                break;
            }
        }
    }
    

    对可比链表进行排序的示例:

    public class Main {
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            LinkedList<SuperRosie> list = new LinkedList<SuperRosie>();
            list.add(new SuperRosie("C3138"));
            list.add(new SuperRosie("C3119"));
            list.add(new SuperRosie("A1488"));
            list.add(new SuperRosie("A1480"));
            list.add(new SuperRosie("A1517"));
            list.add(new SuperRosie("B1297"));
            list.add(new SuperRosie("C2597"));
            list.add(new SuperRosie("B1356"));
            list.add(new SuperRosie("C9000"));
            list.add(new SuperRosie("C3517"));
            list.add(new SuperRosie("C3729"));
            list.add(new SuperRosie("C1729"));
            list.add(new SuperRosie("B1729"));
            Collections.sort(list);
            for(SuperRosie rs : list)
                System.out.println(rs.getValue());
        }
    }
    

    SuperRosie.java 类从 Comparable 实现

    public class SuperRosie implements Comparable<SuperRosie> {
        private String value;
    
        public SuperRosie(String value) {
            this.value = value;
        }
    
        public String getValue() {
            return value;
        }
    
        @Override
        public int compareTo(SuperRosie arg0) {
            int compareFirst = this.value.charAt(0) - arg0.value.charAt(0);
            return compareFirst == 0 ? (Integer.parseInt(this.value.replaceAll(
                    "\\D", "")) - Integer
                    .parseInt(arg0.value.replaceAll("\\D", ""))) : compareFirst;
        }
    
        public static Comparator<SuperRosie> FruitNameComparator = new Comparator<SuperRosie>() {
    
            public int compare(SuperRosie rosie1, SuperRosie rosie2) {
    
                String rosieValue1 = rosie1.value.toUpperCase();
                String rosieValue2 = rosie2.value.toUpperCase();
    
                // ascending order
                return rosieValue1.compareTo(rosieValue2);
    
                // descending order
                //return rosieValue2.compareTo(rosieValue1);
            }
    
        };
    }
    

    【讨论】:

    • 排序插入应该比在大型数据集中追加然后排序要快得多。
    【解决方案4】:

    根据性能问题,我建议另一种性能解决方案。

    private static LinkedList<String> list;
    public static void main(String[] args) {
        list = new LinkedList<>();
        add("C3138");
        add("C3119");
        add("A1488");
        add("A1480");
        add("A1517");
        add("B1297");
        add("C2597");
        add("B1356");
        add("C9000");
        add("C3517");
        add("C3729");
        add("C1729");
        add("B1729");
        for (int i = 0; i < list.size(); i++)
            System.out.println(list.get(i));
    }
    
    private static void add(String value){
        // don't check empty array, check to add in the first, last element.
        // Each case, it works but when array has more than 1 element, 
        // so the above check are useless, run will cost memory, steps,....
        // So don't, please do just the following
        int insertIndex = 0;
        for(String element : list){
            if(compare(value, element) <= 0){ // or whatever compare way you want
                break;
            }else{
                insertIndex+=1;
            }
        }
        list.add(insertIndex, value);
    }
    
    private static int compare(String value1, String value2){
        int compareFirst = value1.charAt(0) - value2.charAt(0);
        return compareFirst == 0 ? (Integer.parseInt(value1.replaceAll(
                "\\D", "")) - Integer
                .parseInt(value2.replaceAll("\\D", ""))) : compareFirst;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-03-15
      • 2011-04-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-16
      相关资源
      最近更新 更多