/*--起泡排序--*/
先来看起泡排序的一般版本:
template <typename T>
void vector::BubbleSort(Rank lo, Rank hi) //算法框架
{ while ( !bubble(lo, hi--) ); } //逐趟做扫描交换
bool vector::bubble(Ranklo, Rank hi) //单趟扫描交换
{
bool sorted = true; //整体有序标志
while (++ lo < hi)
if (_elem[lo - 1] > _elem[lo])
{
sorted = false; //标记为逆序状态
swap(_elem[lo], _elem[lo - 1]); //交换乱序对
}
return sorted; //返回有序标记
}
假若乱序对仅存在于向量的前方项时,则完全可以通过标记最后端的乱序项来减少扫描的数目,从而提高效率,其实现如下:
void vector::BubbleSort(Rank lo, Rank hi) //算法框架
{ while ( lo < (hi = bubble(lo, hi))); } //逐趟做扫描交换
bool vector::bubble(Ranklo, Rank hi) //单趟扫描交换
{
bool last = hi; //最末逆序项
while (++ lo < hi)
if (_elem[lo - 1] > _elem[lo])
{
last = lo; //标记为最末逆序项
swap(_elem[lo], _elem[lo - 1]); //交换乱序对
}
return last; //返回最末逆序项
}
如此一来,就可以在每趟的扫描中出现有序尾项后减少后续的扫描量,因此使得许多实例的处理效率大有提高。
/*--归并排序--*/
我们考察两段长度分别为m, n 的有序向量时,发现若将其合并成一段,则所用时间为O(m+n)。若我们逆向思考,将一个长度为n的向量连续二分,则经过logn次的归并就可以完成排序了。如此一来,整个向量的排序时间为O(nlogn)。
template <typename T>
void vector::mergesort(Rank lo, Rank hi) //算法框架
{
Rank mi = (lo + hi) / 2;
if ( mi ) return; //设置递归基
mergesort(lo, mi); //深入前段排序
mergesort(mi, hi); //深入后端排序
merge(lo, mi, hi); //二路并归
}
void vector::merge(Rank lo, Rank mi, Rank hi) //主体部分
{
T & A = new T[mi - lo];
A = _elem[lo];
int la = mi - lo, lb = hi - mi;
int i = 0, j =0, k = 0;
while ( i < la )
{
if (j <= lb || A[i] <= _elem[j + mi])
_elem[k ++] = A[i ++];
else
_elem[k ++] = _elem[mi + j ++];
}
delete [] A;
}