0
点赞
收藏
分享

微信扫一扫

各类排序算法

Ichjns 2022-03-30 阅读 81
学习python

这里写自定义目录标题

插入排序

直接插入排序

  • 插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率
    步骤:将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。
    从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。
    时间复杂度:O(n^2)
    空间复杂度:O(1)
    稳定性:稳定
def insertionSort(arr):
    for i in range(len(arr)):
        preIndex = i-1
        current = arr[i]
        while preIndex >= 0 and arr[preIndex] > current:
            arr[preIndex+1] = arr[preIndex]
            preIndex-=1
        arr[preIndex+1] = current
    return arr

希尔排序

递减增量排序算法
步骤:按照增量d分组排序,d1=n//2,d2=d1//2,……
对于i in [0,d1),对data[i],data[i+d1],data[i+2*d1]……做插入排序
然后d2,d3……直到d==1,对整个表做一次插入排序
时间复杂度:O(n^1.3)
空间复杂度:O(1)
稳定性:不稳定

def shellSort(arr):
	n=len(arr)
	d=n//2
	while d>=1:
		print(d)
		for i in range(0,d):#有这些个子序列需要排序 i代表了需要遍历的子序列的第一个
			for j in range(i+d,n,d):#j表示当前要插入的点
				pre=j-d#pre表示可能要后移的点
				temp=arr[j]
				while pre>=i and arr[pre]>temp:
					arr[pre+d]=arr[pre]
					pre-=d
				arr[pre+d]=temp
		d=d//2
		#print(arr)
	return arr

交换排序

冒泡排序

步骤:不断比较两个相邻元素,每趟比较后,最大的到了最右端
时间复杂度:O(n^2)
空间复杂度:O(1)
稳定性:稳定

def bubbleSort(arr):
	n=len(arr)
	for i in range(0,n):
		for j in range(1,n-i):
			if arr[j]<arr[j-1]:
				#print('change',arr[j], arr[j -1])
				arr[j], arr[j -1] = arr[j - 1], arr[j]
		print(arr)
	return arr

快速排序

步骤:随机选取一个元素作为轴,小于或者等于它的放左边,大于它的放右边,再接着处理左边和右边
时间复杂度:平均O(nlogn), 最坏O(n^2)
空间复杂度:最好O(logn), 最坏O(n)
稳定性:no

def partition(arr,l,r):
	temp=arr[l]
	while l<r:#等于的时候即为找到中轴了
		while l<r and arr[r]>temp:
			r-=1
		arr[l]=arr[r]
		while l<r and arr[l]<=temp:
			l+=1
		arr[r]=arr[l]
	arr[l]=temp
	return l
def partition2(arr,l,r):
	temp=arr[l]
	ln,rn=l,r
	while ln<=rn:
		#有等于号是为了让left<right,并且让right指到一个<=temp的位置,从而和中轴值换位置
		while ln<=rn and arr[rn]>temp:
			rn-=1
		while ln<=rn and arr[ln]<=temp:
			ln+=1
		if ln<rn:
			arr[ln],arr[rn]=arr[rn],arr[ln]
			ln+=1
			rn-=1		
	arr[l],arr[rn]=arr[rn],arr[l]
	return rn
def quickSort(arr, left, right):
	if left<right:
		p=partition2(arr,left,right)
		quickSort(arr, left, p-1)
		quickSort(arr, p+1, right)

选择排序

简单选择排序

步骤:每次找出一个最小的来,和位置i-1的值交换
时间复杂度:O(n^2)
空间复杂度:O(1)
稳定性:

def SelectionSort(arr):
	for i in range(1,len(arr)):
		k=i-1
		for j in range(i,len(arr)):
			if arr[j]<arr[k]:
				k=j
		if k!=i-1:
			arr[i-1],arr[k]=arr[k],arr[i-1]
	return arr

堆排序

步骤:
时间复杂度:O(nlogn)
空间复杂度:O(1)
稳定性:no

归并排序

步骤:分治法
时间复杂度:O(nlogn)
空间复杂度:O(n)
稳定性:yes

