冒泡排序:把小的元素往前调或者把大的元素往后调。比较是相邻的两个元素比较,交换也发生在这两个元素之间。所以,如果两个元素相等,是不必再去交换的;如果两个相等的元素没有相邻,那么即使通过前面的两两交换把两个相邻起来,这时候也不会交换,所以相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法。
//冒泡排序在平均和最坏情况下的时间复杂度都是O(n^2),最好情况下是O(n);
void BubbleSort(int arr[], int len)
{
int tmp = 0;
for (int i = 0; i < len - 1; ++i)
{
for (int j = 0; j < len - i - 1; ++j)
{
if (arr[j] > arr[j + 1])
{
tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}
冒泡排序优化:针对的是序列本身有序或者序列元素都相等的情况,比如1 2 3 4 5或者 1 1 1 1 1这样形式的数据;另一种是像3 2 1 4 5 6这样的数据,其特点是后半部分数据已经有序。优化的方法都是减少不必要的比较次数。
void BubbleSort1(int arr[], int len)
{
int tmp = 0;
bool flag = false;
int lastSawpIndex = 0;//记录一轮最后一次交换的位置
int swapTimes = 0;
for (int i = 0; i < len - 1; ++i)
{
flag = false;
for (int j = 0; j < len - i - 1; ++j)
{
if (arr[j] > arr[j + 1])
{
tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
lastSawpIndex = j;//更新最后一次交换的位置
flag = true;
}
swapTimes++;
}
i = len - 1 - lastSawpIndex; //优化方案二:计算"实际"有序区间的大小,减少不必要的比较
if (!flag) //优化方案一:记录第一趟交换次数,交换的次数为0,说明有序,不需要再排序,跳出循环
{
printf("%d\n", swapTimes);
break;
}
}
printf("%d\n", swapTimes);
}
//优化方案三:双向排序
void cocktail_sort(int arr[],int len)
{
int left = 0, right = len - 1;
int temp;
while (left<right)
{
for (int i = left; i<right; i++)//找到当前排序元素里最大的那个,放在右侧
{
if (arr[i]>arr[i + 1])
{
temp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = temp;
}
}
right--;
for (int j = right; j > left; j--)//找到当前排序元素里最小的那个,放在左侧
{
if (arr[j - 1] > arr[j])
{
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
left++;
}
}
}