冒泡排序
排序约定:
public abstract class Sort<T> where T:IComparable<T>
{
public abstract void sort(T[] nums);
/// <summary>
/// 第一位比第二位小
/// </summary>
/// <param name="t1"></param>
/// <param name="t2"></param>
/// <returns></returns>
protected bool less(T t1, T t2)
{
return t1.CompareTo(t2) < 0;
}
protected void Swap(int i,int j,T[] nums)
{
T temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
约定接口:比较函数,交换函数。
冒泡排序的思想是从0->i 依次比较相邻元素,如果大于或者小于,就交换位置,每遍历一次,最大/最小的就跑到最高位置去, 走一次遍历可以把一个数排到最高位置, 因此需要N*N-i 次 ,算法复杂度为:On2。
因为遍历一次就可以得到一位排序好的数, 因此在第二次遍历的需要减去i;如果遍历一次,一次都不需要交换,则不需要再排序了。
基本冒泡排序
public override void sort(T[] nums)
{
for (int i = 0; i < nums.Length - 1; i++)
{
bool isNeed = false;
for (int j = 1; j < nums.Length - i; j++)
{
if (less(nums[j],nums[j-1]))
{
Swap(j,j-1,nums);
isNeed = true;
}
}
if (!isNeed)
{
break;
}
}
}
关于优化
1.基于冒泡排序的 优化,在需要交换的时候,还可以记录下 当前需要交换的位置,把它视作边界;
排序后有序的边界,然后下次就不用全部再走一遍了。
2. 升级版鸡尾酒排序, 思路就是一前一后遍历, 排序就像摆钟 , 这种情况适合在数组中已经有很多有序的数的情况下, 排序次数在以上是最少的。
优化边界版:
这种 情况是在于 2,1,3,4,5,6,7,8 这种情况, 按照上面的逻辑 ,最后一轮 发现 2 ,1交换,然后继续,2,3, 3,4 ....直到结束, 实际上后面都是有序的,再比较也没意义。
因此只需要记录下边界 ,遍历到下标为1 ,就可以了。
/// <summary>
/// 冒泡排序 优化版 , 加外框,在每轮排序后,记录下来最后一次元素交换的位置,
/// 该位置即为无序数组的边界, 往后就是有序数组了
/// </summary>
/// <param name="nums"></param>
public void BorderBubleSort(T[] nums)
{
for (int i = 0; i < nums.Length - 1; i++)
{
bool isNeed = false;
int border = nums.Length - 1;
for (int j = 1; j <border; j++)
{
if (less(nums[j], nums[j - 1]))
{
Swap(j, j - 1, nums);
isNeed = true;
border = j;
}
}
if (!isNeed)
{
break;
}
}
}
升级版鸡尾酒排序
加了边界优化,每加边界这里是border就是 nums.length-1-i, 双向冒泡排序。
鸡尾酒排序,排序过程是双向的,因此可以防止出现很多有序的情况还继续比较;
这个非常适用于 数组已经是大部分有序的情况。
/// <summary>
/// 升级版 冒泡排序-鸡尾酒排序, 一前 一 后,
/// </summary>
/// <param name="nums"></param>
public void CocktailSort(T[] nums)
{
for (int i = 0; i < nums.Length/2; i++)
{
bool isSort = false;
int border = nums.Length - 1;
for (int j = i; j <border; j++)//从 i
{
if (less(nums[j],nums[j+1]))
{
Swap(j,j+1,nums);
isSort = true;
border = j;
}
}
if (!isSort)
{
break;
}
isSort = false;
border = nums.Length - 1;
for (int j = border; j >i; j--)
{
if (less(nums[j], nums[j - 1]))
{
Swap(j, j - 1, nums);
isSort = true;
border = j;
}
}
if (!isSort)
{
break;
}
}
}