def mergeSortm(arr):
	n=len(arr)
	if n<2:
		return arr
	mid=n//2
	leftarr,rightarr=arr[0:mid],arr[mid:]
	return mergem(mergeSort(leftarr),mergeSort(rightarr))
def mergem(leftarr,rightarr):
	llen=len(leftarr)
	rlen=len(rightarr)
	result=[]
	li,ri=0,0
	for k in range(llen+rlen):
		if li==llen:
			while ri<rlen:
				result.append(rightarr[ri])
				ri+=1
				break
		elif ri==rlen:
			while li<rlen:
				result.append(rightarr[li])
				li+=1
			break
		if leftarr[li]<=rightarr[ri]:
			result.append(leftarr[li])
			li+=1
		else:
			result.append(rightarr[ri])
			ri+=1

计数排序

步骤: 统计给个值的个数,存在数组相应的下标中
时间复杂度: O(n+k)
空间复杂度: O(n+k)
稳定性: 稳定
当输入的元素是 n 个 0 到 k 之间的整数时,它的运行时间是 Θ(n + k)。计数排序对于数据范围很大的数组,需要大量时间和内存。

def countingSort(arr, maxValue):
    bucketLen = maxValue+1
    bucket = [0]*bucketLen
    sortedIndex =0
    arrLen = len(arr)
    for i in range(arrLen):
        #if not bucket[arr[i]]:
            #bucket[arr[i]]=0
        bucket[arr[i]]+=1
    for j in range(bucketLen):
        while bucket[j]>0:
            arr[sortedIndex] = j
            sortedIndex+=1
            bucket[j]-=1
    return arr

桶排序

步骤:
时间复杂度: O(n)
空间复杂度: O(m)
稳定性:稳定

def bucktetSort(numList,bucketNum):
    if len(numList) == 0 or len(numList) == 1:
        return numList
    maxNum = numList[0]
    minNum = numList[0]
    for i in range(1,len(numList)):   # max and min value
        if numList[i] < minNum:
            minNum = numList[i]
        elif numList[i] > maxNum:
            maxNum = numList[i]
        else:
            continue
    bucketSize = (maxNum - minNum + 1) // bucketNum   
	# range
    buckets = [[] for i in range(bucketNum)]
    for i in range(len(numList)):     
        buckets[(numList[i] - minNum) // bucketSize].append(numList[i])
    for i in range(bucketNum):       
        buckets[i].sort()
    res = []
    for i in range(len(buckets)): 
        for j in range(len(buckets[i])):
            res.append(buckets[i][j])
    return res
numlist = [11,34,23,56,8,20,66,45,54,87,78]
print(bucktetSort(numlist,5))  

						  

基数排序

步骤: 基数排序是对桶排序的扩展。
第一类:最低位优先法,简称LSD法:先从最低位开始排序,再对次低位排序,直到对最高位排序后得到一个有序序列;
第二类:最高位优先法,简称MSD法:先从最高位开始排序,再逐个对各分组按次高位进行子排序,循环直到最低位。(位没有数的话,补0)
时间复杂度: O(k*n)
空间复杂度: O()
稳定性:稳定

def getbit(num,i):          #
    return (num % (i * 10) - (num % i)) // i
def getMax(numList):        # 
    if len(numList) == 1:
        return numList[0]
    maxNum = numList[0]
    for i in range(len(numList)):
        if numList[i] > maxNum:
            maxNum = numList[i]
    return maxNum
def radixSort(numList):
    if len(numList) == 0 or len(numList) == 1:
        return numList
    maxNum = getMax(numList)
    bitCount = 0
    index = 1
    while maxNum // index:
        bitCount += 1
        index *= 10
    currentBit = 1 
    # maxvalue's bitCount
    while currentBit <= 10**(bitCount-1):# 
        res = []
        buckets = [[] for i in range(10)]    # 
        for i in numList:
            currentBitNum = getbit(i,currentBit)
            buckets[currentBitNum].append(i)
        for i in range(10):
            for j in range(len(buckets[i])):
                res.append(buckets[i][j])
        numList = res
        currentBit *= 10
    return numList
numlist = [12,3,45,3543,214,1,4553]
print(radixSort(numlist))


举报

相关推荐

0 条评论