一、冒泡排序
基本思路:冒泡排序(Bubble Sort),是一种计算机科学领域简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。这个算法的名字由来是因为越小的元素会慢慢“浮”到数列的顶端,越重的元素会慢慢的沉入到底端,故名“冒泡排序”。时间复杂度最快: O(n)。,最坏: O(n^2)。注意,缺点是每一次只能确定一个元素。
python语言实现代码如下:
# 冒泡排序
def bubble_sort(my_list):length = len(my_list)# 序列长度为length,需要执行length-1轮交换
for i in range(1, length):# 对于每一轮交换,都将序列当中的左右元素进行比较
# 每轮交换当中,由于序列最后的元素一定是最大的,因此每轮循环到序列未排序的位置即可
for i in range(0, length-i):if my_list[i] > my_list[i+1]:temp = my_list[i]my_list[i] = my_list[i+1]my_list[i+1] = tempreturn my_list
if __name__ == '__main__':my_list = [1, 4, 5, 7, 3, 9, 10, 24, 0]new_mylist = bubble_sort(my_list)print(new_mylist)
二、直插法排序
基本思路:直插排序法就是将一个新的数据直接插入到已经排好的数据当中,将数组中的所有元素依次跟前面已经排好的元素相比较,如果选择的元素比已排序的元素小,则交换,直到全部元素都比较过, 时间复杂度为O(n^2)。
python语言实现代码如下:
# 直接插入排序
def insert_sort(my_list):# 遍历数组中的所有元素,其中0号索引元素默认已排序,因此从1开始
for i in range(1, len(my_list)):# 将该元素与已排序好的前序数组依次比较,如果该元素小,则交换
# range(x-1,-1,-1):从i-1倒序循环到0
for j in range(i-1, -1, -1):# 判断:如果符合条件则交换
if my_list[j] > my_list[j+1]:temp = my_list[j+1]my_list[j+1] = my_list[j]my_list[j] = tempreturn my_list
if __name__ == '__main__':my_list = [1, 2, 10, 3, 9, 4, 5, 7]new_list = insert_sort(my_list)print(new_list)
三、选择排序
基本思路:比较+交换。从将要排序的序列中,找到最小的元素;如果最小元素不是待排序序列的第一个元素,将其和第一个元素互换;从余下的 N - 1 个元素中,找出关键字最小的元素,重复(1)、(2)步,直到排序结束。
时间复杂度:O(n^2)。
python语言实现代码如下:
# 选择排序 四、堆排序 基本思路: 取出大顶堆的根节点,和末尾的节点进行交换,在满足的大顶堆的前提下,进行重复交换,剩下的哪个值就是最小值。时间复杂度:O(n^2) 堆的概念:堆,分为大顶堆和小顶堆, 大顶堆要求节点的元素都要大于其孩子, 小顶堆要求节点元素都小于其左右 利用堆排序,就是基于大顶堆或者小顶堆的一种排序方法。一下是通过大顶堆来实现。 python语言实现代码如下: # -------------------------堆排序-------------------------------- 五、快速排序 基本思路:从序列当中选择一个基准数(pivot)(我们选择第一个数为基准数) python语言实现代码如下: # 快速排序 六、希尔排序 基本思路:将待排序数组按照步长进行分组,然后将每组的元素利用直接插入排序的方法进行排序;每次将gap折半减小,循环上述操作;当gap=1时,利用直接插入,完成排序。 python语言实现代码如下: # 希尔排序 七、归并排序 基本思路:将已有的子序列合并,达到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。 首先将序列每次折半拆分,然后将划分后的序列段两两排序合并 python语言实现代码如下: # 归并排序 八、基数排序 基本思路:通过序列中各个元素的值,对排序的N个元素进行若干趟的“分配”与“收集”来实现排序。 分配:我们将L[i]中的元素取出,首先确定其个位上的数字,根据该数字分配到与之序号相同的桶中 收集:当序列中所有的元素都分配到对应的桶中,再按照顺序依次将桶中的元素收集形成新的一个待排序列L[ ] 对新形成的序列L[]重复执行分配和收集元素中的十位、百位...直到分配完该序列中的最高位,则排序结束 python语言实现代码如下: #************************基数排序**************************** 八、桶排序(简化版:最简单最快速的排序) 基本思路:个人理解-逆向思维,首先将要排序的目标排序好,然后将出现的数值记录+1,形象的说就是,每出现一次,就将它放入对应的桶中,然后将出现的次数输出。 demo: 第一步:将分数按照大小排序,分数由0-100分构成,我们就定义一个数组int a[100] ,然后循环遍历数组的下标,将所有的下标对应的值初始化为0 # python中没有数组,我们用列表代替 第二步:第一步以后,我们现在已经有了代表一百个分数的列表元素了,初始化为0,那么,我们的思维是,每一个元素就代表一个‘’桶‘’,每出现一次就将元素初始化的值对应+1,也就是说,列表中(C语言中是数组,下标)每一个元素的值,就代表下标(分数)对应出现的次数。 # 循环输入5个数 第三步,遍历这个列表,将大于0的元素,输出对应的下标(分数),0不输出(没有出现过),值是多少就输出几。 # 循环遍历,一次将出现大于0次数的元素输出,值是多少就输出多少,下标的对应的分数 完整代码如下: # python中没有数组,我们用列表代替 这里的桶排序只是一个简化版本的桶排序,并不是真正意义的桶排序,不过思想是这样的,(个人理解是逆向思维,从问题着手),由于python3中,已经没有数组的定义,只好用列表代替,希望大家不要纠结代码,要学会这种数据结构的抽象思维,只有这样,才能编程你们的东西。 桶排序最大的问题就是,当你的数据达到数以万计的时候,他就需要定义相应的空间,十分浪费,所以这样用空间换时间的做法不靠谱,再者,要是小数更没有办法进行排序了,所以引入了冒泡,快排,选择,直插,希尔等排序。 总结: 当数据量小的时候,这八种排序不会有什么区别。 但是当数据量达到几万,甚至几十万的时候,就会拉开差距。 从运行结果上来看,堆排序、归并排序、基数排序比其他算法要快的多。 提醒:这里的排序只是C语言中排序的最简单的思想,想要深入研究和挖掘,需要对算法进行不断的优化处理,以后有时间给大家更新。
def select_sort(my_list):# 依次遍历序列中的每一个元素
for x in range(0, len(my_list)):# 将当前位置的元素定义为当前的最小值
mixnum = my_list[x]# 将该元素与剩下的元素依次比较寻找最小元素
for i in range(x+1, len(my_list)):if my_list[i]
my_list[x] = mixnumreturn my_list
if __name__ == '__main__':my_list = [2, 4, 1, 6, 7, 3, 9, 8]new_list = select_sort(my_list)print(new_list)
# **********获取左右叶子节点**********
def Left(i):return 2*i + 1
def Right(i):return 2*i + 2
# ********** 调整大顶堆 **********
# L:待调整序列 length: 序列长度 i:需要调整的下标
def adjust_max_header(L, length, i):# 定义一个int值保存当前序列最大值的下标
largest = i# 执行循环操作:两个任务:1 寻找最大值的下标;2.最大值与父节点交换
while True:# 获得序列左右叶子节点的下标
left, right = Left(i), Right(i)# 当左叶子节点的下标小于序列长度 并且 左叶子节点的值大于父节点时,将左叶子节点的下标赋值给largest
if (left
if (right
if largest != i:temp = L[i]L[i] = L[largest]L[largest] = tempi = largestcontinue
else:break
return L# ********** 建立大顶堆 **********
def build_max_header(L):length = len(L)for x in range(int((length-1)/2), -1, -1):adjust_max_header(L, length, x)# ********** 堆排序 **********
def do_header_sort(L):# 先建立大顶堆,保证最大值位于根节点;并且父节点的值大于叶子结点
build_max_header(L)# i:当前堆中序列的长度.初始化为序列的长度
i = len(L)# 执行循环:1. 每次取出堆顶元素置于序列的最后(len-1,len-2,len-3...)
# 2. 调整堆,使其继续满足大顶堆的性质,注意实时修改堆中序列的长度
while i > 0:temp = L[i-1]L[i-1] = L[0]L[0] = temp
# 堆中序列长度减1
i -= 1
# 调整大顶堆
adjust_max_header(L, i, 0)return L# 程序执行入口
if __name__ == '__main__':L = [2, 4, 3, 1, 7, 8, 9, 5, 10, 12, 11]print(do_header_sort(L))
将序列当中的所有数依次遍历,比基准数大的位于其右侧,比基准数小的位于其左侧
重复步骤,直到所有子集当中只有一个元素为止。
# L:待排序的序列 start排序的开始 index,end序列末尾的index
# 对于长度为length的序列:start = 0;end = length - 1
def quick_sort(L, start, end):if start
while (i
# 将小于pivot的值移到左边
if i
# 从左开始向右寻找第一个大于pivot的值
while (i
# 将大于pivot的值移到右边
if i
# 循环结束后,说明 i=j,此时左边的值全都小于pivot,右边的值全都大于pivot
# pivot的位置移动正确,那么此时只需对左右两侧的序列调用此函数进一步排序即可
# 递归调用函数:依次对左侧序列:从0 ~ i-1//右侧序列:从i+1 ~ end
L[i] = pivot# 左侧序列继续排序
quick_sort(L, start, i-1)# 右侧序列继续排序
quick_sort(L, i+1, end)return Lif __name__ == '__main__':L = [9, 7, 2, 1, 7, 5, 3, 4]print(quick_sort(L, 0, len(L) - 1))
def insert_shell(L):# 初始化gap值,此处利用序列长度的一般为其赋值
gap = int(len(L)/2)# 第一层循环:依次改变gap值对列表进行分组
while gap >= 1:# 下面:利用直接插入排序的思想对分组数据进行排序
# range(gap,len(L)):从gap开始
for x in range(gap, len(L)):# range(x-gap,-1,-gap):从x-gap开始与选定元素开始倒序比较,每个比较元素之间间隔gap
for i in range(x-gap, -1, -gap):# 如果该组当中两个元素满足交换条件,则进行交换
if L[i] > L[i+gap]:temp = L[i+gap]L[i+gap] = L[i]L[i] = temp# while循环条件折半
gap = int(gap/2)return Lif __name__ == '__main__':L = [3, 2, 4, 6, 3, 9, 4, 2]print(insert_shell(L))
# 这是合并的函数
# 将序列L[first...mid]与序列L[mid+1...last]进行合并
def mergearray(L,first,mid,last,temp):# 对i,j,k分别进行赋值
i, j, k = first, mid+1, 0
# 当左右两边都有数时进行比较,取较小的数
while (i <&#61; mid) and (j <&#61; last):if L[i] <&#61; L[j]:temp[k] &#61; L[i]i &#61; i&#43;1
k &#61; k&#43;1
else:temp[k] &#61; L[j]j &#61; j&#43;1
k &#61; k&#43;1
# 如果左边序列还有数
while i <&#61; mid:temp[k] &#61; L[i]i &#61; i&#43;1
k &#61; k&#43;1
# 如果右边序列还有数
while j <&#61; last:temp[k] &#61; L[j]j &#61; j&#43;1
k &#61; k&#43;1
# 将temp当中该段有序元素赋值给L待排序列使之部分有序
for x in range(0, k):L[first&#43;x] &#61; temp[x]
# 这是分组的函数
def merge_sort(L,first,last,temp):if first
merge_sort(L, first, mid, temp)# 使右边序列有序
merge_sort(L, mid&#43;1, last, temp)# 将两个有序序列合并
mergearray(L, first, mid, last, temp)
# 归并排序的函数
def merge_sort_array(L):# 声明一个长度为len(L)的空列表
temp &#61; len(L)*[None]# 调用归并排序
merge_sort(L, 0, len(L)-1, temp)
# 确定排序的次数
# 排序的顺序跟序列中最大数的位数相关
def radix_sort_nums(L):maxNum &#61; L[0]# 寻找序列中的最大数
for x in L:if maxNum
times &#61; 0
while maxNum > 0:maxNum &#61; (int)(maxNum/10)times &#61; times&#43;1
return times
# 找到num从低到高第pos位的数据
def get_num_pos(num,pos):return ((int)(num/(10**(pos-1))))%10
# 基数排序
def radix_sort(L):count &#61; 10*[None] # 存放各个桶的数据统计个数
bucket &#61; len(L)*[None] # 暂时存放排序结果
# 从低位到高位依次执行循环
for pos in range(1, radix_sort_nums(L)&#43;1):# 置空各个桶的数据统计
for x in range(0, 10):count[x] &#61; 0
# 统计当前该位(个位&#xff0c;十位&#xff0c;百位....)的元素数目
for x in range(0,len(L)):#统计各个桶将要装进去的元素个数
j &#61; get_num_pos(int(L[x]), pos)count[j] &#61; count[j] &#43; 1
# count[i]表示第i个桶的右边界索引
for x in range(1, 10):count[x] &#61; count[x] &#43; count[x-1]# 将数据依次装入桶中
for x in range(len(L)-1, -1, -1):# 求出元素第K位的数字
j &#61; get_num_pos(L[x], pos)# 放入对应的桶中&#xff0c;count[j]-1是第j个桶的右边界索引
bucket[count[j]-1] &#61; L[x]# 对应桶的装入数据索引-1
count[j] &#61; count[j]-1
# 将已分配好的桶中数据再倒出来&#xff0c;此时已是对应当前位数有序的表
for x in range(0, len(L)):L[x] &#61; bucket[x]
a &#61; []
for i in range(0, 101):# 初始化0
a.append(0)
for i in range(5):n &#61; int(input("请输入第%d个分数:" % i))a[n] &#43;&#61; 1
for i in range(0, 101):for j in range(0, a[i]):print(i)
a &#61; []
for i in range(0, 101):# 初始化0
a.append(0)# 循环输入5个数
for i in range(5):n &#61; int(input("请输入第%d个分数:" % i))a[n] &#43;&#61; 1
# 循环遍历&#xff0c;一次将出现大于0次数的元素输出&#xff0c;值是多少就输出多少&#xff0c;下标的对应的分数
for i in range(0, 101):for j in range(0, a[i]):print(i)