插入排序:为什么将键分配给j + 1索引?

时间:2017-05-01 22:11:03

标签: c++ sorting

void insertionSort(vector<int>& v){
    for(int i =1; i<v.size(); ++i){
        int key = v[i];
        int j = i - 1;

        while(j>=0 && key < v[j]){
            swap(v[j], v[j+1]);
            j--;
        }
        v[j+1] = key; // works fine without this.
    }
}

在插入排序算法中,我只是想知道为什么插入了注释部分。 我做了几个实验去除那部分,实际上认为可以摆脱它。

有人可以解释这条线的目的吗?任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:2)

由于每次交换后它都会j--,在最终交换之后(释放v[j]),它再次减少j。因此,您需要将新元素放在v[j + 1]

顺便说一下,此代码不需要交换,您也可以v[j + 1] = v[j]代替swap

修改

关于实施的问题,或许作者提出了一个需要swap的问题 - 在不知道背景的情况下,我们无法肯定地说。

由于没有人真正使用插入排序,我认为这只是理论上的目的,并且可能通过计算交换次数来计算复杂性。因此,作者可能已经使用swap作为构建块来演示排序。

回到问题,

  1. 如果您对swap执行的额外写操作没有问题,则实施正确
  2. (基本上swap(a, b)t = a; a = b; b = t;,因此另外两次写入。)

    1. 如果你有swap,那么注释掉的行确实没有必要。
    2. 如果没有swap,您可以将其重写为 -

      void insertionSort(vector<int>& v){
          for(int i = 1; i < v.size(); ++i){
              int key = v[i];
              int j = i - 1;
      
              while(j >= 0 && key < v[j]){
                  v[j + 1] = v[j];
                  j--;
              }
              v[j + 1] = key;  // this is now necessary.
          }
      }
      

      请注意,由于这会减少仅由常量所取的渐近时间,因此复杂性仍然与swap的复杂度相同,即$ O(n ^ 2)$。