c语言 算法 o(n),【算法】一般冒泡排序 O(n^2) 稳定的 C语言

冒泡排序

一、算法描述

假设序列中有N个元素:

第一趟选取第一个元素作为关键字,从左至右比较,若遇到比它小的则放到它左边(也即两数进行交换),若遇到比它大的,则改为选取该元素作为关键字完成后续的比较,第一趟则将最大的数调整至序列的最末位置

第二趟选取第一个元素作为关键字,从左至右比较,若遇到比它小的则放到它左边(也即两数进行交换),若遇到比它大的,则改为选取该元素作为关键字完成后续的比较,第二趟则将倒数第二大的数调整至序列的倒数第二位置

第三趟选取第一个元素作为关键字,从左至右比较,若遇到比它小的则放到它左边(也即两数进行交换),若遇到比它大的,则改为选取该元素作为关键字完成后续的比较,第三趟则将倒数第三大的数调整至序列的倒数第三位置

第m趟选取第一个元素作为关键字,从左至右比较,若遇到比它小的则放到它左边(也即两数进行交换),若遇到比它大的,则改为选取该元素作为关键字完成后续的比较,第m趟则将倒数第m大的数调整至序列的倒数第m位置

第N趟选取第一个元素作为关键字,从左至右比较,若遇到比它小的则放到它左边(也即两数进行交换),若遇到比它大的,则改为选取该元素作为关键字完成后续的比较,第N趟(即最后一次)则将倒数第N大(即最小的)的数调整至序列的倒数第N位置(即首位)

注:当没有发生过记录交换,则算法终止

即每次选取第一个元素作为主元往后进行比较,若遇到比它小的则放到它左边(即进行交换),若遇到比它大的则选取大的作为主元进行后续比较,每趟选取了无序队列中最大元素放置无序列最后位,当一趟比较没有发生交换则为有序序列,即像吐泡泡一样第一次把最大的数吐到最末位,第二趟把倒数第二大的数吐到倒数第二位。。。。。

二、算法分析

当原始数据正向有序时为最好情况,此时只需进行一趟排序,作n-1次比较,因此最好情况下的时间复杂度是O(n)

当原始数据反向有序时为最坏情况,此时需进行n-1趟排序,这样需n(n-1)/2次比较,移动元素3n(n-1)/2次,因此最坏情况下时间复杂度为O(n^2)

综上,因此冒泡排序总的平均时间复杂度为 O(n^2) ,且只需定义一个临时变量用于交换,因此空间复杂度为O(1)

冒泡排序就是把小的元素往前调或者把大的元素往后调。比较是相邻的两个元素比较,交换也发生在这两个元素之间。所以,如果两个元素相等,我想你是不会再无聊地把他们俩交换一下的;如果两个相等的元素没有相邻,那么即使通过前面的两两交换把两个相邻起来,这时候也不会交换,所以相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法

三、算法实现代码

定义顺序表代码:

typedef struct list {

int Size;//大小

int Elements[MaxSize];//用数组存放

}List;//定义顺序表

定义冒泡排序代码:

void Maopaopaixu(List*lst)

{

int i, j;

int temp;//用于交换

bool sorted;//用于判别是否发生过交换

sorted = false;

i = lst->Size - 1;//用于记录趟数

while (i > 0 && !sorted) //当i<=0时(已经完成了N趟排序)或sorted为ture时(某趟没有发生交换)退出

{

sorted = true;

for (j = 0; j < i; j++)//完成0到i期间的比较,i逐渐变小

{

if (lst->Elements[j + 1] < lst->Elements[j])//若主元大于需比较的也即其后面的元素,进行交换,也即

{ //放到他左边若小于或等于,不做任何处理,也即换取了后一个数作为主元

temp = lst->Elements[j + 1];

lst->Elements[j + 1] = lst->Elements[j];

lst->Elements[j] = temp;

sorted = false;//若发生交换则为false,若该趟不发生一次交换,则sorted一直为true

}

}

i--;//完成一次趟数减一

}

}

四、实例测试代码

#include

#include

#include

#include //布尔类型头文件,需支持C99

#define MaxSize 99

typedef struct list {

int Size;//大小

int Elements[MaxSize];//用数组存放

}List;//定义顺序表

void Maopaopaixu(List*lst);//冒泡排序函数声明

int main(void) {

List a;//定义一个顺序表对象a

int i;

srand((unsigned)time(NULL)); //随机数种子

a.Size = 10;//定义大小为10

for (i = 0; i<10; i++)

{

a.Elements[i] = rand() % 10;//初始化顺序表

}

printf("初始原表为:");

for (i = 0; i < 10; i++)

{

printf("%d ", a.Elements[i]);

}

printf("

");

Maopaopaixu(&a);//调用冒泡排序函数,修改值需传入地址

printf("经冒泡排序:");

for (i = 0; i < 10; i++)

{

printf("%d ", a.Elements[i]);

}

getchar();

return 0;

}

void Maopaopaixu(List*lst)

{

int i, j;

int temp;//用于交换

bool sorted;//用于判别是否发生过交换

sorted = false;

i = lst->Size - 1;//用于记录趟数

while (i > 0 && !sorted) //当i<=0时(已经完成了N趟排序)或sorted为ture时(某趟没有发生交换)退出

{

sorted = true;

for (j = 0; j < i; j++)//完成0到i期间的比较,i逐渐变小

{

if (lst->Elements[j + 1] < lst->Elements[j])//若主元大于需比较的也即其后面的元素,进行交换,也即

{ //放到他左边若小于或等于,不做任何处理,也即换取了后一个数作为主元

temp = lst->Elements[j + 1];

lst->Elements[j + 1] = lst->Elements[j];

lst->Elements[j] = temp;

sorted = false;//若发生交换则为false,若该趟不发生一次交换,则sorted一直为true

}

}

i--;//完成一次趟数减一

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值