==============================
冒泡排序算法
==============================
1.算法稳定性
稳定
2.复杂度
空间复杂度O(1); 平均时间复杂度O(n2)
3.极限情况分析
最好情况:向量本来就是有序的,则一趟扫描即可结束,共比较n-1次,无交换。
最坏情况:向量是逆序的,则一共需要做n-1次扫描,每次扫描都必须比较n-i次,由等差数列求和公式知道,一共需做n(n-1)/2次比较和交换。
4.算法实现
template<typename T>
void bubble_sort(T * array, const int size)
{
if(size < 2 || array == NULL)
{
cout << "illegal input!" << endl;
return;
}
bool exchanged = false;
T tmp;
for(int i=0; i<size-1; ++i)
{
exchanged = false;
for(int j=size-1; j>i; --j)
{
if(array[j] < array[j-1])
{
tmp = array[j];
array[j] = array[j-1];
array[j-1] = tmp;
exchanged = true;
}
}
if(!exchanged)
{
return;
}
}
}
5. 算法改进
(1) 奇偶交换排序
稳定性? 稳定 //TODO need verifying
空间复杂度O(1), 时间复杂度O(n2)
极限情况分析:正向有序:n-1次比较;逆向有序((n+1)/2)*n+(n/2-1)次比较
综合而言,性能和冒泡排序相当,所以一般不用此种排序方法。
算法实现:
template<typename T>
void oe_sort(T * array, const int size)
{
if(size < 2 || array == NULL)
{
cout << "illegal input!" << endl;
return;
}
T tmp;
bool exchanged = true;
while(exchanged)
{
exchanged = false;
//scan odd index
for(int i=1; i<size-1; i+=2)
{
if(array[i] > array[i+1])
{
tmp = array[i];
array[i] = array[i+1];
array[i+1] = tmp;
exchanged = true;
}
}
//scan even index
for(int j=0; j<size-1; j+=2)
{
if(array[j] > array[j+1])
{
tmp = array[j];
array[j] = array[j+1];
array[j+1] = tmp;
exchanged = true;
}
}
}
}
(2) 每次扫描记住最后一次扫描发生的位置lastExchange
如此一样,下一趟排序时区间[0, lastExchange-1]是有序区, [lastExchange, size-1]是无序区。如果不记录,则下一趟排序时区间[0, i]有序区间,i为上次排序的趟数。自然的,lastExchange的最小可能数值就是i,所以此种改性是有效的。
算法性能和普通冒泡一样。
算法实现: //TODO
(3) 改进冒泡算法的不对称性
什么是不对称性? 比如上面的冒泡排序算法,如果数组中的最大值位于a[0],理论上一遍扫描就可以完成排序,但实际仍旧需要n-1遍扫描。而如果改冒泡为沉底,则一遍即可。