• 算法-选择、冒泡、插入


    问题:一列数组,从小到大依次排序

    一、选择排序

    原理:

      比方说有一个数组:data = [12,45,2,48,66,2,1,56,36,90,5,10,503]

      从第一个数字开始,后面的数字依次与第一个比较,如果小于第一个,则和第一个交换位置。比如这里的 1 < 12,则会变成 1,45,2,48,66,2,12,56,36,90,5,10,503,这样下来,最小的会被放在第一个的位置上

      然后从第二个数字开始,后面的数字依次与第二个比较,这样,倒数第二小的数字会被放在第二个位置上。

    怎么写?解决两个问题:

    1. 要写几个for循环?
    2. 找出每个for循环的边界

    那么,我们的选择排序要几层循环呢???答案是两层。

    1、外层是往第几个位置上放元素/交换元素

      i~[0,len]  ##为啥从 0 开始?因为数组下标是从 0 开始

    2、里层是该位置的后面的每一个元素跟其比较

      j~[i+1,len] 

    这里我们用Python实现:

    # -*- coding: utf-8 -*-
    #选择排序
    data = [12,45,2,48,66,2,1,56,36,90,5,10,503]
    for i in range(len(data)):  # 外层,定义第几个位置
        for j in range(i+1,len(data)):  # 内层,后面的每一个元素与当前外层元素相比较
            #//如果后面的元素比我选择元素还小 就互换位置
            if data[j] < data[i] :
             #互换位置
                temp = data[i]
                data[i]=data[j]
                data[j] = temp
    print(data)

    二、冒泡排序

    原理:

    data = [12,45,2,48,66,2,1,56,36,90,5,10,503]

      比较两个相邻的比较,如果前面的比后面的大,就交换位置,一直比较,这样比较完一轮,最大的值就被放在了最后一位;

      再比较,一轮,第二大的就放在了代数第二位,以此类推……

    怎么写?同样解决两个 for 循环的边界

    1、外层 for 循环写轮次,第一轮就是把最后一个位置确定了……

      i~[0,len-1]

    2、内层就是把之前的元素相比较

      j~[0,len-1-i]

    # -*- coding: utf-8 -*-
    # 冒泡排序
    for i in range(len(data)-1):   # 控制排好的第几个位置
        for j in range(len(data)-i-1):  # 控制前面的位置
            # 比较左右两个值
            if data[j]>data[j+1]:
                temp = data[j]
                data[j]=data[j+1]
                data[j+1]=temp
    print(data)

    三、插入排序

    原理: 

    data = [12,45,2,48,66,2,1,56,36,90,5,10,503]

      相当于打扑克牌抓牌,第一张牌放手里,抓第二张,假设大于第一张就放第一张后面,以此类推……

      数组内理解:把一个数组分成两部分,后面半部分就是我们要抓的牌(需要排序的元素),前面半部分就是已经排好的,也就是已经摸到手里的牌

    以我们的数组来看,一开始我们抓到 12 在手里,然后去抓一张 45 ,跟 12 比较如果比 12 小就放在 12 前面,45 > 12 所以放在 12 后面,这两张就是我们手里的牌了;再继续抓一张 2 跟 45 和 12 比较,2 < 45 ,那么 45 往后挪一位,再和 12 比较, 2< 12 那么12 再往后挪一位,第一位就是 2 ;现在是 2,12,45 假设后面一个是 10 怎么办?把 10 抓过来,依次跟 45,12,10 比较,10 < 45 ,所以 45 往后挪一位到 10 的位置上,再 10 和 12 比较,10 < 12,那么 12 往后挪一位,10 到 12 的位置上,10 > 2 ,所以 2 不用挪……

    for 循环也是两层:

    1、外层 for 循环控制你要抓的牌

      i~[0,len-1]

    2、里层 for 循环是抓到的牌依次和手里的牌比较

      j~[0,i-1]

    # -*- coding: utf-8 -*-
    # 插入排序
    for i in range(len(data)):   # 已经抓到手里的牌
        for j in range(i-1,-1):  # 每次抓到手里的牌
            # 如果抓到的牌大于手里的,那么手里的往后挪
            if data[j]>data[i]:
                data[j+1] = data[j]
    print(data)

    特殊情况:

    # -*- coding: utf-8 -*-
    # 插入排序
    for i in range(len(data)):  # 控制手上已经有的数字个数
        newget = data[i]    # 每次新抓到的数字,如果不存起来,已有的数字后移会覆盖掉新抓到的
        for j in range(i-1,-1): # 新抓的数字跟手中已有的比较
            if data[j] > newget:
                data[j+1] = data[j]
            else:   # 如果抓到的新数字小于最后一个,那就不用比了
                break
            data[j+1] = newget  # 不比,把新抓到的放到最后
    print(data)
  • 相关阅读:
    jquery 图片播放器插件(支持自己设定时间,自己设定是否自动播放)
    ie6下bug集合(二)li之间空隙bug
    大小不固定的图片和多行文字的垂直水平居中
    解决IE6下 position的fixed定位问题
    C# 编写不安全代码
    委托和事件的使用
    如何删除win7桌面的库和家庭组图标
    gcc g++ 区别
    Java 访问注册表
    C# 通过反射类动态调用DLL方法
  • 原文地址:https://www.cnblogs.com/xiaowenshu/p/10126562.html
Copyright © 2020-2023  润新知