代码改变世界

算法与数据结构——排序(四)简单插入排序

2012-10-25 21:49  左眼微笑右眼泪  阅读(730)  评论(0编辑  收藏  举报

      直接插入排序,从名字上来看,它就是将一个数选择一个恰当的位置插入到一个有序的列表中,让插入这个数后的列表仍然是有序的。它实现起来的原理其实很简单,下面是一个简单的示意图:

image

 

       我们假设有一个空列表,然后有10个数{4,2,8,0,5,7,1,3,9,6},

 

1. 首先,第一个数4插入到列表中,它不用进行任何比较,因为列表中此时并没有任何数。

2. 接着我们插入第二个数2,插入2的时候,我们就需要进行比较,看列表中的数有没有比2大的,如果比2大,那么2就要插入到它的前面去。插入后,列表中序列为{2,4}

3. 接着我们把8插入到列表中去,在插入之前,我们先把8与4进行比较,发现4比8小,那么8就放到4的后面。(此时只需要与4比较,不需要与2进行比较,后面的时候有说明),此时的序列为{2,4,8}

4. 接着我们把0插入到列表中,插入0时,我们要把0与8进行比较,此时发现0与8小,那么0要插入到8的前面.是不是这样就行了呢。通过前面可得知,插入每一个数后,整个列表必须仍然有序。所以这时候,我们还需要把0与4进行比较,0比4小,那么0应该插入到4的前面,4的前面还有2,所以还需要把0与2进行比较,0比2小,0应该插入到2的前面。2之前再没有别的数了,所以这个才是0的真正位置,插入0之后的序列变成了{0,2,4,8};

5. 后面的数插入跟前面的原理是一样。如果说将要插入的一个数比前面的一个数大,那么它就不用交换,当前的位置就是它在序列中的位置,如果将要插入的数比它前面的一个数小,那么它就需要跟它前面的前面的数进行比较,如果每次比较都是它小,那么它就一直需要和前面的前面的前面的数进行比较,直到到比较到序列中的最后一个数。如果其中有一次比较,它较大,那么就把它插入到它那一次比较的那个数的后面。

    

      有一点我们要注意的,就是如果要插入的数比它前面的一个数大,那么这个数就不用跟它前面的前面的数进行比较了,当前数的后面就是它的插入位置。只有小的时候,才会一直向前比较。这是因为每一次插入排序完成后,序列都是有序的,可以从上面的图中看出。所以如果你比最后一个数还大,那么你一定比前面的数都要大。

      下面是具体的代码:

public void InsertSort(List<int> sortList)
      {
          int i, j;
          for (i = 0; i < sortList.Count-1; i++)
          {
              if (sortList[i] > sortList[i + 1])
              {
                  int tempMin=sortList[i + 1];//把目前最小的一个数记录下来,会接着与后面的数进行比较
                  for (j = i; j >=0; j--)
                  {
                      if (sortList[j] > tempMin)//与后面的每一个数进行比较
                      {
                          sortList[j + 1] = sortList[j];//如果有数比tempMin小, 那么就把这个数往后移一位
                      }
                      else
                      {
                          break;//记住,此处需要Break,因为只要有一次不大于temp,那么后面的数就不用再比较了,就已经找到正确位置了
                      }
                  }
                  sortList[j +1] = tempMin; //把最小的数插入到正确的位置            
              }
          }
      }

      我们再来看一下插入排序的时间复杂度:

      从上面的代码,我们可以看出,直接插入排序是每插入一个数就和它前面的一个数进行比较,如果比它大,那么就直接插入到当前位置,如果比它小,就一直向前比较,直到它比前面的数都大时为止。在最好的情况下,整个序列是一个有序的列表,那么其实每一次循环只需要比较一次就可了,也不用进行移动。此时时间复杂度为O(n),最后的情况下,整个列表是逆序,那么这时候每一个数都需要和它前面的所有数进行比较,每比较一次就要移动一次,最后的时间复杂度为1+2+……+n,所以时间复杂度为O(n^n).