python常见排序算法--day06

常见排序算法

先简单讲解一下如何交换两个变量的值

  1. 创建临时变量
  2. 直接交换(a,b = b,a)
例:
临时变量:
c = a
a = b
b = c




#直接交换
a , b = b , a

冒泡排序

两两比较,找最大值换到最后,再找次大值,放次之

以下以找最大值为例子:

# 冒泡排序 大数上浮法、小数下沉法(每次找最小值往最前边排或每次找最大值往最后排)
arr = [30,8,-10,22,26,3,2,9,11]

def bubble_sort(arr):
    for i in range(0, len(arr)-1):  #为了控制比较操作的循环次数
        for j in range(0, len(arr)-1-i):  #选择操作的元素(索引下标)
            if arr[j] >= arr[j+1]:
                arr[j], arr[j+1] = arr[j+1], arr[j]
            else:
                pass     #空语句,防止报错
    return arr
if __name__ == '__main__':   #python的main函数 防止被别的模块导入时执行
    a = bubble_sort(arr)
    print(a)


结果:
[-10, 2, 3, 8, 9, 11, 22, 26, 30]

图解:

在这里插入图片描述

选择排序

每次找最小值,以假设的最小值进行位置互换。(循环后面全部找出最小值后换)
[30,8,-10,22,26,3,2,9,11]
第一次 假设30最小,在其他当中找最小值,即-10,进行位置互换
[-10,8,30,22,26,3,2,9,11]
第二次 假设8最小,在其他当中找最小值,即2,进行位置互换
[-10,2,30,22,26,3,8,9,11]

img

# 选择排序
# 类似于冒泡排序,每一次找到最小值
arr = [8,3,2,6,1,4,9,7]
def xuanze(arr):
    for i in range(0, len(arr)-1):  #控制循环的次数(即开始的起点)
        min = i    #假定第一个为最小值(创建个临时变量)
        for j in range(i+1, len(arr)):   #从开始起点循环到结束
            if arr[j] < arr[min]:    #如果小则交换,将下标交换
                min = j
        if i != min:   #循环结束,判断是否后面有小值,有则交换
            arr[i], arr[min] = arr[min], arr[i]
    return arr
if __name__ == '__main__':
    a = xuanze(arr)
    print(a)


结果:
[1, 2, 3, 4, 6, 7, 8, 9]

插入排序

默认第一个值为有序的,之后一次插入后面的每一个值(多次比较),最终得出排序结果。保证 i 前面的数都是有序

例:

[6,5,3,8,7,2,4]

第一次 假设第一位(6)有序(最小),将后一位(第二位)与第一位对比,若第二位小将其插入到第一位前作为第一位

[5,6,3,8,7,2,4]

第二次 假设前两位有序,将后一位(第三位)与第二位对比,若比第二位小,再与第一位对比,若比第一位大比第二位小则将其插入到第二位前作为第二位,反之若比第一位小则将其插入到第一位前作为第一位

[3,5,6,8,7,2,4]

第三次 假设前三位有序,将后一位(第四位)与第三位对比,,若比第三位大,则保持原位,默认前四位有序,若比第三位小,再与第二位和第一位(前面有序的全部)对比,若比第二位大比第三位小则将其插入到第三位前作为第三位,反之若比第一位大比第二位小则将其插入到第二位前作为第二位,若比第一位小则将其插入到第一位前作为第一位

[3,5,6,8,7,2,4]

img

#插入排序
num = [11,2,12,13,1,4]
def insert_sort(num):
    for i in range(0, len(num)-1):  #默认有序下标(i前包括i全部有序)
        for j in range(i+1, 0, -1):  #i+1 往前比较
            if num[j] < num[j-1]:
                num[j], num[j-1] = num[j-1], num[j]
    return num
insert_sort(num)   #函数调用
print(num)

计数排序

计数排序(Counting Sort)是一种不比较数据大小的排序算法,是一种牺牲空间换取时间的排序算法

计数排序适合数据量大且数据范围小的数据排序,如对人的年龄进行排序,对考试成绩进行排序等

找到待排序列表中的最大值 k,开辟一个长度为 k+1 的计数列表

例(元素不重复):

原容器:

arr = [2,3,1,6,5,7]

创建新容器(7+1)

arr0 = [0, 0, 0, 0, 0, 0, 0, 0]

下标 0 1 2 3 4 5 6 7

然后找与元素相同的下标值元素加1(两个就是2)

arr0 = [0, 1, 1, 1, 0, 1, 1, 1]

然后再将为1的导出

==> [1,2,3,5,6,7] 即排序成功

#计数排序
def counting_sort(array): #如果只有一个数无需排序直接返回
    if len(array) < 2:
        return array
    max_num = max(array)
    count = [0] * (max_num + 1)  #创建一个新列表,记录下标索引
    for num in array:  #寻找是否有元素相同的下标值,有则加一,并统计每个值的数量
        count[num] += 1
    new_array = list()  #创建空列表导出
    for i in range(len(count)):  #循环次数(遍历列表全部)
        for j in range(count[i]):  #循环次数(相同元素的数量)
            new_array.append(i)  #将元素i加入new_array
    return new_array


if __name__ == '__main__':
    array = [5, 7, 3, 7, 2, 3, 2, 5, 9, 5, 7, 6]
    print(counting_sort(array))


