【C语言】插入排序与希尔排序

希尔排序是插入排序的升级版,简单说,希尔排序就是数据分组然后再进行插入排序。

正因为希尔排序的存在,一般将插入排序称为直接插入排序。

很早就看过希尔排序,自己似乎也动手实现过这个算法。但在今天温习Braian.W.Kernihan、Dennis M.Ritchie合著的《C程序设计语言》时候,发现书上有一个希尔排序的程序(下),非常简洁,甚至让我有些迷糊。

/*
 shell sort:grouping and insert sorting
 dennis m. ritchie

*/
void shell_sort(int a[], int len)
{
 int gap, i, j, temp;

 for(gap = len/2; gap > 0; gap /= 2)
 {
  for(i = gap; i < len; i++)
  {
   for(j = i-gap; j>=0 && a[j]>a[j+gap]; j -= gap)
   {
    temp = a[j];
    a[j] = a[j+gap];
    a[j+gap] = temp;
   }
  }
 }

}

在最里层的for循环中,我看不出来这是插入排序,与自己写的插入排序(下)相差太远了。

/*
 insert sort
 the worst cal o(n^2), the best cal is o(n)
*/
void insert_sort(int a[], int len)
{
 int i,j,temp;


 for(i = 1; i < len; i++)
 {
  temp = a[i];
  for(j = i-1; j >= 0; j--)
  {
   
   if(a[j] > temp)
   {
    a[j+1] = a[j];
   }
   else
   {
    a[j+1] = temp;
    break;
   }
  }
 }
}

相应地,我的希尔排序程序为:


/*
 shell sort:grouping and insert sorting

*/
void shell_sort_house(int a[], int len)
{
 int gap, i, j, k, temp;

 for(gap = len/2; gap > 0; gap /= 2)
 {
  for(i = 0; i < gap; i++)
  {
   for(j = 0; j*gap < len; j++)
   {
    temp = a[i+j*gap];
    for(k = j-1; k >= 0; k--)
    {
     if( a[i+k*gap] > temp)
     {
      a[i+(k+1)*gap] = a[i+k*gap];
     }
     else
     {
      a[i+(k+1)*gap] = temp;
      break;
     }
    }
   }
  }
 }

}

对比一下,不得不说Dennis大神的程序比我的简洁N倍。

后来上网查阅资料,发现书中的写法原来是将“后移”操作改成了“交换”,本质上,还是插入排序。在http://blog.csdn.net/morewindows/article/details/6665714

一文中有详细介绍。

本以为温习《C程序设计语言》一书只是用来打发时间的,越看越发现自己还有许多不懂的地方。

最后附上一个完整的测试程序清单:


#include <stdio.h>


void print_array(int *list, int len)
{
    int i;
    for (i = 0; i < len; ++i)
    {
        printf("%d\t", *(list+i));
    }
    printf("\n");
}
 
/*
 insert sort
 the worst cal o(n^2), the best cal is o(n)
*/
void insert_sort(int a[], int len)
{
 int i,j,temp;


 for(i = 1; i < len; i++)
 {
  temp = a[i];
  for(j = i-1; j >= 0; j--)
  {
   
   if(a[j] > temp)
   {
    a[j+1] = a[j];
   }
   else
   {
    a[j+1] = temp;
    break;
   }
  }
 }
}

/*
 shell sort:grouping and insert sorting
 dennis m. ritchie

*/
void shell_sort(int a[], int len)
{
 int gap, i, j, temp;

 for(gap = len/2; gap > 0; gap /= 2)
 {
  for(i = gap; i < len; i++)
  {
   for(j = i-gap; j>=0 && a[j]>a[j+gap]; j -= gap)
   {
    temp = a[j];
    a[j] = a[j+gap];
    a[j+gap] = temp;
   }
  }
 }

}

/*
 shell sort:grouping and insert sorting

*/
void shell_sort_house(int a[], int len)
{
 int gap, i, j, k, temp;

 for(gap = len/2; gap > 0; gap /= 2)
 {
  for(i = 0; i < gap; i++)
  {
   for(j = 0; j*gap < len; j++)
   {
    temp = a[i+j*gap];
    for(k = j-1; k >= 0; k--)
    {
     if( a[i+k*gap] > temp)
     {
      a[i+(k+1)*gap] = a[i+k*gap];
     }
     else
     {
      a[i+(k+1)*gap] = temp;
      break;
     }
    }
   }
  }
 }

}

 


int main(int argc, char **argv)
{


 int ary[] = {2, 3, 4, 7, 1, 6, 8, 2, 10, 5, 12, 2, 3, 33, 12, 45, 12, 123, 44, 12, 32, 19, 29, 333};
 int len = sizeof(ary)/sizeof(int);

 print_array(ary, len);

 //insert_sort(ary, len);
 shell_sort_house(ary, len);

 print_array(ary, len);

 return 0;

}

 算法复杂度分析:

稳定性:相同记录,经过排序后,它们之间的相对位置保持不变,此类排序算法就是稳定的。常见的稳定排序算法有插入排序、冒泡排序、归并排序。这些算法之所以稳定,来自于它们算法本身,遇见相同记录时,保持原样,不作处理,所以这些相同记录的相对位置仍不变。相对而言,直接选择排序、堆排序、shell排序、快速排序都是不稳定算法。

时间复杂度,和空间复杂度是算法复杂度的另外两个指标,从上文提到的排序算法来看,冒泡法的速度最慢,希尔排序最高。空间复杂度基本差不多。

 我爱 菊子曰

你可能感兴趣的:(插入排序)