#python的基础10大排序算法--冒泡,快速,基数,桶。。 import random #冒泡排序 def bubble_f(b_li): b_len = len(b_li) #获取列表的长度 for i in range(b_len): #从第一个元素,即0,开始,直到最后一个元素,n - 1,用i来记录循环,总计是n次 #第一次循环,即i = 0,找到整列表中最大的一个,并且,放在列表的最后一个位置,即n-1的位置 # 用j来控制比较循环,j从0开始,j与j+1进行比较,故而,j+1的最大值是n-1,那么,j的最大值就是n-2,就是j小于n-1-0,n-1-i #第二次循环,即i=1的时候,用j来控制循环,把整个数列的次最大的,放到整个数列的次最后一个位置,即j+1=n-2,就是j小于n-1-1,n-1-i for j in range(b_len - i - 1 ): if b_li[j] > b_li[j + 1]: #逐个比较,直到把整个列表中的最大的一个放到整个列表的最后一个位置,即n-1的位置 b_li[j],b_li[j + 1] = b_li[j + 1],b_li[j] #数列进行一个升序排列,小于,就是降序排列 return b_li #插入排序 def insert_f(i_li): i_len = len(i_li) #获取整个数列的升序 for i in range(i_len): #循环遍历整个数列 j = i - 1 #取数列比较值的前一个数值 #i是0的时候,j是-1。不用比较。i是1的时候,j是0,用数列[0]与[1],进行对比 i_temp = i_li[i] #把比较值的数值取出,暂存到临时值,temp,中 #只要j大于,等于0,而且,[j]比temp要大,那么,就把这个[j]移动到[j+1]的位置 #即向后移动,所有比temp大的。而比temp小的,则停止循环。 while j >= 0 and i_li[j] > i_temp: #大于,就是升序排列。小于,就是降序排列。 i_li[j + 1]= i_li[j] #[j]向后移动一个位置 j -= 1 #j向前移动1个位置 i_li[j + 1] = i_temp #把temp的数值,赋值给j+1,也就是i return i_li #希尔排序,就是升级版本的插入排序 def shell_f(s_li): s_len = len(s_li) #得到数列的长度 gap = s_len // 2 #得到第一次的gap,即长度的一半 #从gap开始进行,逐个加1的循环,把数列分成若干个,以gap为间隔的小数列 for i in range(gap,s_len): #i的初值是gap,然后,次值是gap+1。。。 j = i - gap #将[i]与[i-gap]进行对比 temp = s_li[i] #将[i]赋值给temp,空出[i] #大于,等于gap,并且,[j]大于temp,则后移。 #大于,就是升序。小于,就是降序 while j >= gap and s_li[j] > temp: s_li[j + gap] = s_li[j] j -= gap s_li[j + gap] = temp gap //= 2 #对gap地板除以2,得到新的gap,再次进行新的循环遍历 return s_li #选择排序 def selection_f(se_li): se_len = len(se_li) #获取数列的长度 for i in range(se_len): #遍历循环整个数列 se_min = i #假设当前的i,是整个数列的最小值 #i是0,即假设0是最小值。i是1,即假设1是最小值 #j从i+1开始与i比较。 #i是0,j从1开始,即0与1以后的所有数值进行比较 for j in range(i + 1,se_len): #小于,就是升序排列。找到整个数列中,最小的一个数值 #并将最小的数值放到i的位置,即0 #大于,就是降序排列。 if se_li[j] < se_li[se_min]: se_min = j #j比se_min还要小,则将j赋值给se_min #保证,se_min始终指向整个数列的最小的数值 if se_min != i: #如果整个数列的最小值不是i,则将se_min与i交换 se_li[se_min],se_li[i] = se_li[i],se_li[se_min] return se_li #归并排序 #先分治,把整个数列划分为一个又一个单独的小数列 #再合并,把整个数列单独的一个一个进行比较,合并 #分治数列,拆分数列 def devide_f(de_li): de_len = len(de_li) #获取数列的长度 if de_len == 1: #直到把数列拆分为单独的一个数列的时候,则返回这个数列 return de_li #返回单个的小数列 #拆分为左数列,左数列是从0开始,直到整个数列升序的一半 left_li = devide_f(de_li[:de_len // 2]) #拆分为右数列,右数列是从整个数列长度的一半开始,直到整个数列的最后一个数值 right_li = devide_f(de_li[de_len // 2:]) #把最后拆分的,单独的,一个一个的数列,传输给,合并的函数merge return merge_f(left_li,right_li) #合并数列 def merge_f(left_li,right_li): #在每次循环,进入合并的函数之前,把左,右赋值为0. #在循环之前,始终用一个空的数列来保存,合并函数运行之后的,数列 left_s, right_s, merge = 0, 0, [] #控制循环的条件,左值小于左数列的长度,右值小于右数列的长度 while left_s < len(left_li) and right_s < len(right_li): #小于,就是升序排列。大于,就是降序排列。 #左数列的数值小于右数列的数值,则把,小值赋值到,空的数列中 if left_li[left_s] <= right_li[right_s]: merge.append(left_li[left_s]) left_s += 1 # 右数列的数值小于左数列的数值,则把,小值赋值到,空的数列中 else: merge.append(right_li[right_s]) right_s += 1 #把将数列进行合并,并且,把左数列剩余的数值,与右数列剩余的数值,分别赋值给merge merge = merge + left_li[left_s:] + right_li[right_s:] return merge #快速排序 #比较每个循环之间,保证左边永远是小于temp,右边永远是大于temp def kuai_f(ku_li,head,tail): ku_temp = ku_li[head] #把数列的第一个数值,即head,赋值给temp while head < tail: #始终保证数列至少有2个数值,如果,小于2,不用进入循环 #初值必须要始终小于终值,而且,终值必须始终大于temp。直到找到一个小于temp的,则退出循环 while head < tail and ku_li[tail] >= ku_temp: #大于号就是升序排列,小于号就是降序排列 tail -= 1 #大于temp,则前移1个数位 ku_li[head] = ku_li[tail] #将小于temp的,赋值给初值 #初值必须要始终小于终值,而且,终值必须始终小于temp。直到找到一个大于temp的,则退出循环 while head < tail and ku_li[head] < ku_temp: #小于号就是升序排列,大于号就是降序排列 head += 1 #小于temp,则后移1个数位 ku_li[tail] = ku_li[head] #将大于temp的,赋值给终值 #在最后的循环结束的时候,head等于tail的时候,把temp赋值给数列的head,tail ku_li[head] = ku_temp return tail #拆分数列 def partion_f(ku_li,heads,tails): if heads < tails: #始终保证数列,至少有2个数值 # 第一次循环,将数列的第一个数值,[0],赋值给temp, #以[0]为中间值,右边全部是比[0]大的数值,左边全部是比[0]小的数值 mid = kuai_f(ku_li,heads,tails) #再次循环比较head到mid-1,的数列 partion_f(ku_li,heads,mid - 1) # 再次循环比较mid+1到tails,的数列 partion_f(ku_li, mid + 1, tails) return ku_li #堆排序 #比较数列,保证根值,始终是最大的数值 def heap_f(he_li,n_len,i): hea_temp = i #把根值赋值给temp,假设,temp始终指向最大值 #分别获取左叶子值与右叶子值 #如,1,3,5,98,7。。这些var对应的index分别是0,1,2,3,4。。 #所以,左叶子值是,2*0+1,右叶子值是2*0+2。。。 left_s, right_s = 2 * i + 1, 2 * i + 2 #只要左叶子值小于长度值,len。并且,左叶子值大于根值 #则,把temp指向最大值的,左叶子值left,使temp指向left #大于号,就是升序排列。小于号,就是降序排列。 if left_s < n_len and he_li[left_s] > he_li[i]: hea_temp = left_s #只要右叶子值小于长度值,len。并且,右叶子值大于根值 #则,把temp指向最大值的,右叶子值right,使temp指向right # 大于号,就是升序排列。小于号,就是降序排列。 if right_s < n_len and he_li[right_s] > he_li[hea_temp]: hea_temp = right_s #如果,根值与temp不相等,则说明,i没有指向最大值。而是,temp指向最大值。 #则,交换temp指向的与i指向的数值 #如果,i与temp相等,说明,数列本身就是一个大顶堆,即i指向最大值 if i != hea_temp: he_li[hea_temp],he_li[i] = he_li[i],he_li[hea_temp] #则,把temp传递给新的i值,进行下一次的函数调用排序。 heap_f(he_li,n_len,hea_temp) #数列进行循环 def devide_fs(array): dev_len = len(array) #获取数列的长度 #从n-1到0,要遍历循环数列的每个数值,所以,最终值是-1,倒序以-1进行递减,逐个比较数列的每个数值 #直到把数列变成一个大顶堆 for i in range(dev_len - 1,-1,-1): heap_f(array,dev_len,i) #倒序把每个数值传递到堆函数中,进行循环比较 #从n-1到1,只用比较到倒数的第二个数值即可,所以,最终值是0。 #交换,1指向的与0指向的数值,到1即可停止循环了。 # 倒序,把j从len-1开始,一个一个的递减,以-1为单位进行递减。 for j in range(dev_len - 1,0,-1): #交换根值与最后一个数值 array[j],array[0]=array[0],array[j] #每次把0赋值给i,每个初值就是0,每个j就是数列的长度。 heap_f(array,j,0) return array #计数排序 只有一个升序排列,暂时没有降序排列 def count_f(c_arr,c_max = 100000): #用c_max控制数列的最大长度 #c_max可以是100,代表,只能对101以内的数值进行排序对比 # c_max可以是1000,代表,只能对1001以内的数值进行排序对比 #新建一个,c_amx + 1的长度的数列 c_li = [0 for _ in range(c_max + 1)] #遍历该数列,取出var,即数值 for var in c_arr: #把var相同的数值,添加到var的数值中 c_li[var] += 1 #把原数列进行清空,以用于存储新的数值 c_arr.clear() c_len = len(c_li) #遍历数列的,var,index,用于对比之后生成,新的数列 for index,var in enumerate(c_li): #遍历var,将var对应的index,分别添加到新的数列中 for j in range(var): #for j in range(c_len - 1,0): c_arr.append(index) #添加到新的数列中 return c_arr #桶排序 def bucket_f(b_arr,n = 100,n_max = 10000): #用n_max来控制二维数列的长度,n来控制一维数列的长度 b_lis = [[] for _ in range(n)] #生成一个二维数列 for var in b_arr: #遍历要排序的数列 #189,放在哪个桶中呢。应该是放在,2号桶,即index = 2的桶中 #所以,2 = 189 // (10000 // 100),地板除。 #10000,只能放在最后一个桶中,即99号桶, #但,10000 // (10000 // 100) = 100,超过了索引值,99 #所以,要取,地板除与,n-1的最小值 i = min(var // (n_max // n),n-1) b_lis[i].append(var) #把var加入到对应的索引值中,即i #使用类似于冒泡排序的算法,对i的桶进行排序 for j in range(len(b_lis[i]) - 1,0,-1): #按照倒序的方法,从最后一个索引值开始,递减比较大小 if b_lis[i][j - 1] > b_lis[i][j]: #小于号就是降序排列,大于号就是升序排列 b_lis[i][j - 1],b_lis[i][j] = b_lis[i][j],b_lis[i][j - 1] else: break #如果j-1比j要小,则终止if循环,不用交换数值。 s_lis = [] #新建一个数列,用来存储排序之后的数列 for k in b_lis: #遍历二维数列 s_lis.extend(k) #把二维数列的,0到99号的一维数列,把已经排序成功的数列,整个,添加到新的数列中 return s_lis #基数排序 只有一个升序排列,暂时没有降序排列 def radix_f(r_arr): r_max = max(r_arr) #获取数列的最大值 r_pivot = 0 #临时指针,用于记录,每次比较的排序的位数,即从个位数,十位数。。。直到最后的位数 #保证每次被比较的指针值,全部小于,或者,等于数列的最大值 while 10 ** r_pivot <= r_max: #建立一个二维数列,长度是10的,用于存储按照,指针排序好的数列,即个位数,十位数。。等等 r_buckets = [[] for _ in range(10)] for var in r_arr: #获取数列的var #299的第一次排序,按照个位数来,即9 #9 = 299 // 10 ** 0 = 299 // 1 = 299,299 % 10 = 9 digit = (var // 10 ** r_pivot) % 10 r_buckets[digit].append(var) #把个位数全部是,digit的,全部存储到,digit中 r_arr.clear() #清空老数列 for r_var in r_buckets: #遍历二维数列 #从0开始,把个位数从0到9依次升序来输出数列 r_arr.extend(r_var) #添加到老的数列中 #个位数排序完毕,指针数值加1,进行十位数的排序比较 r_pivot += 1 return r_arr p_li = [random.randint(0,90000) for _ in range(13)] random.shuffle(p_li) #把数列的排序随意打乱 print('初始值 : ',p_li) print(f'1,冒泡排序的升序排列值 : {bubble_f(p_li)}') print('2,插入排序的升序排列值 : ', insert_f(p_li)) print('3,希尔排序的升序排列值 : {0}'.format(shell_f(p_li))) print('4,选择排序的升序排列值 : ' , selection_f(p_li)) print('5,归并排序的升序排列值 : ' , devide_f(p_li)) print('6,快速排序的升序排列值 : ' , partion_f(p_li,0,len(p_li) - 1)) print('7,堆排序的升序排列值 : ' , devide_fs(p_li)) print('8,计数排序的升序排列值 : ' , count_f(p_li)) print('9,桶排序的升序排列值 : ' , bucket_f(p_li)) print('10,基数排序的升序排列值 : ' , radix_f(p_li))
python的基础10大排序算法--冒泡,快速,基数,桶。。
最新推荐文章于 2023-05-03 22:06:21 发布