结果:
[2, 2, 3, 3, 5, 5, 5, 6, 7, 7, 7, 9]

二分查找

二分查找(折半查找):在有序序列中高效的查找指定的元素

#二分查找
def binary_search(list,item):
    """二分查找方法"""
    left = 0 # 定义最小下标
    right = len(list)-1 # 定义最大下标
    while left <= right: #while循环,保证可以遍历到指定区域的元素,直到被被寻找的值和中间值相等
        mid = int((left + right)/2) # 寻找数组的中间值
        guess = list[mid] # 获取列表最中间的元素
        if guess == item:
            return mid # 进行条件判断,将中间值和被寻找的值进行比较,相等则返回该值
        if guess > item:
            right = mid-1 # 如果被寻找的值小于中间值,则最大下标变化为中间值的前一个元素下标
        else:
            left = mid + 1 # 如果被寻找的值大于中间值,则最小下标变化为中间值的后一个元素下标
    return None
nums = [1,33,44,66,77,567,5677]
print(binary_search(nums,567))

结果:
5      #返回索引下标

函数

组织好的,可以重复使用的,用于实现特定功能的代码块

len(name)内置函数 len 官方写好的 input print。。。。都是内置函数

避免重复的进行代码书写,提高代码的复用率

函数的定义语法

格式:
def 函数名(参数1,参数2......):
    函数体
    return 语句

#return:返回函数的返回值
#return后边的代码不会再执行了哦
#函数的返回值 将结果返回给调用者

练习:

1、定义一个函数,求其绝对值

def my_abs(x):
    if x < 0:
        return -x
    else:
        return x

a = my_abs(-3)
print(a)
a = my_abs(1)
print(a)


结果:
3
1

2、定义函数,调用后输出“我叫XXX”

def out():
    print("我叫XXX")

b = out()
print(b)

c = out()   #函数名可以赋值给变量
c()         #变量即为函数的别名,函数名+()是执行


结果:
我叫XXX    
None  #函数无返回值
我叫XXX   
#None类型:NoneType的字面量,函数不使用return,返回的是None:返回值没有意义
#None声明无意义的变量
#name=None
#在if判断中:None===False

函数的传参

函数的参数:函数进行计算时,接受外部(调用时)提供的数据

传入参数的类型检查

def my_abs(x):
    if not isinstance(x,(int,float)): #判断如果不是int与float类型报错
        raise TypeError ("i'am sorry") #raise 用于在报错最后显示
    if x < 0:                          
        return -x
    else:
        return x

a = my_abs('a')
print(a)


结果:
Traceback (most recent call last):
  File "D:\pycharm\06-笔记.py", line 39, in <module>
    a = my_abs('a')
  File "D:\pycharm\06-笔记.py", line 33, in my_abs
    raise TypeError ("i'am sorry")
TypeError: i'am sorry     #显示

返回值

事实上,函数返回的是一个元组,多个变量可以同时接收一个元组

#返回值
def sum_01():
    a = 1
    b = 2
    return a,b    #同时返回多个值用 ,隔开即可(元组也可以省略外面的括号)

a = sum_01()   #因为只有一个接收变量,所以多个返回值会以元组的形式给他接收
print(a)
a,b = sum_01()  #多个返回值会以元组的形式返回
print(a)
print(b)

v,b,n = (3,4,5) #多个变量(与元组元素个数相同)接收元组,依次接收
print(v)
print(b)
print(n)


结果:
(1, 2)
1
2
3
4
5

位置参数

例:两个数字相加的函数的定义

在这里插入图片描述

a,b:形式参数
1,2:实际参数
数量不受限制(但形式参数与实际参数数量不同会报错)

形式参数与实际参数数量一致所以依次传递(即位置传参)

1、数量必须与定义时一致
2、位置必须与定义时一致

默认参数

def power(x, n=2):
    s = 1
    while n > 0:
        n = n - 1
        s = s * x
    return s


a = power(1)
print(a)

结果:
1

默认值参数设置的注意点

  1. 必选参数在前,默认参数在后(原因:可以把必选的传入完后,后面全部默认)
  2. 多个参数时,把变化小的放在后面。变化小的参数就可以作为默认值参数

好处:降低调用函数的难度

默认参数的坑:

def add_end(L=[]):
    L.append('END')
    return L

add_end()
add_end()


结果:
['END', 'END']
['END', 'END', 'END']

第一次调用add_end()时没有错误,第二次时,就会出现函数似乎记住了第一次调用的函数添加的end的列表

解释:
t(a)

结果:
1


[外链图片转存中...(img-OJj4Yp6U-1697433643414)]

> 默认值参数设置的**注意点**:
>
> 1. 必选参数在前,默认参数在后(原因:可以把必选的传入完后,后面全部默认)
> 2. 多个参数时,把变化小的放在后面。变化小的参数就可以作为默认值参数
>
> 好处:降低调用函数的难度



**默认参数的坑:**

```python
def add_end(L=[]):
    L.append('END')
    return L

add_end()
add_end()


结果:
['END', 'END']
['END', 'END', 'END']

[外链图片转存中…(img-11PgYsnB-1697433643414)]

第一次调用add_end()时没有错误,第二次时,就会出现函数似乎记住了第一次调用的函数添加的end的列表

解释:
默认参数必须指向不变对象!(数组可变)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值