Note:参考
1.https://blog.csdn.net/wuzhiwei549/article/details/80654836 java排序
2.https://blog.csdn.net/liang_gu/article/details/80627548 java排序
3.https://blog.csdn.net/u014452812/article/details/82752984 python 冒泡 选择 插入
4.https://blog.csdn.net/qq_34840129/article/details/80638225 python 堆排序
1.冒泡 2.选择 3.插入 4.希尔 5.快速 6.归并 7.堆
冒泡排序(Bubble Sort)
冒泡排序算法的运作如下:
- 比较相邻的元素,如果前一个比后一个大,就把它们两个调换位置。
- 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
- 针对所有的元素重复以上的步骤,除了最后一个。
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
A.
'''冒泡排序实现从小到大排序'''
a=[12,-57,23,85,56,-123,-456,250] #测试案例
b=len(a) #队列长度
for i in range(b):
for j in range(b-i-1): #设置循环次数
if a[j]>a[j+1]: #如果后者比前者小,则交换位置,总是把大的数放到后面
a[j],a[j+1]=a[j+1],a[j]
print(a)
B.定义函数方法
arr = [7, 4, 3, 67, 34, 1, 8]
def bubble_sort(arr):
n = len(arr)
for j in range(0, n - 1):
for i in range(0, n - 1 - j):
if arr[i] > arr[i + 1]:
arr[i], arr[i + 1] = arr[i + 1], arr[i]
bubble_sort(arr)
print(arr) # [1, 3, 4, 7, 8, 34, 67]
'''else'''
if __name__ == "__main__":
li = [54, 26, 93, 17, 77, 31, 44, 55, 20]
print(li)
bubble_sort(li)
print(li)
选择排序(Selection Sort)
选择排序也是一种简单直观的排序算法。它的工作原理很容易理解:初始时在序列中找到最小(大)元素,放到序列的起始位置作为已排序序列;然后,再从剩余未排序元素中继续寻找最小(大)元素,放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
注意选择排序与冒泡排序的区别:冒泡排序通过依次交换相邻两个顺序不合法的元素位置,从而将当前最小(大)元素放到合适的位置;而选择排序每遍历一次都记住了当前最小(大)元素的位置,最后仅需一次交换操作即可将其放到合适的位置。
'''
选择排序
选择排序是每次找出最小的索引,
然后替换数据的位置
'''
def select_sort(aList):
'''选择排序'''
l = len(aList)
for j in range(l - 1):
min_index = j
for i in range(min_index + 1, l - 1):
if aList[min_index] > aList[i]:
min_index = i
# 循环一遍后找到最小的索引
aList[j], aList[min_index] = aList[min_index], aList[j]
if __name__ == "__main__":
li = [9 , 16, 17, 15, 11]
print(li)
select_sort(li)
print(li)
插入排序(Insertion Sort)
具体算法描述如下:
-
从第一个元素开始,该元素可以认为已经被排序
-
取出下一个元素,在已经排序的元素序列中从后向前扫描
-
如果该元素(已排序)大于新元素,将该元素移到下一位置
-
重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
-
将新元素插入到该位置后
-
重复步骤2~5
'''插入排序'''
def insert_sort(aList):
'''插入排序'''
n = len(aList)
for i in range(n):
j = i
# print('j= ', j)
while j > 0:
if aList[j] < aList[j - 1]:
aList[j], aList[j - 1] = aList[j - 1], aList[j]
# print(j)
j -= 1
# print(' ')
if __name__ == "__main__":
li = [54, 26, 93, 17, 77, 31, 44, 55, 20]
print(li)
insert_sort(li)
print(li)
希尔排序(Shell Sort)(插入排序的更高效改进)
算法的基本思想是:先将待排记录序列分割成为若干子序列分别进行插入排序,待整个序列中的记录"基本有序"时,再对全体记录进行一次直接插入排序。
希尔排序是基于插入排序的以下两点性质而提出改进方法的:
- 插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率
- 但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位
希尔排序通过将比较的全部元素分为几个区域来提升插入排序的性能。这样可以让一个元素可以一次性地朝最终位置前进一大步。然后算法再取越来越小的步长进行排序,算法的最后一步就是普通的插入排序,但是到了这步,需排序的数据几乎是已排好的了(此时插入排序较快)。
'''设定步长n/2 …递归直到步长为1'''
a = [56,52,-96,-53,23,-789,520] #测试案例
b = len(a) #列表长度
gap = b // 2 #初始步长设置为总长度的一半
while gap >= 1:
for i in range (b):
j = i
while j>=gap and a[j-gap] > a[j]: #在每一组里面进行直接插入排序
a[j],a[j-gap] = a[j-gap],a[j]
j-= gap
gap=gap//2 #更新步长
print(a)
快速排序(Quick Sort)
快速排序使用分治策略(Divide and Conquer)来把一个序列分为两个子序列。步骤为:
- 从序列中挑出一个元素,作为”基准”(pivot).
- 把所有比基准值小的元素放在基准前面,所有比基准值大的元素放在基准的后面(相同的数可以到任一边),这个称为分区(partition)操作。
- 对每个分区递归地进行步骤1~2,递归的结束条件是序列的大小是0或1,这时整体已经被排好序了。
A.
def quicksort(a, left, right):
if left>right:
return -1
temp=a[left]
i=left
j=right
while i!=j:
while a[j]>=temp and i<j:
j-=1
while a[i]<=temp and i<j:
i+=1
if i<j:
a[i],a[j]=a[j],a[i]
a[left]=a[i]
a[i]=temp
quicksort(a,left,i-1)
quicksort(a,i+1,right)
a=[4, 2, 7,8, 0, 1, 5,23]
quicksort(a,0,len(a)-1)
print(a)
B.
#!/usr/bin/python
def quicksort(array):
if len(array) < 2:
return array
else:
pivot = array[0]
less = [i for i in array[1:] if i <= pivot]
print(less)
greater = [i for i in array[1:] if i > pivot]
print(greater)
return quicksort(less) + [pivot] + quicksort(greater)
if __name__ == '__main__':
print(quicksort([10,5,3,2,6]))
输出:
[5, 3, 2, 6]# 第一次less
[]#第一次grester
[3, 2]
[6]
[2]
[]
[2, 3, 5, 6, 10] #最终结果
假定现在要对数字序列 [4, 2, 7,8, 0,1, 5,23] 进行快速排序。
我们假设最左边的编号为i,最左边的编号为j,不失一般性,假定以4作为基准进行排序(每一次总总是让j先出发,向左移动,再让i出发,向右移动)。
- (一)第一轮排序
j向左出发寻找第一个小于4的数,遇到1的时候停下来;i向右出发寻找第一个大于4的数,遇到7的时候停下来,交换两者的位置,数字序列变为
[4,2,1,8,0,7,5,23]
接下继续让j向左移动,寻找第二个小于4的数,遇到0的时候停下来;让i向右移动,寻找第二个大于4的数,遇到8的时候停下来,交换两者的位置,数字序列变为
[4,2,1,0,8,7,5,23]
此时发现i与j相遇了,第一轮排序结束,调换4和0的位置,数字序列变为
[0,2,1,4,8,7,5,23],
所有小于4的数字都在4的左边,所有大于4的数字都在4的右边。
- (二)第二轮排序
分别对4左边和4右边的数字序列进行排序处理,首先对4左边的数字序列[0,2,1]排序。
以第一个数字0为基准,j向左出发寻找第一个小于0的数,i向右出发寻找第一个大于0的数,遇到0的时候停下来,如果找到就交换两者的位置,否则不变。数字序列变为[0,2,1],所有小于0的数字都在0的左边,所有大于0的数字都在0的右边。
再对4右边的数字序列[8, 7,5,23]排序。
以第一个数字8为基准,j向左出发寻找第一个小于8的数,遇到5的时候停下来;i向右出发寻找第一个大于8的数,如果找到就交换两者的位置,同时保证i小于j,那么数字序列变为[5,7,8,23]。所有小于8的数字都在8的左边,所有大于8的数字都在8的右边。
总体数字序列变为[0,2,1,4,5,7,8,23]。
- (三)第三轮排序
好了动手算一算,类似第一和第二轮的排序方法,对0右边的数字序列进行排序,得到[0,1,2];对8左边的数字序列进行排序,得到[5,7,8,23]。第三轮排序结束。
得到最终的排序结果为
[0,1,2,4,5,7,8,23]。
快排过程结束。
归并排序(Merge Sort)
思想:先递归分解数组,再合并数组
原理:将数组分解最小之后,然后合并两个有序数组,基本思想是比较两个数组的最前面的数,谁小就取谁,取完后,将相应的指针后移以为。然后再比较,直到一个数组为空,最后把另一个数组的剩余部分复制过来即可。
'''归并排序'''
def merge_sort(alist):
if len(alist) <= 1:
return alist
# 二分分解
num = len(alist) / 2
left = merge_sort(alist[:num])
right = merge_sort(alist[num:])
# 合并
return merge(left, right)
def merge(left, right):
'''合并操作,将两个有序数组left[]和right[]合并成一个大的有序数组'''
# left与right的下标指针
l, r = 0, 0
result = []
while l < len(left) and r < len(right):
if left[l] < right[r]:
result.append(left[l])
l += 1
else:
result.append(right[r])
r += 1
result += left[l:]
result += right[r:]
return result
alist = [54, 26, 93, 17, 77, 31, 44, 55, 20]
sorted_alist = merge_sort(alist)
print(sorted_alist)
首先是一个例子
原序先通过一半一半的拆分,然后:
堆排序(Heap Sort)
https://blog.csdn.net/qq_34840129/article/details/80638225
堆排序思想:堆顶(小顶堆)的元素是整个堆中最小的元素,将堆顶元素与最后一个元素交换,然后用一次‘向下筛选’将新的堆顶元素移动到堆中正确的位置:即比较堆顶元素与其两个左右子结点的大小,如果堆顶元素最小,则将其保留在堆顶位置,停止;如果左子结点或右子结点最小,则交换堆顶元素与左子结点或右子结点的值,然后再沿着当前路径不断地比较下去,直至最初的堆顶元素在某一次比较中是最小值或者到达叶结点位置。
此外,如果是小顶堆,得到的是降序序列;如果是大顶堆,得到的是升序序列。
def heap_sort(elems):
def siftdown(elems, e, begin, end): #向下筛选
i, j = begin, begin*2+1 #j为i的左子结点
while j < end:
if j+1 < end and elems[j] > elems[j+1]: #如果左子结点大于右子结点
j += 1 #则将j指向右子结点
if e < elems[j]: #j已经指向两个子结点中较小的位置,
break #如果插入元素e小于j位置的值,则为3者中最小的
elems[i] = elems[j] #能执行到这一步的话,说明j位置元素是三者中最小的,则将其上移到父结点位置
i, j = j, j*2+1 #更新i为被上移为父结点的原来的j的位置,更新j为更新后i位置的左子结点
elems[i] = e #如果e已经是某个子树3者中最小的元素,则将其赋给这个子树的父结点
#或者位置i已经更新到叶结点位置,则将e赋给这个叶结点。
end = len(elems)
for i in range(end//2-1, -1, -1): #构造堆序。
siftdown(elems, elems[i], i, end)
for i in range ((end-1), 0,-1): #进行堆排序.i最后一个值为1,不需要到0
print(elems)
e = elems[i] #将末尾元素赋给e
elems[i] = elems[0] #交换堆顶与最后一个元素
siftdown(elems, e, 0, i)
return(elems)
if __name__=="__main__":
print(heap_sort([5,6,8,1,2,4,9]))
下面用图来解释堆排序的具体过程:
假设最初的无序的列表为[5,6,8,1,2,4,9],经过堆的初始化操作后得到的对堆结构如下:
然后开始进行堆排序,每次都交换堆顶和末尾元素,然后对堆顶元素进行一次向下筛选,带颜色区域为已经排好序的位置,过程如下: