在不使用排序函数的情况下按字母顺序放置从数组接收的字符?

Put characters received from an array in alphabetical order without using sorting functions?

所以,基本上,我在 java 中创建了一个算法,该算法从字符串中获取字符并计算其频率。现在,我需要按字母顺序打印它。

例如: 频率:3 d频率:1 l 频率:5

有什么建议吗?这是我到目前为止所拥有的。

     int[] charCounts(String userSort) {
        int[] counts = new int[256];
        char[] c = userSort.toCharArray();
        for (int i=0;i<c.length;++i) {
            counts[c[i]]++;
        }
        return counts;
}

你已经完成了 80%。您已经有一个像 @MadPhysicist 所指的那样的排序地图。您正在使用 distribute-gather 技术。我猜你没有意识到在分发中,你已经对字符进行了排序。您只需要再次收集它们以进行输出。分发和收集可以是分类的一种形式。但是,它本身并没有使用排序函数。

我不会为此提供代码,因为您已经有了一个良好的开端,您只是在征求建议。

首先,您已经完成的分发部分:

ASCII 只有 128 个字符。但是,Java 无论如何都不使用 ASCII。即便如此,将此练习的范围限制在 C0 Controls and Basic Latin 块加上 C1 控制和 Latin-1 补充块似乎是合理的,这正是您的 new int[256] 所做的。

那么,这些块中的字符是否按照您想要的顺序排列?与 counts 中的顺序不一样吗?您已将字符作为计数分配到有序的框中。 counts[c[i]]++

聚会:

你只需要按照你想要的顺序把它们重新收集起来,然后按照你想要的格式写出来。 counts 上的循环会做到这一点。您的问题标题要求按顺序排列字符,这意味着输出放置相同数量的字符。您可以将字符数转换为重复字符。如果您的目标是简单地将它们打印出来,您可以循环执行;否则,你必须 build a string.

顺便说一句——该顺序称为字典顺序,因为它基于字符集或编码定义。字母表意味着选择的符号序列(在数学意义上)或特定自然语言的特定书写系统,其中一些字母被流行惯例或语言学院指定为 "the alphabet"。例如,拉丁字母中的丹麦字母表:ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ。参见 Locale

将您的结果存储在有序地图中,例如 TreeMap。迭代映射中的键将按排序顺序输出它们,无需额外处理。

这需要对您的代码进行少量修改。而不是 returning 一个数组,你会 return a SortedMap:

 SortedMap<Character, Integer> charCounts(String userSort) {
    SortedMap<Character, Integer> counts = new TreeMap<>();
    for (int i=0; i < userSort.size(); ++i) {
        char c = userSort.charAt(i);
        if(counts.contains(c)) {
             counts.put(c, counts.get(c) + 1);
        } else {
             counts.put(c, 1);
        }
    }
    return counts;
 }

您现在可以使用以下内容迭代字符:

 for(Character c : charCounts(...).keySet()) ...

keySet() 编辑的 Set return 将像地图本身一样排序。

如果您无法使用所提供的特定函数,可以在调用后将结果添加到地图,然后像以前一样遍历地图:

 int[] counts = charCounts(...);
 TreeMap<Character, Integer> map = new TreeMap<>();
 for(char c = 0; c < counts.length; c++)
      map.put(c, counts[c]);

首先,您想对提供的字符串中的字符进行排序,不使用任何 API 排序方法的简单方法是使用两个 for 循环。当然,您需要将提供的字符串分解为字符数组。假设提供的字符串是 "This is my string to sort":

String suppliedString = "This is my string to sort";
char[] charArray = suppliedString.toCharArray();

现在使用两个 for 循环遍历字符数组并操纵该数组的元素,将最少的字符值移到开头,将较大的值逐渐移到末尾。这种类型的排序称为 Bubble Sort,它是这样的:

Note: Yes...there are a lot of comments within the following code explaining what is going on. So much so that it's downright cluttering. That's what's so good about editors, you can easily delete them if you don't want them.

// The supplied String to sort.
String suppliedString = "this is my string to sort";
// Remove all whitespaces. We don't need them for 
// this excercise since our goal is to sort and 
// get character occurrences. If you want to also
// process whitespaces then comment the code line
// below.
suppliedString = suppliedString.replace(" ", "");

