面试:讲一讲冒泡排序?冒泡排序时间复杂度是多少?
冒泡排序是通过两层循环嵌套,将相邻元素比较大小,并向一端冒泡;外层遍历用于计次,内层则是用于比较和排序;外层每遍历一次,便可以将列表中一个最大值/最小值冒泡到序列尾部。因为进行了两次遍历,并且嵌套在一起,所以时间复杂度应该是O(n ^ 2)
def bubble_sort(alist): # 单词 bubble 泡泡
n = len(alist)
for i in range(0,n-1):
for j in range(0,n-1-i):
if alist[j] > alist[j+1]:
alist[j],alist[j+1] = alist[j+1],alist[j]
list = [4,3,2,1]
bubble_sort(list)
如果代码有疑惑,请先代入 alist = [4,3,2,1 ]试一试
# i = 0
j = 0
[3,4,2,1]
j = 1
[3,2,4,1]
j = 2
[3,2,1,4]
# i = 1
j = 0
[2,3,1,4]
j = 1
[2,1,3,4]
# i = 2
j = 0
[1,2,3,4]
注意点:外层每遍历一次,内层则是遍历完
if alist [ j ] > alist [ j + 1 ]
内层比较索引为 j 和 j+1,而与i 无关联,比较相邻元素大小,这是冒泡的真谛
range( 0 ,n - 1 ) 左包右不包
外层索引表示遍历次数,,简单的记忆是假设列表只有2个元素,则外层只需要遍历一次,所以range(n - 1) = range(1) ,得到 0,遍历一次
range( 0 ,n - 1 - i )
n 表示元素的个数,n - 1 表示末尾元素的索引,写在range内则不遍历最后一个元素,这是因为内层有j + 1可以得到下一个元素;-i 是因为经过冒泡, 末尾已排好序的不需要再经过遍历
在本次面试时,因为我只曾看过冒泡一眼,所以把函数写成了这样
def maopao(l):
n = len(l)
for i in range(n-1): # 0~4
for j in range(i+1,n):
if l[i] > l[j]:
l[i],l[j] = l[j],l[i]
list = [4,3,2,1]
maopao(list)
写成这样的原因,便是迷惑了for循环嵌套的执行顺序,认为内外循环差1,便可进行比较。但是这个程序是可以进行排序的,以下研究我写的到底是什么东西
*先代入 alist = [4,3,2,1 ]试一试
# i = 0
j = 1
[3,4,2,1]
j = 2
[2,4,3,1]
j = 3
[1,4,3,2]
# i = 1
j = 2
[1,3,4,2]
j = 3
[1,2,4,3]
# i = 2
j = 3
[1,2,3,4]
代入逻辑可知:外部循环索引的元素,和内部所有未排序部分的元素一 一比较,替换最小值到外部索引处,所以这就是选择排序
真正的选择排序
def select_order(alist):
n = len(alist)
for j in range(0,n-1):
min_index = j
for i in range(j+1, n):
if alist[min_index] > alist[i]:
min_index = i
alist[min_index],alist[j] = alist[j],alist[min_index]
list = [3,5,12,5,23,1,6,2,11,23]
select_order(list)
print(list)
通过代码可知,算法的逻辑是一样的,但是这个规范代码在内部循环并不进行数据顺序的调换,而只是最小值索引的标记,外层进行排序
*range()值域,外层从0开始不包括最后一个,内层从外层的下一个开始(未排好序)包括最后一个,所以外层是 n - 1,内层是 n 。
选择排序是指定索引位和其他元素跳跃式一一比较,并调换位置;冒泡排序是相邻元素比较,最大元素每一次大循环移动到尾部