希望大家能够给一个关注,我会努力写好每一篇文章的
每一趟排序,从左向右两两比较,如果左边大于(为了排序的稳定性,是大于而不是大于等于)右边则两两交换,否则不交换(默认为升序排列)
//冒泡排序 时间复杂度O(n^2) 空间复杂度O(1) 稳定性:稳定
void Bubble_Sort(int *arr, int len)
{
for(int i=0; i<len-1; i++)//控制循环趟数 len-1趟
{
for(int j=0; j+1<len-i; j++)//控制每一趟具体的比较过程 j代表两两比较的左值下标 两两比较的右值下标j+1
{
//从左向右 两两比较,如果左值大于右值 则交换
if(arr[j] > arr[j+1])
{
int tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
}
}
}
}
如果在第i次比较后,整个排序序列为有序序列时,按上述代码,仍然要将剩余轮数比较结束,这就是可以优化的点。
设置一个标记flag,当循环中没有元素相互交换时就跳出循环
//冒泡的优化
void Bubble_Sort2(int *arr, int len)
{
for(int i=0; i<len-1; i++)//控制循环趟数 len-1趟
{
bool tag = true;//下一个标记
for(int j=0; j+1<len-i; j++)//控制每一趟具体的比较过程 j代表两两比较的左值下标 两两比较的右值下标j+1
{
//从左向右 两两比较,如果左值大于右值 则交换
if(arr[j] > arr[j+1])
{
int tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
tag = false; //如果存在交换 则标价修改为假
}
}
if(tag)//如果此时tag这个标记还是true,则代表这一趟排序没有左右交换过一次,也就代表着完全有序
{
//return;
break;
}
}
}
优化前:我们将标记注释掉,定义一个count计数器来统计函数比较的次数,在函数中将其打印出来,结果如下图
优化后
void show(int* arr,int len)
{
for (int i = 0; i < len; i++)
{
printf("%d ", arr[i]);
}
}
int main()
{
int arr[] = { -43,57,-71,47,3,30,-85,6,60,-59,0,-46,-40,-73,53,68,-82,-54,88,73,20,-89,-22,39,55,-26,95,-87,-57,-86,28,-37,43,-27,-24,-88,-35,82,-3,39,-85,-46,37,45,-24,35,-49,-27,-96,89,87,-62,85,-44,64,78,14,59,-55,-10,0,98,50,-75,11,97,-72,85,-68,-76,44,-12,76,76,8,-75,-64,-57,29,-24,27,-3,-45,-87,48,10,-13,17,94,-85,11,-42,-98,89,97,-66,66,88,-89,90,-68,-62,-21,2,37,-15,-13,-24,-23,3,-58,-9,-71,0,37,-28,22,52,-34,24,-8,-20,29,-98,55,4,36,-3,-9,98,-26,17,82,23,56,54,53,51,-50,0,-15,-50,84,-90,90,72,-46,-96,-56,-76,-32,-8,-69,-32,-41,-56,69,-40,-25,-44,49,-62,36,-55,41,36,-60,90,37,13,87,66,-40,40,-35,-11,31,-45,-62,92,96,8,-4,-50,87,-17,-64,95,-89,68,-51,-40,-85,15,50,-15,0,-67,-55,45,11,-80,-45,-10,-8,90,-23,-41,80,19,29,7 };
Bubble_Sort(arr, sizeof(arr) / sizeof(int));
show(arr, sizeof(arr) / sizeof(int));
return 0;
}
该数组是我在刷力扣时老通不过的一组例子,所以我现在写的所有有关排序的例子都用它来测试!!
选择排序也叫简单选择排序,在每一趟排序时,找到最小值,将其与第一个值进行交换,冒泡排序是每一趟结束后能找到最大值,两种算法有相似性
//选择排序 时间复杂度O(n^2) 空间复杂度O(1) 稳定性:不稳定
void Select_Sort(int *arr, int len)
{
for(int i=0; i<len-1; i++)//控制循环的趟数 len-1趟
{
int min = i;//让min 保存 这一趟循环中"待排序序列"的第一个值的下标
for(int j=i+1; j<len; j++)//找到这一趟排序中,待排序序列的最小值的下标,用min保存
{
if(arr[j] < arr[min])//如果发现了比min指向的值还要小的值,则min修改指向
{
min = j;
}
}
//此时,里面这一层for循环跑完,代表着min正保存着待排序序列的最小值的下标
// 而此时待排序序列的第一个值的下标,由变量i保存
if(min != i)//如果min==i, 代表着待排序序列最小值就是待排序序列第一个值
{
int tmp = arr[min];
arr[min] = arr[i];
arr[i] = tmp;
}
}
}
在主函数中调用选择排序函数,其余同上即可!
冒泡排序和选择排序是最简单最基础的排序算法,是C语言入门时必须要求要掌握的两种算法,缺点是时间复杂度较高,当数据量较大时建议根据情况选择其他算法。