繁体   English   中英

如何排序ArrayList <String> 包含整数?

[英]How do I sort an ArrayList<String> that contains integers?

我制作了一个单词计数器二进制搜索树,当输入一个以上单词时,它会增加一个单词的计数。 单词和单词计数都保存在树中。 我试图先打印出计数最高的单词,然后按降序排列。

为了执行此操作,我将BST转换为ArrayList,但现在似乎无法弄清楚如何通过减少计数顺序对列表进行排序。 这是我到目前为止的内容:

public ArrayList<String> toArray() {
  ArrayList<String> result = new ArrayList<String>();
  toArrayHelp(root, result);
  Collections.sort(result);
  return result;
}

private void toArrayHelp(Node<String, Integer> node, ArrayList<String> result) {
  if (node == null) {
      return;
  }
  toArrayHelp(node.left, result); 
  result.add("count: " + String.valueOf(node.count) + "/t word: " + node.data); 
  toArrayHelp(node.right, result); 
}

我已经尝试过Collections.sort(),但是它不是按字符串而是仅按单词排序。

  • 遍历树,从所有元素生成List<Node<String, Integer>>
  • List排序,按节点的int部分排序
  • 创建一个仅保留字符串的列表,顺序相同

您构建输出字符串的时间太早:您需要首先使用count作为键对列表进行排序,然后打印结果。 您可以制作一个包含结果的简单包装器:

public class WordCount implements Comparable<WordCount>{
   private String word;
   private Integer count;

   //constructors, getters, setters etc..

   @Override
   public int compareTo(WordCount other) {
       return Integer.compare(this.count, other.count);
   }

}

并在遍历树时构造一个List<WordCount> list 完成后,您只需要按Collections.sort(list)对列表进行排序并打印结果即可。

1.对于DESC订单,请使用Collections.sort(result, Collections.reverseOrder()); 因为默认的排序顺序是ASC。

2.确保count的字符串表示长度相同。 否则,字典顺序假定11 <2:

List<String> list = Arrays.asList("11", "1", "2");
Collections.sort(list, Collections.reverseOrder());
System.out.println(list); // output: [2, 11, 1]

但是,如果数字具有相同的长度,则可以正常工作:

List<String> list = Arrays.asList("11", "01", "02");
Collections.sort(list, Collections.reverseOrder());
System.out.println(list); // output: [11, 02, 01]

如何添加前导零,可以在这里https://stackoverflow.com/a/275715/4671833找到。 应该是这样的结果result.add("count: " + String.format("%02d", String.valueOf(node.count)) + "/t word: " + node.data);

两点要点:让名称选择和格式成为您的朋友! 您需要养成选择简单且富有表现力的变量名的习惯,并保持代码的格式整齐。

让我们从明确的步骤开始:

(1)有单词数据源,表示为节点树。 为了避免过多的细节,让我们设置节点类型的重要细节,并使用getter使节点树可用。

值得一提的重要细节是,节点打算保留在具有不同键值的已排序二叉树中,为此,任何左节点的值均严格小于该节点的值,而任何右节点的值均小于该节点的值。节点严格大于节点的值。 这具有重要的结果,即节点的左子树的值都严格小于该节点的值,并且右子树的值同样均严格大于该节点的值。

public class Node<K, V> {
  public K key;
  public V value;

  public Node<K, V> left;
  public Node<K, V> right;

  public Node(K key, V value) {
    this.key = key;
    this.value = value;
  }
}

public Node<String, Integer> getRootNode() {
    // Undetailed ...
}

(2)需要三个主要操作:将树的节点收集到列表中的操作,对该列表进行排序的操作以及显示排序后的列表的操作:

public List<Node<String, Integer>> flatten(Node<String, Integer> rootNode) {
    // Undetailed ...
}

public void sort(List<Node<String, Integer>> nodes) {
    // Undetailed ...
}

public void print(List<Node<String, Integer>> nodes) {
    // Undetailed ...
}

(3)例如,如下所示:

public void tester() {
  Node<String, Integer> rootNode = getRootNode();
  List<Node<String, Integer>> flatNodes = flatten(rootNode);
  sort(flatNodes);
  print(flatNodes)l
}

(4)剩下的就是详细介绍几种方法。 我们从“展平”开始。 这将被实现为递归操作。 并且,由于为平面列表传递存储更简单,因此该方法将分为两部分,一部分分配存储,另一部分进行递归处理。 这种传递存储集合的技术是此类处理的典型方法。

'flatten'利用节点相对于节点的左节点和节点的右节点的排序属性:'flatten'将左子树的所有值添加到平面节点列表中,然后是节点,然后是节点右子树的所有值。

public List<Node<String, Integer>> flatten(Node<String, Integer> rootNode) {
    List<Node<String, Integer>> flatNodes = new ArrayList<Node<String, Integer>>();
    flatten(rootNode, flatNodes);
    return flatNodes;
}

public void flatten(Node<String, Integer> node, List<Node<String, Integer>> flatNodes) {
   if ( node == null ) {
       return;
   }
   flatten(node.left, flatNodes);
   flatNodes.add(node);
   flatten(node.right, flatNodes);
}

(5)出于清晰的考虑,可以通过移动null检查来使之更加有效。 对于完全平衡的树,这将避免约2/3的递归调用,这是相当不错的减少。 这仅在节点数很高时才重要。 无论如何,一个好的编译器很可能会以这种方式转换代码。

public List<Node<String, Integer>> flatten(Node<String, Integer> rootNode) {
    List<Node<String, Integer>> flatNodes = new ArrayList<Node<String, Integer>>();
    if ( rootNode != null ) {
        flatten(rootNode, flatNodes);
    }
    return flatNodes;
}

public void flatten(Node<String, Integer> node, List<Node<String, Integer>> flatNodes) {
    Node<String, Integer> leftNode = node.left;
    if ( leftNode != null ) {
        flatten(leftNode, flatNodes);
    }

    flatNodes.add(node);

    Node<String, Integer> rightNode = node.right;
    if ( rightNode != null ) {
        flatten(rightNode, flatNodes);
    }
}

(6)接下来的一点是对平面节点列表进行排序。 提出了两种实现,一种使用lambda的更现代的实现,以及一种使用显式比较器的较旧样式的实现。 编写比较以生成从最小到最大排序的列表。 要颠倒排序顺序,请交换比较顺序。

public void sort(List<Node<String, Integer>> nodes) {
    Collections.sort(
        nodes,
        ((Node<String, Integer> n1, Node<String, Integer> n2) -> Integer.compare(n1.value, n2.value)) );
}

public static final Comparator<Node<String, Integer>> NODE_COMPARATOR = 
    new Comparator<Node<String, Integer>>() {
        public int compare(Node<String, Integer> n1, Node<String, Integer> n2) {
            return Integer.compare(n1.value, n2.value);
        }
    };

public void sort(List<Node<String, Integer>> nodes) {
    Collections.sort(nodes, NODE_COMPARATOR);
}

(7)作为结果,打印结果排序列表。

暂无
暂无

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

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