【问题标题】:Insertion Sort Algorithm to Sort String[]插入排序算法对字符串进行排序[]
【发布时间】:2018-08-17 06:38:51
【问题描述】:

我有一个关于在 Java 中使用 插入排序算法 对 String[] 数组进行排序的问题。我确实意识到使用不同的算法可能会更容易完成我的问题,但我正在尝试首先了解一切如何与这个算法一起工作。

基本上,我正在尝试使用该算法对字符串数组进行排序。为此,我比较字符串数组中的 char 值,以便能够使用标准 >== 运算符,因为比较值方式(就像使用 ints 一样)自然非常简单。

我有一个正在解决的解决方案,我通过在每个数组索引处找到的前 2 个 char 值对字符串数组进行排序,但我开始意识到我所做的并不是一个非常强大的解决方案,因为字符串在一个数组很容易具有比彼此“更长”的值,这不会使我的排序对于具有相似值的较长字符串非常准确。

考虑到这一点,有人可以建议(以及我在下面编写的代码)我将如何动态比较从各种 strings 创建的 char 值进行排序原来的 string 值?

那么...

答: ...在比较不同大小字符串的值时,我不会遇到 NullPointer 异常

B: ...每个char值都是从字符串中比较的,不考虑大小,所以我可以准确地对原始字符串数组进行排序)

public String[] sortArrayOfStrings(String[] array){
        //NOT COMPLETE, ONLY SORTS BASED ON FIRST & SECOND CHAR OF STRING INDEX
        //BASED ON INSERTION SORT ALGORITHM
        int length = array.length;

        String value;
        int index;

        for(int a = 1; a < length; a++){
            char currentCharValue = array[a].charAt(0);//USE '[a]' not '[index]'
            value = array[a];
            index = a;

            if(currentCharValue == array[a - 1].charAt(0) ){//IF FIRST CHAR == PREVIOUS
                while (index > 0 && array[index - 1].charAt(1) > array[index].charAt(1)){
                    array[index] = array[index - 1];
                    index = index - 1;
                }
            }else{

                while (index > 0 && array[index - 1].charAt(0) > currentCharValue){
                    array[index] = array[index - 1];
                    index = index - 1;
                }
            }
            array[index] = value;
        }

        return array;
}

由于 2 个字符检查而按预期工作的示例数组:

String[] arr = {"zz", "bb", "cb", "ba","za", "zb", "cz", "ab","aa"};

由于额外字符而无法正确排序的示例数组:

String[] arr = {"bbz", "bba", "abz","abc"};

我知道上面的数组由于硬编码 2 个字符的“检查”而无法正确排序,我正在尝试消除对检查进行硬编码的需要。

