八大排序

 一:排序分类

 

二、算法实现(内部排序)

1、插入排序之直接插入排序

排序步骤:

①从第一个元素开始,该元素可以认为已经被排序
②取出下一个元素,在已经排序的元素序列中从后向前扫描
③如果该元素小于前面的元素(已排序),则依次与前面元素进行比较如果小于则交换,直到找到大于该元素的就则停止;
④如果该元素大于前面的元素(已排序),则重复步骤2
重复步骤2~4 直到所有元素都排好序

 

例:3 4 7 1 5 2 6 9(排成递增序列)

排序过程:i = 1:3 4 7 1 5 2 6 9 (3和4比)

     i = 2:3 4 7 1 5 2 6 9 (4和7比)

       i = 3:①3 4 1 7  5 2 6 9(1和7比)

        ②3 1 4 7 5 2 6 9(1 和4比)

        ③1 3 4 7 5 2 6 9(1和3比)

    ......

    i = 8:1 2 3 4 5 6 7 9

使用直接插入排序的优点是稳定,快速,缺点是:比较次数不一定,比较次数越多,插入点后的数据移动越多,特别是当数据总量庞大的时候,但用链表可以解决这个问题。平均时间复杂度O(n^2),适合于量级小于千的排序。

清单1:

int StraightInsertSort(int s[],int n)
{
  int i,j;
  int temp;
  for(i = 1;i<n;i++)
  {
    for(j = i; j > 0;j--)
    {
      if(s[j] < s[j-1])
      {
        temp = s[j];
        s[j] = s[j-1];
        s[j-1] = temp;
      }
      else
      break;
    }
  }
}

 

2、插入排序之希尔排序

原理:已知一组无序数据a[1]、a[2]、……a[n],需将其按升序排列。发现当n不大时,插入排序的效果很好。首先取一增量d(d<n),将a[1]、a[1+d]、a[1+2d]……列为第一组,a[2]、a[2+d]、a[2+2d]……列为第二组……,a[d]、a[2d]、a[3d]……列为最后一组以此类推,在各组内用插入排序,然后取d'<d,重复上述操作,直到d=1。

优点:快,数据移动少

缺点:d值不确定,取什么值看经验

希尔排序的时间复杂度为 O(N*(logN)2),适合于中等规模排序

清单2:

int sheelsort(int a[],int n)
{
  int k = n / 2;//k是增量
  while (k > 0)
  {
    for (int i = k; i < n; i++)
    {
      int t = a[i];
      int j = i - k;
      while (j >= 0 && t < a[j])
      {
        a[j + k] = a[j];
        j = j - k;
      }
      a[j + k] = t;
     }
     k /= 2;
  }
}

 

3.选择排序之简单选择排序

①从左至右遍历,找到最小(大)的元素,然后与第一个元素交换。
②从剩余未排序元素中继续寻找最小(大)元素,然后与第二个元素进行交换。
③以此类推,直到所有元素均排序完毕。

有序区,无序区

优点:移动数据的次数已知(n-1次)。
缺点:比较次数多,不稳定
例:3 4 7 1 5 2 6 9(排成递增序列)
第一趟排序:     4 7 3 5 2 6 9
     有序区    无序区
第二趟排序:1 2     7 3 5 4 6 9
               有序区    无序区
第三趟排序:1 2 3  7 5 4 6 9
     有序区   无序区
。。。。。。
      1 2 3 4 5 6 7 9
清单3:

int selectionsort(int a[],int n)
{
  int i,j,temp;
  //一趟一趟的找
  for(i = 0; i < n;i++)
  {
    int min = i;
    //找最小值,记录位置
    for(j = i+1; j < n; j++)
    {
      if(a[min] > a[j])
        min = j;
    }
    //找到后交换值
    temp = a[min];
    a[min] = a[i];
    a[i] = temp;
  }
}

 

4.堆排序 

示例:

 

5、冒泡排序

一组数据,两两比较,大的放后面,小的放前面,就像冒泡一样,越大的泡会冒到最上面,一趟一趟比较,直到所有数据从小到大依次排列。

算法分析:

①相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法。

②平均时间复杂度o(n^2)

清单5:

int Bubblesort(int a[],int n)
{
  int i,j,min;
  for(j = 1; j < n; j++)    //控制排序的执行次数
  {
    for(i = 0; i < n-j; i++)   //控制在一次排序中相邻记录的比较和交换
    {
      if(a[i] > a[i+1])  //如果前面元素大于后面元素则交换
      {
        min = a[i+1];
        a[i+1] = a[i];
        a[i] = min;
      }
    }
  }
}

 

6、快速排序

快速排序又叫分区交换排序,是目前已知的平均速度最快的一种排序方法。基本思想:从待排序的n个记录中任意选取一个记录Ri(通常选取序列中的第一个记录)做标准,调整序列中各个记录的位置,使排在Ri前面的记录的关键字都小于Ri.key,排在Ri后面的记录的关键字都大于等于Ri.key,我们把这样的一个过程称作一次快速排序。在第一次快速排序过程中,确定了所选取的记录Ri最终在序列中的排列位置,同时也把剩余的记录分成了两个子序列。对两个子序列分别进行快速排序,又确定了两个记录在序列中应处的位置,并将剩余记录分成了四个子序列,如此重复下去,当各个子序列的长度为一时,全部记录排序完毕。

算法分析:

①是一种不稳定的排序方法

②递归形式的快速排序法需要栈空间暂存数据,其空间复杂度为O(n)

③时间复杂度是o(nlgn)

清单6:

int quicksort(int a[],int low,int high)
{
  int i,j,temp;
  i = low;
  j = high;
  temp = a[i];
  while(i < j)
  {
    //从右向左找第一个比temp小的元素
    while(i < j && temp <= a[j])  //如果满足此条件,即temp的值比a[j]小
      j--;                 //则j向左移动
    if(i < j)                //当不满足while循环的条件,即找到了一个比temp小的数,只要i<j,
    {
      a[i++] = a[j];        //将找到的小的数a[j]的值赋给a[i],i = i+1
    }
    //同理从左向右找第一个比temp大的元素
    while(i < j && temp >= a[i])  //如果满足此条件,即temp的值比a[i]大
      i++;          //则i向右移动
    if(i < j)                  //当不满足while循环的条件,即找到了一个比temp大的数,只要i<j,
    {
      a[j--] = a[i];        //将找到的大的数a[i]的值赋给a[j],j = j-1
    }
    a[i] = temp;
    //使用递归实现子序列的排序
    if(low < i)
    {
      quicksort(a,low,i-1);
    }
    if(i < high)
    {
      quicksort(a,j+1,high);
    }
  }

}

 

7、归并排序

8、基数排序

总结:

待续~~

posted on 2017-09-26 18:35  懿一懿一  阅读(337)  评论(0编辑  收藏  举报

导航