排序算法

 
//稳定排序:大小相同的元素排序后它们顺序不变。
//
//排序方法选择,n表示数据长度:
/*
  1、若n较小(n <= 50)可以用插入排序、选择排序,如果再小的话就考虑使用插入排序;
  2、若文件初始是大致有序的,应考虑插入排序、冒泡排序;
  3、如果n很大5000+,则考虑快速排序、堆排序、归并排序;
*/
 
//排序法          平均时间          最差情形         稳定度       额外空间         	    备注 
//冒泡              O(n2)          O(n2)         稳定           O(1)              n小时较好,大部分已排序时较好  
//交换              O(n2)          O(n2)         不稳定         O(1)              n小时较好 
//选择              O(n2)          O(n2)         不稳定         O(1)              n小时较好 
//插入              O(n2)          O(n2)         稳定           O(1)              大部分已排序时较好 
//基数              O(logRB)     O(logRB)        稳定           O(n)              B是真数(0-9),R是基数(个十百)
//
//Shell          O(nlogn)      O(ns)      1<s<2 不稳定       O(1)              s是所选分组 
//快速              O(nlogn)      O(n2)          不稳定         O(nlogn)          n大时较好 
//归并              O(nlogn)      O(nlogn)       稳定           O(1)              n大时较好 
//堆                O(nlogn)      O(nlogn)       不稳定         O(1)              n大时较好 
 
 
//****************************************************************************************************
//插入排序
//从第一个开始,记录data[i]为temp
//将i左边所有比temp大的元素data[j-1]都向后移动一位
//然后将temp插入到空出来的位置
template<class T>
void insertSort( T data[], const size_t &n )
{
 for ( size_t i=0,j=0; i<n; i++ )
 {
  T temp = data[i];
  for ( j=i; j>0 && temp < data[j-1]; j--)
  {
   data[j] = data[j-1];
  }
  data[j] = temp;
 }
}
 
//****************************************************************************************************
//选择排序
//起始从第一个元素开始i
//找到i到n中最小的放在i位置
//i++
template<class T>
void selectSort( T data[], const size_t &n )
{
 for ( size_t i=0,j,least; i<n-1; i++ )
 {
  for ( j=i+1,least=i; j<n; j++ )
  {
   if ( data[j] < data[least] )
   {
    least = j;
   }
  }
  swap( data[least], data[i] );
 }
}
 
 
//****************************************************************************************************
//冒泡排序
//想像成一个柱体,最小的在低端,会像起泡一样冒上来
//每次i循环结束都冒上来剩余元素中最小的
//记录每次i循环标志是否发生交换,如果没发生则排序结束,终止循环
template<class T>
void bubbleSort( T data[], const size_t &n )
{
 bool isExchange = false;
 for ( size_t i=0,j; i<n-1; i++ )
 {
  isExchange = false;
  for ( j=n-1; j>i; j--)
  {
   if ( data[j] < data[j-1] )
   {
    swap( data[j], data[j-1] );
    isExchange = true;
   }
  }
  if ( !isExchange )
  {
   return;
  }
 }
}
 
 
//****************************************************************************************************
//Shell排序
//
//Shell排序通过将数据分成不同的组,先对每一组进行排序
//然后再对所有的元素进行一次插入排序,以减少数据交换和移动的次数。
//演示如下链接
//http://student.zjzk.cn/course_ware/data_structure/web/flashhtml/shell.htm
//其中分组的合理性会对算法产生重要的影响。现在多用D.E.Knuth的分组方法。
//
//Shell排序比冒泡排序快5倍,比插入排序大致快2倍。
//Shell排序比起QuickSort,MergeSort,HeapSort慢很多。
//但是它相对比较简单,它适合于数据量在5000以下并且速度并不是特别重要的场合。
//它对于数据量较小的数列重复排序是非常好的。

template<class T>
void shellFun( T data[], const size_t &n, const size_t &d)
{
 for ( size_t i = d+1; i<n; i++ )
 {
  T temp = data[i];
  size_t j = i;
  while ( j-d>=0 && temp < data[j-d] )
  {
   data[j] = data[j-d]; 
   j -= d;
  }
  data[j] = temp;
 }
}
template<class T>
void shellSort( T data[], const size_t &n )
{
 size_t d = n;
 while ( d>1 )
 {
  d = d/3 + 1;
  shellFun( data, n, d );
 }
}
 
 
 
 
//****************************************************************************************************
//快速排序(QuickSort)
//
//快速排序是一个就地排序,分而治之,大规模递归的算法。
//从本质上来说,它是归并排序的就地版本。快速排序可以由下面四步组成。
//
//(1) 如果不多于1个数据,直接返回。
//(2) 一般选择序列最左边的值作为支点数据。
//(3) 将序列分成2部分,一部分都大于支点数据,另外一部分都小于支点数据。
//(4) 对两边利用递归排序数列。
//
//快速排序比大部分排序算法都要快。尽管我们可以在某些特殊的情况下写出比快速排序快的算法,
//但是就通常情况而言,没有比它更快的了。
//快速排序是递归的,对于内存非常有限的机器来说,它不是一个好的选择。
 