【问题讨论】:

    标签: java arrays algorithm sorting insertion-sort


    【解决方案1】:

    如果你真的想使用字符比较来做,最好的方法是创建单独的方法来比较这些字符串。

    在 isSmallerThan() 内部,while 循环递增 currentIndex 直到它不会超出任何参数 的范围,直到字符相同。 然后 if 语句检查 currentIndex 是否超出了至少一个字符串的范围,它可能发生在输入中,例如: (啊啊啊,啊), (aaabb, aaa), (啊啊啊啊啊)。 然后我们必须通过长度比较来决定哪个更小。

    对于插入排序算法,我们不关心 (aaa, aaa) 是相同的字符串,我们可以返回它为 false,它会中断 sortArrayOfStrings 方法内的 while 循环。

    否则我们知道字符是不同的,我们只是比较它们。

    String[] sortArrayOfStrings(String[] array){
        int length = array.length;
        String value;
        int index;
    
        for(int a = 1; a < length; a++){
            value = array[a];
            index = a;
            while(index > 0 && isSmallerThan(value, array[index-1])) {
                array[index] = array[index - 1];
                --index;
            }
            array[index] = value;
        }
        return array;
    }
    
    boolean isSmallerThan(String left, String right) {
        int curIndex = 0;
        while (curIndex < left.length()
                && curIndex < right.length()
                && left.charAt(curIndex) == right.charAt(curIndex)){
            ++curIndex;
        }
    
        if (curIndex == left.length() || curIndex == right.length())
            return left.length() < right.length();
        else
            return left.charAt(curIndex) < right.charAt(curIndex);
    }
    

    但正如人们在我之前所说的,最好使用 String 库中的 compareTocompareToIgnoreCase 方法。要完成这项工作,只需更改 isSmallerThan(值,数组 [index-1]) 进入 数组[index-1].compareToIgnoreCase(value) > 0.

    【讨论】:

    • 太棒了,这就是我昨天在逃避的逻辑。尽管您在回答中这么说,但我会注意到@Chris 的 compareTo 回答似乎比使用 chars 更好(现在我考虑了一下),但是我是基于 char 值进行排序的在我问这个问题之后,所以谢谢!
    • 我在文章末尾写了有关 compareTo() 方法的内容。 CompareTo 方法非常简单和重要,所以至少基本了解它的逻辑总是好的,你的逻辑有问题所以我决定编写整个方法代码。不客气:)
    【解决方案2】:

    使用compareTo()方法,insertion sort算法的实现可以是这样的:

    class InsertionSorter {
    
        public String[] sortArrayOfStrings(String[] array) {
            for (int i = 1; i < array.length; i++) {
                String element = array[i];
                int j;
                for (j = i - 1; j >= 0 && element.compareTo(array[j]) <= 0; j--)
                    array[j + 1] = array[j];
    
                array[j + 1] = element;
            }
            return array;
        }
    }
    

    示例测试:

    public class InsertionSorterTest {
    
        @Test
        public void shouldSortTwoLetterWords() {
            String[] arr = {"zz", "bb", "cb", "ba", "za", "zb", "cz", "ab", "aa"};
            String[] sortedArray = new InsertionSorter().sortArrayOfStrings(arr);
            Assert.assertEquals(sortedArray, new String[]{"aa", "ab", "ba", "bb", "cb", "cz", "za", "zb", "zz"});
        }
    
        @Test
        public void shouldSortLongerWords() {
            String[] arr = {"bbz", "bba", "abz", "abc"};
            String[] sortedArray = new InsertionSorter().sortArrayOfStrings(arr);
            Assert.assertEquals(sortedArray, new String[]{"abc", "abz", "bba", "bbz"});
        }
    }
    

    【讨论】:

      【解决方案3】:

      尝试使用 String.CompareTo(String s) 方法。这很像您一直在使用的比较运算符,只是它会计算为整数。

      String str1 = "Cat";
      String str2 = "Dog"; 
      
      int sCompare = str1.CompareTo(str2);
      
      1. 如果 sCompare == 0,则字符串是“相同的”
      2. 如果 sCompare > 0,则 str1 > str2(按字母顺序)
      3. 如果 sCompare str1(按字母顺序)

      编辑:

      为清楚起见,在上述示例中,sCompare 的计算结果为负值。

      【讨论】:

      • 这是一个非常优雅的解决方案,并且可能更有效地解决我正在做的事情@Chris。我昨天也向我的硕士课程中的一位教授询问了这个问题,他提出了相同的 compareTo 解决方案。但是,我将不得不将 Damian 的答案标记为正确,因为我正在尽我所能远离内置的 String 方法,因为使用 chars 允许我创建(我想)将字符串转换为 chars 的辅助算法和比较它们。 +1 不过,如果我能标记 2 个正确答案,我会的。
      • 只是添加到我的最后一条评论以消除混乱(如果有的话)。我确实意识到 charAt() 是一个 String 类方法。我的意思是为了学习目的,我试图远离 String 类中的比较方法。我将查看 compareTo 的文档,看看它是如何实现的 :)
      • compareTo 是 Java 库中非常常见的函数,并且对于许多不同的类有不同的实现。事实上,通过查看 Comparable 接口(例如 Class foo Implements Comparable),您可能会在这项研究中更好地为自己服务。例如,您如何比较猴子和大象:体重、毛量、寿命等?在您的代码中,您一次比较一个字符的字符串,可能与 String.CompareTo() 的实际编码方式没有太大区别。您实际上是在重新发明轮子。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-12
      • 2014-05-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多