数据结构与算法——数列排序【冒泡排序、选择排序】

 如有错误,请指正,蟹蟹。 

一、冒泡排序

“如果是大数往下沉的冒泡,就是从左开始;如果是小数往上浮的冒泡,就是从右开始”。

  • 从右往左: 最小值被移到了最左边。 【冒泡法】的本意
  • 从左往右: 最大值被移到了最右边。 此时其实应该叫 【沉石法】
  • 最坏时间复杂度:O(n^2)
    最优时间复杂度:O(n^2)
    平均时间复杂度:O(n^2)
    最坏空间复杂度: 总共 O(n),需要辅助空间 O(1)

从左往右还是从右往左好像都差不多吧,这里是从小到大排序,从右往左,两两比较,右边小的则交换位置,将小的放左边,经过一轮就可以得出一个左边的最小值,在之后的排序中不再参与比较。

最小的已经在左边了,继续从最右边开始重复比较,第二次排序不用再比较第一个值,因为已经是上一轮最小了,以此类推,每循环排序一次,需要排序的值就少一个

n=len(arr)
for i in range(n):
    for j in range(n-1,i,-1):
         if arr[j-1]>arr[j]:
            arr[j],arr[j-1]=arr[j-1],arr[j]

从左往右两两比较,则和上面的内外循环相反,外循环是右边往左边的i,内循环是左边往右边的j

n=len(arr)
for i in range(n-1,0,-1):
    for j in range(1,i+1):
        if arr[j-1]>arr[j]:
            arr[j],arr[j-1]=arr[j-1],arr[j]

c语言版:源码来自《C语言从入门到精通》

需要注意的是,在交换两个数值时的先后顺序

#冒泡法排序指的是在排序时,每次比较数组中相邻的两个数组元素的值,将较小的数(从小到大排列)排在较大的数前面。
#include<iostream.h>
int main()
{
int i,j;
int a[10];
int iTemp;
printf("为数组元素赋值:\n");

for(i=0;i<10;i++)
{
    printf("a[%d]=",i);
    scanf("%d",&a[i]);
}

for(i=1;i<10;i++)
{
    for(i=9;j>=i;j--)
    {
        if(a[j]<a[j-1])
        {
            iTemp=a[j-1]
            a[j-1]=a[j];
            a[j]=iTemp;
        }
    }
}

for(i=0;i<10;i++)
{
    printf("%d\t",a[i]);
    if(i==4)
        printf("\n");
}
return 0;
}

二、选择排序

线性搜索数列并找到最小值。将最小值替换为列中左端的数字并进行排序。如果最小值已经在左端,则不执行任何操作。重复相同操作,直到所有数字都被排序。

选择法排序指每次选择所要排序的数组中的最大值(这里指由大到小排序,由
小到大排序则应选择最小值)的数组元素,将这个数组元素的值与最前面没有进行
排序的数组元素的值互换。——《C语言从入门到精通》

1、定义变量
1)int i,j;
定义两个变量i和j,i用来做外层循环,j用来做内层循环。
外层循环:循环对比值,如上的每一行,一行更换一个对比值i。
内层循环:查找剩余的值的最小值。
2)int a[10];
定义数组a长度为10
3)int iTemp;
当前值,包含外循环和内循环的当前值。
4)int iPos;
定义iPos为当前值的地址。
2、键盘输入,为数组赋值
for(i=0;i<10;i++)
{
printf("a[%d]=",i)
scanf("%d",&a[i])
}
# 下标从0-9,刚好长度10,a[%d]是值,&a[i]输入的值是指定地址
3、外层循环
#第一次循环i为9,第二次循环i为6,以此类推。
for(i=0;i<9;i++)    # 外循环是从第一个值开始到倒数第二个值,因为最后一个值后面没有值了,也没有值能和它对比了,所以i不包括最后一个--下标为9,所以i是0-8,长度为9。
{
iTemp=a[i];    # 将a[i]设为外循环的当前值,iPos为地址下标。
iPos=i;
for(j=j+1;j<10;j++)    # 内循环j是从i的下一个剩余值开始循环的,j是包括最后一个值的,因为最后一个值也需要进行最小值的比较。
{
# 判断剩余的值中的最小值。a[j]为iTemp当前值,用来做对比值,其右边剩余的值为被对比值,找出最小值,将其更新赋给iTemp。
if(a[j]<iTemp)
{
iTemp=a[j];    
iPos=j;
}
}
# 两个值--交换位置,更新赋值。
# 将a[i]的值赋值给a[iPos],将iTemp的值赋值给a[i]。顺序不能反过来,不然a[i]的值被iTemp替换了,就无法知道它的值是多少,就无法赋值给a[iPos]。
a[iPos]=a[i];    
a[i]=iTemp;
}

