【问题标题】:Insertionsort and Sentinels插入排序和哨兵
【发布时间】:2016-05-07 17:33:06
【问题描述】:

我正在尝试理解插入排序。我听说我可以用哨兵改进它。

这是我没有标记的代码:

public static int[] insertionSort(int[] sortieren) {
    int temp;
    for (int i = 1; i < sortieren.length; i++) {
        temp = sortieren[i];
        int j = i;
        while (j > 0 && sortieren[j - 1] > temp) {
            sortieren[j] = sortieren[j - 1];
            j--;
        }
        sortieren[j] = temp;
    }
    return sortieren;
}

我目前正在尝试了解在哪种情况下我可以获得 ArrayIndexOutOfBounds 异常。你能帮我理解为什么需要一个哨兵来改进该代码,以及我必须在哪里输入它?我会说我必须在数组的左边缘放置一个 Integer.MIN_Value 但我不确定,因为我没有看到它用完数组的情况。

如果您能帮助我了解插入排序中哨兵的用法,我将不胜感激。

使用 Sentinel...

    public void insertionSort(int[] array) {

    int temp;
    int arraySentinel[] = new int[array.length+1];
    for(int i = 0; i < array.length; i++){
        arraySentinel[i+1] = array[i];
    }
    arraySentinel[0] = Integer.MIN_VALUE;

    for (int i = 1; i < arraySentinel.length; i++) {
            temp = arraySentinel[i];
            int j = i;
            /**
             * Stabil weil sortieren[j-1] > temp!
             * Wäre nicht stabil wenn >=!
             */
            while (arraySentinel[j - 1] > temp) {
                arraySentinel[j] = arraySentinel[j - 1];
                j--;
            }
            arraySentinel[j] = temp;                
    }

    for (int i = 1; i < arraySentinel.length; i++){
        array[i-1] = arraySentinel[i];
    }
}

【问题讨论】:

    标签: java algorithm insertion-sort sentinel


    【解决方案1】:

    您不需要创建更大尺寸的新数组。

    只需遍历数组,找到最小元素并将其移动到第 0 个位置。

    现在这个元素作为哨兵,你可以在不检查边界的情况下对数组的其余部分进行排序。

    【讨论】:

      【解决方案2】:

      静态哨兵将是一个非常低的值,它将作为数组的第一个元素放置,即在数组 [0] 中。这样做的好处是不检查代码中的条件“j>0”。

      添加了 j>0 条件,以便程序不会给出 ArrayIndexOutOfBounds 异常。通过在 array[0] 处添加填充元素,并从 array[1....n] 运行循环,我们节省了检查 j>0 条件的开销。

      请注意,在无症状的情况下,它不会影响插入排序的复杂性。

      编辑:您修改后的实现是正确的。我假设您感到困惑,因为现在您必须再次填充整个数组,这将花费额外的 theta(n) 时间。因此,您担心添加哨兵实际上会使其变慢。但是,您需要了解这是 Java 的问题。 Java 数组具有不可变的大小,因此您需要创建一个新数组。这不是算法的注意事项。算法与语言无关。如果您使用其他具有可变数组大小规定的语言或使用 Java 的 List,则可以在 O(1) 时间内添加哨兵。在这种情况下,生成的程序会更快。

      【讨论】:

      • 谢谢你。但是,如果我想实现这个 Sentinel,我将创建一个长度为 + 1 的新数组,我的代码是否还在原地?或者我可以以更好的方式实现这一点。我在主题中添加了新代码。
      • 您的实现似乎是正确的。我可以理解它看起来似乎没有用,因为它对整体复杂性没有任何影响。但是你必须意识到你只是在减少开销常数,因此它不会降低渐近复杂度。事实上,插入排序被广泛使用,因为它的内部循环非常有效,使用很少的常量和就地交换。
      • 好的,谢谢。最后我明白了!也许使用 ArrayList mhm 会更好。我添加了新代码,希望现在可以了 :)
      • 没问题!感谢您实际上付出了努力来实现哨兵代码并再次提出您的问题。表明你真的想知道。快乐编程:)
      • 您好,如果您的问题得到满意回答,请标记为已回答!
      猜你喜欢
      • 2014-01-21
      • 1970-01-01
      • 1970-01-01
      • 2018-06-17
      • 2014-09-23
      • 2014-10-11
      • 1970-01-01
      • 1970-01-01
      • 2021-01-13
      相关资源
      最近更新 更多