template<class T>
void quickFun( T data[], const size_t &first, const size_t &last )
{
 size_t lower = first+1;
 size_t upper = last;
 funtemp( data );
 swap( data[first], data[(first+last) >> 1] );
 funtemp( data );

 T bound = data[first];
 while( lower <= upper )
 {
  while ( lower <= upper && data[lower] < bound )
  {
   ++lower;
  }
  while ( lower <= upper && bound < data[upper] )
  {
   --upper;
  }
  if ( lower < upper )
  {
   swap( data[lower++], data[upper--] );
   funtemp( data );
  }
  else
  {
   ++lower;
  }
 }
 swap( data[upper], data[first] );
 funtemp( data );
 if ( 0 < upper && first < upper-1 ) //这里用的size_t不判断upper大于0就悲剧了
 {
  quickFun( data, first, upper-1 );
 }
 if ( upper+1 < last )
 {
  quickFun( data, upper+1, last );;
 }
}

template<class T>
void quickSort( T data[], const size_t &n )
{
 if ( n < 2 )
 {
  return;
 }
 size_t max = 0;
 for ( size_t i=1; i<n; i++ )
 {
  if ( data[max] < data[i] )
  {
   max = i;
  }
 }
 swap( data[n-1],data[max]);
 quickFun( data, 0, n-2 );
}
 
 
 
 
//****************************************************************************************************
//归并排序
//归并排序先分解要排序的序列,从1分成2,2分成4,依次分解,
//当分解到只有1个一组的时候,就可以排序这些分组,
//然后依次合并回原来的序列中,这样就可以排序所有数据。
//归并排序比堆排序稍微快一点,但是需要比堆排序多一倍的内存空间,因为它需要一个额外的数组。

template<class T>
void MergeFun( T L1[], T L2[], const size_t &first, const size_t &last )
{
 for(size_t i=first; i<=mid; i++)
  L2[i] = L1[i];
 size_t k = last;
 for(size_t j=mid+1; j<=last; j++)
  L2[j] = L1[k--];
 size_t s1 = first;
 size_t s2 = last;
 size_t t = first;
 while(t<=last)
 {
  if(L2[s1] <= L2[s2])
   L1[t++] = L2[s1++];
  else
   L1[t++] = L2[s2--];
 }
}
template<class T>
void MergeSort( T L1[], T L2[], const size_t &first, const size_t &last )
{
 if(first >= last)
 {
  return;
 }
 size_t mid = (first+last)/2;
 MergeSort(L1, L2, first, mid);
 MergeSort(L1, L2, mid+1, last);
 MergeFun(L1, L2, first, mid, last);
}
 
 
 
 
//****************************************************************************************************
//基数排序(RadixSort)
//
//基数排序和通常的排序算法并不走同样的路线。
//它是一种比较新颖的算法,但是它只能用于整数的排序,
//如果我们要把同样的办法运用到浮点数上,我们必须了解浮点数的存储格式,
//并通过特殊的方式将浮点数映射到整数上,然后再映射回去,这是非常麻烦的事情,
//因此,它的使用同样也不多。
//而且,最重要的是,这样算法也需要较多的存储空间。
 
 
 
//****************************************************************************************************
//堆排序(HeapSort)
//
//堆排序适合于数据量非常大的场合(百万数据)。
//
//堆排序不需要大量的递归或者多维的暂存数组。
//这对于数据量非常巨大的序列是合适的。
//比如超过数百万条记录,因为快速排序,归并排序都使用递归来设计算法
//在数据量非常大的时候,可能会发生堆栈溢出错误。
//
//堆排序会将所有的数据建成一个堆,最大的数据在堆顶
//然后将堆顶数据和序列的最后一个数据交换
//接下来再次重建堆,交换数据,依次下去,就可以排序所有的数据。
 
 

你可能感兴趣的:(排序算法)