算法学习入门之使用C语言实现各大基本的排序算法

2020-01-06 14:01:56王冬梅

插入排序 (Insertion Sort)

假设在新生报到的时候,我们将新生按照身高排好队(也就是排序)。如果这时有一名学生加入,我们将该名学生加入到队尾。如果这名学生比前面的学生低,那么就让该学生和前面的学生交换位置。这名学生最终会换到应在的位置。这就是插入排序的基本原理。

对于起始数组来说,我们认为最初,有一名学生,也就是最左边的元素(i=0),构成一个有序的队伍。

随后有第二个学生(i=1)加入队伍,第二名学生交换到应在的位置;随后第三个学生加入队伍,第三名学生交换到应在的位置…… 当n个学生都加入队伍时,我们的排序就完成了。


/*By Vamei*/
/*insert the next element 
 into the sorted part*/
void insert_sort(int a[], int ac)
{
  /*use swap*/
  int i,j;  
  for (j=1; j < ac; j++) 
  {
    i = j-1;
    while((i>=0) && (a[i+1] < a[i])) 
    {
      swap(a+i+1, a+i);
      i--;
    }
  }
}

选择排序 (Selection Sort)

排序的最终结果:任何一个元素都不大于位于它右边的元素 (a[i] <= a[j], if i <= j)。所以,在有序序列中,最小的元素排在最左的位置,第二小的元素排在i=1的位置…… 最大的元素排在最后。

选择排序是先找到起始数组中最小的元素,将它交换到i=0;然后寻找剩下元素中最小的元素,将它交换到i=1的位置…… 直到找到第二大的元素,将它交换到n-2的位置。这时,整个数组的排序完成。


/*By Vamei*/
/*find the smallest of the rest,
 then append to the sorted part*/
void select_sort(int a[], int ac) 
{
  /*use swap*/
  int i,j;
  int min_idx;
  for (j = 0; j < ac-1; j++) 
  {
    min_idx = j;
    for (i = j+1; i < ac; i++) 
    {
      if (a[i] < a[min_idx]) 
      {
        min_idx = i;
      }
    }
    swap(a+j, a+min_idx);
  }  
}

希尔排序 (Shell Sort)

我们在冒泡排序中提到,最坏的情况发生在大的元素位于数组的起始。这些位于数组起始的大元素需要多次遍历,才能交换到队尾。这样的元素被称为乌龟(turtle)。

乌龟元素的原因在于,冒泡排序总是相邻的两个元素比较并交换。所以每次从右向左遍历,大元素只能向右移动一位。(小的元素位于队尾,被称为兔子(rabbit)元素,它们可以很快的交换到队首。)

希尔排序是以更大的间隔来比较和交换元素,这样,大的元素在交换的时候,可以向右移动不止一个位置,从而更快的移动乌龟元素。比如,可以将数组分为4个子数组(i=4k, i=4k+1, i=4k+2, i=4k+3),对每个子数组进行冒泡排序。比如子数组i=0,4,8,12...。此时,每次交换的间隔为4。