一、时间复杂度
将程序执行的计算步骤的总和叫做时间复杂度
时间复杂度实际上用来描述算法时间效率
例:如T(n)=n2+5n+6与T(n)=4n2+2n+1它们的频度不同,但时间复杂度相同,都为O(n2)。随着问题规模n的不断增大,上述时间复杂度不断增大,算法的执行效率越低。
总结:大O表示法就是将一个T(n)时间复杂度的系数去掉只留下最特征的部分就是大O表示法。
引用:

二、排序
常用排序:
冒泡排序 - (交换排序) 、快速排序 - (交换排序)、
选择排序 - (选择排序)、堆排序 - (选择排序)、
直接插入排序 - (插入排序)、希尔排序 - (插入排序)、
(归并排序、、桶/基数排序)
——————————————
冒泡排序
思路:
1.重复遍历要排序的数列n个元素,一次比较相邻两个元素 一次比较,保证右边的元素始终大于左边的元素;
(第一轮结束后,数列中最后一个元素一定是当前数列中最大值)
2.对数列当中剩下的n-1个元素,再次执行步骤1
3.对于长度为n的数列,一共需要执行n-1次轮的比较
"""冒泡排序"""
def bubble_sort(lst):
for i in range(len(lst) - 1):
for j in range(len(lst) - 1 - i):
if lst[j] > lst[j + 1]:
lst[j], lst[j + 1] = lst[j + 1], lst[j]
return lst
l1 = [33, 11, 44, 22, 55, 66, 12, 42, 23, 45, 97, 54]
print(bubble_sort(l1))
#[11, 12, 22, 23, 33, 42, 44, 45, 54, 55, 66, 97]
————————————————
选择排序
思路:
1.遍历待排序数列,并定义当前位置的元素为此次循环最小值
(首先找到最小的元素)
2.若最小元素不是待排序数列的第一个元素,将其和第一个元素互换
3.将该元素与剩下的元素依次比较寻找最小元素,重复1,2直至结束
"""选择排序"""
def select_sort(lst):
for i in range(len(lst)):
min = i
for j in range(i + 1, len(lst)):
if lst[j] < lst[min]:
min = j
lst[i], lst[min] = lst[min], lst[i]
return lst
import random
lst = [random.randint(1, 22) for i in range(5)]
print(lst)
print(select_sort(lst))
# [4, 8, 13, 6, 3]
# [3, 4, 6, 8, 13]
————————————————
直接插入排序
思路:
将待排序数列中的所有元素依次跟前面已经排好的元素相比较,如果选择的元素比已排序的元素小,则交换位置,直到遍历过全部元素
注意:遍历待排序数列中所有元素,默认索引为0的元素已排序,所以从1开始
"""插入排序"""
def inset_sort(lst):
for i in range(1,len(lst)):
for j in range(i,0,-1):
#从第i元素开始向前比较,如果小于前面一个元素 则交换位置
if lst[j] < lst[j-1]:
lst[j],lst[j-1] = lst[j-1],lst[j]
return lst
import random
lst = [random.randint(10,66) for i in range(10)]
print(lst)
print(inset_sort(lst))
# [62, 32, 20, 56, 39, 39, 63, 16, 15, 48]
# [15, 16, 20, 32, 39, 39, 48, 56, 62, 63]
————————————————
快速排序
思路:通过多次比较和交换来实现
1.从待排序数列中挑选一个元素,称为"基准"(一般为索引为0的元素)
2.重新排序数列,所有元素中比基准值小的放在基准前面,比基准值大的放在基准后面,排序后该基准处于数列中间位置,该操作可称为分区操作
3.递归调用,把左右两侧排序完毕
def quick_sort(lst, start, end):
if start < end:
s = start
e = end
num= lst[s]
while s < e:
while s < e and lst[e] > num:
e = e - 1
lst[s] = lst[e]
while s < e and lst[s] < num:
s = s + 1
lst[e] = lst[s]
#剩下一个s的坑,用来放num
lst[s] = num
# 这个地方用递归,对左右两边的排列再次调用快排
quick_sort(lst, start, s - 1)
quick_sort(lst, e + 1, end)
return lst
lst =[random.randint(11,66) for i in range(5)]
print(lst) # [28, 41, 14, 42, 12]
res = quick_sort(lst, 0, len(lst) - 1)
print(res) # [12, 14, 28, 41, 42]
—————————————————————————————
堆排序
堆是一个近似完全二叉树的结构
并同时满足堆积的性质:
即子结点的键值或索引总是小于(或者大于)它的父节点
堆的操作:
在堆的数据结构中,堆中的最大值总是位于根节点
(在优先队列中使用堆的话堆中的最小值位于根节点)
堆中定义以下几种操作:
最大堆调整:将堆的末端子节点作调整,使得子节点永远小于父节点
创建最大堆:将堆中的所有数据重新排序
堆排序:移除位在第一个数据的根节点,并做最大堆调整的递归运算
def d_sort(arr):
l = len(arr)
for i in range(int(l / 2 - 1), -1, -1):
adjustHead(arr, i, l)
# 交换堆顶和最后一个元素,并调整堆结构
for j in range(l - 1, 0, -1):
arr[0], arr[j] = arr[j], arr[0] # 将堆顶元素和末尾元素进行交换
adjustHead(arr, 0, j) # 重新对对进行调整
for k in range(0, l):
print(arr[k])
# 构造大顶堆
def adjustHead(a, i, l):
temp = a[i] # 取出当前元素
k = 2 * i + 1 # 从左子节点开始,即2*i+1
while k < l:
# 若果左子节点小于右子节点,k指向右子节点
if k + 1 < l & a[k] < a[k + 1]:
k = k + 1
# 如果子节点大于父节点,将子节点赋值给父节点,并将子节点下标记录下来,
#后面将父节点值赋值给该子节点
if a[k] > temp:
a[i] = a[k]
i = k
else:
break
k = 2 * k + 1 # 把该节点当作父节点,继续操作
a[i] = temp # 将父节点值赋值给该子节点
if __name__ == "__main__":
a = [10, 2, 4, 5, 3,]
d_sort(a)
#2 3 4 5 10
Python排序算法详解:冒泡、选择、插入、快速、堆排序
本文介绍了排序算法的时间复杂度和大O表示法,详细讲解了冒泡排序、选择排序、直接插入排序和快速排序的思路,并提到了堆排序的概念和操作。这些排序算法在Python中的应用广泛,理解其工作原理对于优化代码性能至关重要。
3441

被折叠的 条评论
为什么被折叠?