外循环:(如上每一行的)a[i]为iTemp,和右边剩余的值中的最小值互换位置(内循环判断最小值),如果没有比它小的则不用换,进行下一个循环。
内循环:如果当前值iTemp小于剩下的某个值,则当前值iTemp依旧是当前值iTemp并继续和下一个值对比,
如果剩下的某个值小于当前值,则该某个值就重新设为当前值iTemp,循环,新的当前值iTemp继续和其下一个值进行比较大小。

iPos默认是先从i开始为0,在对比过程中,知道下标j=4为最小值,故ipos=j=4,交换的时候把下标0的值赋值更新给下标为4的;iTemp为a[j]的值2,赋值更新给a[i],使得a[i]为2。

#输出数组
for(i=0;i<10;i++)
{
printf("%d\t",a[i])
}

源码来自《C语言从入门到精通》

#include<studio.h>
int main()
{
int i,j;
int a[10];
int iTemp;
int iPos;
printf("为数组元素赋值:\n");
for(i=0;i<10;i++)
{
    printf("a[%d]=",i);
    scanf("%d",&a[i]);
}

for(i=0;i<9;i++)    
{
    iTemp=a[i]; 
    iPos=i;
    for(j=j+1;j<10;j++)    
        {
            if(a[j]<iTemp)
                {
                    iTemp=a[j];    
                    iPos=j;
                }
        }
    a[iPos]=a[i];    
    a[i]=iTemp;
}

for(i=0;i<10;i++)
{
printf("%d\t",a[i]);
if(i==4)
    printf("\n");
}
return 0;
}

python版:

时间复杂度:O(n^2)

空间复杂度:O(1)

def selection_sort(arr):
    n = len(arr)
    for i in range(n - 1):
        # 将起始元素设为最小元素
        min_index = i
        for j in range(i + 1, n):    # 从左往右,找出最小值放在左侧,已经放在左侧的将不再对比
            if arr[j] < arr[min_index]:
                min_index = j    # 当前值小于上面的最小值,则将当前值重新赋值给最小值min_index
        arr[min_index], arr[i] = arr[i], arr[min_index]    # 交换位置
array = [26, 11, 99 , 33, 69, 77, 55, 56, 67]
print("原列表:")
print(array)
selection_sort(array)
print("排序后的列表:")
print(array)

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
冒泡排序是一种简单的排序算法,它重复地遍历待排序的元素,比较相邻元素的大小,如果顺序错误就交换它们,直到没有需要交换的元素为止。下面是冒泡排序的C语言实现: ```c void bubbleSort(int arr[], int n) { for(int i = 0; i < n-1; i++) { int flag = 0; //是否冒泡 for(int j = 0; j < n-1; j++) { if(arr[j > arr[j+1]) { swap(&arr[j], &arr[j+1]); flag = 1; } } if(flag == 0) { //如果没有发生交换,说明数组已经有序,可以提前结束循环 break; } } } ``` 在这个实现中,冒泡排序函数`bubbleSort`接受一个整型数组`arr`和数组长度`n`作为参数。它使用两层循环来遍历数组,并通过比较相邻元素的大小来进行交换。内层循环每次将最大的元素冒泡到数组的末尾。外层循环控制了冒泡的轮数,每一轮都会将当前未排序的最大元素放在正确的位置上。如果在某一轮的冒泡过程中没有发生交换,说明数组已经有序,可以提前结束循环,从而提高算法的效率。 需要注意的是,上述代码中使用了一个`swap`函数来交换两个元素的值,你可以根据需要自行实现该函数。此外,为了减少冒泡排序的时间复杂度,可以在内层循环中添加一个标志位`flag`,用于标记是否发生了交换。如果某一轮的冒泡过程中没有发生交换,说明数组已经有序,可以提前结束循环。这样可以避免不必要的比较和交换操作,提高排序的效率。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值