内容大多引用菜鸟教程,写完了才发现教程讲的非常详细,我这里只针对python的代码实现
排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存
名词解释:
(1)当输入的数据已经是正序时,就不需要冒泡排序了
(2)当输入的数据是反序时,写一个 for 循环反序输出数据就行,没必要麻烦的用冒泡排序
def bubble_sort(nums):
for i in range(1, len(nums) - 1): # 设置冒泡排序进行的次数
for j in range(0, len(nums) - i): # j为列表下标
if nums[j] > nums[j + 1]:
nums[j], nums[j + 1] = nums[j + 1], nums[j] #交换两值
return nums
print(bubble_sort([45, 32, 8, 33, 12, 22, 19, 97]))
# 输出:[8, 12, 19, 22, 32, 33, 45, 97]
数据规模越小越好
def selectionSort(nuns):
for i in range(len(nums) - 1):
# 记录最小数的索引
minIndex = i
for j in range(i + 1, len(nums)):
if nums[j] < nums[minIndex]:
minIndex = j
# i 不是最小数时,将 i 和最小数进行交换
if i != minIndex:
nums[i], nums[minIndex] = nums[minIndex], nums[i]
return nums
(1)当输入的数据已经是正序时,需要进行的比较操作是 (n-1)次
(2)当输入的数据是反序时,需要进行的比较共有n(n-1)/2次
def insertionSort(nums):
for i in range(len(nums)):
preIndex = i-1
current = nums[i] # 保存当前元素值,拿前面的值和它比较
while preIndex >= 0 and nums[preIndex] > current:
nums[preIndex+1] = nums[preIndex] # 将前面较大的元素向后移
preIndex -= 1
nums[preIndex+1] = current #最后将其保存到相应位置
return nums
(1)当输入的数据已经是正序时,需要进行的比较操作是 (n-1)次
(2)当输入的数据是反序时,需要进行的比较共有n(n-1)/2次
def shellSort(nums):
import math
gap=1
while(gap < len(nums)/3): # 动态定义间隔序列
gap = gap*3+1 # 这里目的最后必然有一次间隔为1的插入排序,防止有些元素没有比较排序
while gap > 0:
for i in range(gap,len(nums)):
temp = nums[i]
j = i-gap
while j >=0 and nums[j] > temp: #对每组使用插入排序
nums[j+gap]=nums[j]
j-=gap
nums[j+gap] = temp
gap = math.floor(gap/3) #向下取整,最后一趟排序必然为间隔为1的插入排序,由于上面定义的间隔序列规则
return nums
该算法是采用分治法(Divide and Conquer)的一个非常典型的应用,归并排序的实现由两种方法:
def mergeSort(nums):
import math
if(len(nums) < 2):
return nums
middle = math.floor(len(nums) / 2)
left, right = nums[0:middle], nums[middle:]
print(left,right)
return merge(mergeSort(left), mergeSort(right))#这里递归较复杂,看不懂建议带数一步一步来
def merge(left,right):
result = []
while left and right:
if left[0] <= right[0]:
result.append(left.pop(0))
else:
result.append(right.pop(0))
while left:
result.append(left.pop(0))
while right:
result.append(right.pop(0))
return result
if __name__ == '__main__':
a = [14, 2, 34, 43, 21, 19]
print (mergeSort(a))
def quickSort(nums, left=None, right=None):
# isinstance() 函数来判断一个对象是否是一个已知的类型,类似type()
left = 0 if not isinstance(left,(int, float)) else left # if else语法糖
right = len(nums)-1 if not isinstance(right,(int, float)) else right
if left < right:
partitionIndex = partition(nums, left, right)
quickSort(nums, left, partitionIndex-1)
quickSort(nums, partitionIndex+1, right)
return nums
# 分治
def partition(nums, left, right):
pivot = left #基准元素为左边第一个元素
index = pivot+1 #index保存数组中比基准元素小的最后一个元素的位置,用于最后基准元素的替换
i = index
while i <= right:
if nums[i] < nums[pivot]: # 值小的放基准元素左边
nums[i], nums[index] = nums[index], nums[i] #交换元素
index += 1
i += 1
nums[pivot], nums[index-1] = nums[index-1], nums[pivot] #交换元素,将基准元素放置大小分离的中间
return index-1
# 示例:
array = [4,3,2,6,5,6,2,7,5,8,4]
print(quickSort(array))
# 第一趟快排结果 [3,2,2, 4 ,5,6,6,7,5,8,4]
# 输出为[1, 2, 2, 3, 4, 5, 5, 6, 7, 7, 9, 9, 10, 12, 15, 15, 17]
alt+j 多次点击可以一次性选中并修改多个相同的变量
def buildMaxHeap(nums):
import math
for i in range(math.floor(len(nums)/2),-1,-1):
heapify(nums,i)
def heapify(nums, i):
left = 2*i+1
right = 2*i+2
largest = i
if left < numsLen and nums[left] > nums[largest]:
largest = left
if right < numsLen and nums[right] > nums[largest]:
largest = right
if largest != i:
swap(nums, i, largest)
heapify(nums, largest)
def swap(nums, i, j):
nums[i], nums[j] = nums[j], nums[i]
def heapSort(nums):
global numsLen
numsLen = len(nums)
buildMaxHeap(nums)
for i in range(len(nums)-1,0,-1):
swap(nums,0,i)
numsLen -=1
heapify(nums, 0)
return nums
def countingSort(nums, maxValue):
bucketLen = maxValue+1
bucket = [0]*bucketLen
sortedIndex =0
numsLen = len(nums)
for i in range(numsLen):
if not bucket[nums[i]]:
bucket[nums[i]]=0
bucket[nums[i]]+=1
for j in range(bucketLen):
while bucket[j]>0:
nums[sortedIndex] = j
sortedIndex+=1
bucket[j]-=1
return nums
(1)最快:当输入的数据可以均匀的分配到每一个桶中
(2)最慢:当输入的数据被分配到了同一个桶中
def bucketSort(nums, maxNum):
buf = {
i: [] for i in range(int(maxNum)+1)} # 不能使用[[]]*(max+1),这样新建的空间中各个[]是共享内存的
nums_len = len(nums)
for i in range(nums_len):
num = nums[i]
buf[int(num)].append(num) # 将相应范围内的数据加入到[]中
nums = []
for i in range(len(buf)):
if buf[i]:
nums.extend(sorted(buf[i])) # 这里还需要对一个范围内的数据进行排序,然后再进行输出
return nums
if __name__ == "__main__":
lis = [3.1, 4.2, 3.3, 3.5, 2.2, 2.7, 2.9, 2.1, 1.55, 4.456, 6.12, 5.2, 5.33, 6.0, 2.12]
print(bucketSort(lis, max(lis)))
def radixSort(nums):
"""基数排序"""
i = 0 # 记录当前正在排拿一位,最低位为1
maxNum = max(nums) # 最大值
j = len(str(maxNum)) # 记录最大值的位数
while i < j:
bucketList =[[] for _ in range(10)] #初始化桶数组
for x in nums:
bucketList[int(x / (10**i)) % 10].append(x) # 找到位置放入桶数组
print(bucketList)
nums.clear()
for x in bucketList: # 放回原序列
for y in x:
nums.append(y)
i += 1
if __name__ == '__main__':
nums = [334,5,67,345,7,345345,99,4,23,78,45,1,3453,23424]
radixSort(nums)
print(nums)