// Convert the supplied string to a character array.
char[] charArray = suppliedString.toCharArray();
// Declare a Character variable to hold the current
// Character Array element value being processed.
char tempChar;
// Iterate through the character array with two
// FOR loops so as to create a string which will
// hold the least character values to the greatest
// character values.
for (int i = 0; i < charArray.length; i++) {
    for (int j = 0; j < charArray.length; j++) {
        // Is the current Array element value in 
        // charArray[i] less than the what is in
        // the current Array element for charArray[j]?
        if (charArray[i] < charArray[j]) {
            // Yes it is...
            // Hold our current character element value.
            tempChar = charArray[i];
            // Now make the Array element at index i hold
            // what is in Array element at index j.
            charArray[i] = charArray[j];
            // Make the Array element at index j hold what
            // was originally in the Array element at index i.
            charArray[j] = tempChar;
        }
        // No it's not so let's continue iterations through 
        // the character array using the index place-holder 
        // j to see if there are still more character Array 
        // element values less than what is currently in the 
        // Character Array index place-holder i location.
    }
    // continue iterations through the character array 
    // using the index place-holder i to see if there 
    // are still more character Array element values less
    // that what might be in the Character Array index place
    // -holder j location.
}

//==============================================
// For your project you don't need this little
// section. I just added it so you can see what 
// the sort looks like.
// Now use yet another FOR loop to convert the 
// the sorted Character Array (charArray[]) back
// to a sorted string.
// Declare and initialize a String variable to 
// Null String (""). This variable will hold the
// new Sorted String.
String sortedString = "";
for (int i = 0; i < charArray.length; i++) {
    sortedString+= charArray[i];
}

// Display the sorted String. If you don't
// want spaces in your sort then use: 
// System.out.println(sortedString.trim());
// Spaces have the least value (32) so they
// will almost always be at the beginning of
// the sorted string.
System.out.println("Sorted String: -->   " + sortedString + "\n");
//==============================================

// Now that the Character Array is sorted let's
// use yet another couple FOR loops to figure out
// the occurrences of each character. We'll use our 
// same String variable (sortedString) to hold our 
// display text to console. (Note: There's a lot of 
// ways to do this sort of thing in Java)
int counter; // counter used to keep track of char occurrences.
sortedString = "";
for (int i = 0; i < charArray.length; i++) {
    counter = 0; // new character. Make sure counter is zeroed
    // Iterate through the entire array and count
    // those that are the same.   
    for (int j = 0; j < charArray.length; j++) {
        if (charArray[i] == charArray[j]) {
            counter++;
        }
    }
    // Make sure we don't place duplicate character/frequencies
    // into the string we're creating.
    if (!sortedString.contains("Char: " + charArray[i])) {
        // Add the current character and occurrence
        // to our string variable.
        if (sortedString.equals("")) {
            sortedString+= "Char: " + charArray[i] + " - Freq: " + counter; 
        } 
        else {
            sortedString+= " || Char: " + charArray[i] + " - Freq: " + counter; 
        }
    }
}
// Display the sorted characters and their occurrences.
System.out.println(sortedString);

是的,该代码中有很多 for 循环。理解代码后,如果愿意,可以删除所有评论。一旦你这样做了,你会发现真的没有太多的代码来完成这个任务。

您正在尝试实施所谓的 Counting Sort (Wikipedia)。

如果您的 universe(可能的字符集)与您要排序的输入的大小相比较小,则效果很好。

相对容易。您之前知道 universe 的正确顺序并设置了排序的 MapLinkedHashMap 以保持顺序)。对于我们的示例,让我们将宇宙限制为 [a, b, c, d, e].

LinkedHashMap<Character, Integer> charToCount = new LinkedHashMap<>();
charToCount.put('a', 0);
charToCount.put('b', 0);
charToCount.put('c', 0);
charToCount.put('d', 0);
charToCount.put('e', 0);

现在您遍历 input 并计算所有出现的次数:

String inputToSort = ...
for (char c : inputToSort.toCharArray()) {
    // Increase counter by one
    charToCount.put(c, charToCount.get(c) + 1);
}

最后,您只需按照先前已知的正确顺序遍历 Map 并打印每个字符出现次数:

StringBuilder sb = new StringBuilder();
// Every character
for (Entry<Character, Integer> entry : charToCount.entrySet()) {
    // How often it occurred
    for (int i = 0; i < entry.getValue(); i++) {
        sb.append(entry.getKey());
    }
}
String output = sb.toString();

当然你可以稍微优化一下程序,但那是一般的程序。链接的维基百科文章包含更多信息。

例如,在实践中,您可以使用 Java 中每个 charint 值来提取正确的顺序。这样你就不需要用整个宇宙初始化 Map 并且可以忽略甚至不会出现一次的东西。您也可以放弃 Map 以支持 array ,它根据定义保留顺序并且由您的机器进行了极度优化。如前所述,charindex 基于其 int 值。