算法1—排序(桶排序、冒泡排序、快速排序python)
冒泡排序
基本思想:
每次比较两个相邻的元素,如果它们的顺序错误就把它们交换
过来
运行步骤:
- 比较相邻元素,将两者按照升序位置进行排列,即第一个大于第二个,将两者进行交换,若不是,则保持不变;
- 从第一对一直到结尾的最后一对,对每一对数据都进行步骤一的比较处理,并将最大的元素放在后面。这样,遍历完所有相邻元素后,整个序列的最后一个元素会是最大的数;
- 将循环缩短一位(因为最后一个元素已经是序列最大的数了),再重复步骤2的处理,得到倒数第二个大的数;
- 持续步骤3 的处理,每次将循环缩短一位,并得到本次循环中的最大的数,直到循环个数缩短为1,此时已经没有一对数据可以比较了,则得到了一个从小到大(升序)排序的序列。
总结:每次都是比较相邻的两个数,如果后面的数比前面的数小,则交换这两个数的位置。一直比较下去直到最后两个数比较完毕后,最大的数就在最后一个了。就如同是一个气泡,一步一步往后“翻滚”,直到最后一位。所以这个排序的方法有一个很好听的名字“冒泡排序”。
如下图所示:
代码实现:
def bubble_Sort(array_list):
#遍历所有数据
L = len(array_list)
for i in range(L):
#遍历所有相邻数据
for j in range(L-i-1):
if array_list[j] >= array_list[j+1]:
array_list[j],array_list[j+1] = array_list[j+1],array_list[j]
if __name__=="__main__":
arr = [12,35,99,18,76]
bubble_Sort(arr)
print ("排序后的数组:",arr)
运行结果:
排序后的数组: [12, 18, 35, 76, 99]
学生成绩和姓名一起返回:方法一
def bubble_Sort(array_list):
if type(array_list) == dict:
array_name = list(array_list)
array_score = list(array_list.values())
#遍历所有数据
L = len(array_score)
for i in range(L):
#遍历所有相邻数据
for j in range(L-i-1):
if array_score[j] >= array_score[j+1]:
array_score[j],array_score[j+1] = array_score[j+1],array_score[j]
array_name[j],array_name[j+1] = array_name[j+1],array_name[j]
return dict(zip(array_name,array_score))
else:
#遍历所有数据
L = len(array_list)
for i in range(L):
#遍历所有相邻数据
for j in range(L-i-1):
if array_list[j] >= array_list[j+1]:
array_list[j],array_list[j+1] = array_list[j+1],array_list[j]
return array_list
if __name__=="__main__":
arr = [12,35,99,18,76]
print("排列后的字典:",bubble_Sort(arr) )
student = {"wang hong":24,"xiao hong":98,"hua hua": 90}
print("排列后的字典:",bubble_Sort(student) )
结果
排列后的数组: [12, 18, 35, 76, 99]
排列后的字典: {‘wang hong’: 24, ‘hua hua’: 90, ‘xiao hong’: 98}
冒泡排序:从两段同时开始
** 思想**
1.相邻元素两两比较,找到最大值,放到最后的位置,并记录标志为true;则此时从倒数第二的位置开始倒序进行两两元素比较找到最小值,放到数据的第一个位置,标记为true;
2.重复步骤1,当标记为false,则返回数据排序完成,返回排列好的数据。
def bubble_sort(items, comp=lambda x, y: x > y):
for i in range(len(items) - 1):
flag = False
for j in range(len(items) - 1 - i):
if comp(items[j],items[j + 1]):
items[j], items[j + 1] = items[j + 1], items[j]
flag = True ###找到此次的最大值
if flag:
flag = False
for j in range(len(items) - 2 - i, 0, -1):
if comp(items[j - 1],items[j]):
items[j], items[j - 1] = items[j - 1], items[j]
flag = True ###找到此次的最小值
if not flag:
break
list = [11,23,5,6,58,15]
print(bubble_sort(list,lambda s1,s2: s1 > s2))
[5, 6, 11, 15, 23, 58]
学生成绩和姓名一起返回:方法二,通过定义类
class Student():
"""学生"""
def __init__(self, name, age):
self.name = name
self.age = age
def __repr__(self):
return f'{self.name}: {self.age}'
items1 = [
Student('Wang Dachui', 25),
Student('Di ren jie', 38),
Student('Zhang Sanfeng', 120),
Student('Bai yuanfang', 18)
]
print(bubble_sort(items1, lambda s1, s2: s1.age > s2.age))
[Bai yuanfang: 18, Wang Dachui: 25, Di ren jie: 38, Zhang Sanfeng: 120]
桶排序
思想
- 首先建立一个空的数组,长度与要排序的数据的最大值+1等长;
- 遍历要排序的数据,当数据与数组的索引相等时,对数组改索引的值加1,直到遍历完所有数据;
- 根据数组的值打印数组索引值,数组的值为几,则打印该索引几遍。
代码实现
桶排序
### 桶排序
def Bucket_sort(arr):
L = len(arr)
## 判断数据是否为空或只有一个数据,若是则直接返回数据
if L == 0 or L==1:
return arr
else:
n = max(arr)+1
bucket = [0 for i in range(n)]
for i in range(len(arr)):
bucket[arr[i]] +=1
# 存储排序好的元素
sort_nums = []
# 取出桶中的元素
for j in range(len(bucket)):
if bucket[j] != 0:
for y in range(bucket[j]):
sort_nums.append(j)
return sort_nums
if __name__ == "__main__":
arr = [12, 18, 35, 76, 99]
print("排好序的数列:",Bucket_sort(arr))
arr = [12]
print("排好序的数列:",Bucket_sort(arr))
结果:
排好序的数列: [12, 18, 35, 76, 99]
排好序的数列: [12]
快速排序
思想
首先快速排序是先找到一个标杆(基准数),然后把大于标杆(基准数)的数放到右边,小于标杆的数放到左边,然后再将左边的数看成新的序列按照刚的操作重新找标杆进行排序,对右边也做同样的操作;依次类推,直到排完整个序列。具体步骤如下:
- 从序列中挑出一个元素,称为"标杆",即基准数(pivot);
- 分别从初始序列两端开始“探测”。先从右往左找一个小于pivot 的数,再从左往右找一个大于 pivot的数,然后交换它们。这里可以用两个变量 i 和 j,分别指向序列最左边和最右边。我们为这两个变量起个好听的名字“哨兵 i”和“哨兵 j”。刚开始的时候让哨兵 i 指向序列的最左边(即 i=0)。让哨兵 j 指向序列的最右边(即 j=len(length)-1);
- 哨兵j先动,判断所指位置的数是否小于基准数,如果大于基准数,则j-1,继续向左前进,直到找到一个小于基准数的数时停止;
- 哨兵i在j停止移动后进行移动,直到找到一个大于基准数的数时停止移动;
- 此时叫唤哨兵i与哨兵j的数,则循环步骤3-4,直到j==i时停止移动,将基准数赋予此位置,
- 重复步骤1-5,将左边数据和右边数据分别进行排序,直到长度为1 为止,输出拍好的序列。
具体如图所示:
细心的同学可能已经发现,快速排序的每一轮处理其实就是将这一轮的基准数归位,直到所有的数都归位为止,排序就结束了。下面上个霸气的图来描述下整个算法的处理过程。
代码实现如下:
## 快速排序
def Quicksort(list_dir,start,end):
if start >= end: ##停止递归迭代的条件只剩一个数停止迭代
return
temp = list_dir[start] # 设定起始的基准元素
left = start # low为序列左边在开始位置的由左向右移动的游标
right = end # high为序列右边末尾位置的由右向左移动的游标
while left < right:
##从右往左找到小于基准数的数停下
while left <right and list_dir[right] >= temp:
right -= 1
list_dir[left] = list_dir[right]
##从左往右找到大于基准数的数停下
while left < right and list_dir[left] < temp:
left += 1
list_dir[right] = list_dir[left]
## 将基准数放到中间位置
list_dir[left] = temp
#进行迭代
Quicksort(list_dir,start,left-1) ##对左边的进行排序
Quicksort(list_dir,left+1,end) ###对右边的进行排序
return list_dir
if __name__ == '__main__':
list_d = [6,1,2,5,9,8,3,4,7,10]
Quicksort(list_d,0,9)
print(list_d)
运行结果如下:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
【参考文献】
- 啊哈磊,《啊哈!算法》,北京,人民邮电出版社.
- 王志平, https://blog.csdn.net/wangzhiping321/article/details/82381704