希尔排序

希尔排序通过将比较的全部元素分为几个区域来提升插入排序的性能。这样可以让一个元素可以一次性地朝最终位置前进一大步。然后算法再取越来越小的步长进行排序,算法的最后一步就是普通的插入排序,但是到了这步,需排序的数据几乎是已排好的了(此时插入排序较快)。

时间复杂度:根据步长而不同,最优时间复杂度:O(n),平均时间复杂度:根据步长而不同

def shell_sort(lst):
	h=1
	N=len(lst)
	while h<N/3 :
		h=3*h+1
	while h>=1:
		for i in range (h,N,1):
			while i>=h and lst[i-h]>lst[i]:
				lst[i-h],lst[i]=lst[i],lst[i-h]
				i-=h
		h=int(h/3)
	print(lst)

if __name__== "__main__":
	lst=[1,3,4,1,3,7,8,2,123,4,2]
	shell_sort(lst)



归并排序 merge

归并操作(merge),也叫归并算法,指的是将两个已经排序的序列合并成一个序列的操作。归并排序算法依赖归并操作。

时间复杂度:O(nlogn),最优时间复杂度:O(n),平均时间复杂度:O(nlogn),空间复杂度O(n)

自顶向下的归并排序

#自顶向下
def merge(lst):
	merge_sort(lst,0,len(lst)-1)
	print(lst)

def merge_sort(lst,right,left):
	if right>=left:  return;
	mid=(right+left)//2
	merge_sort(lst,right,mid)
	merge_sort(lst,mid+1,left)
	sort(lst,right,mid,left)

def sort(lst,right,mid,left):
	#lst_copy[right:left]=lst[right:left]
	lst_copy=lst[right:left+1]
#	print(lst_copy)
#	print("change")
#############这里要先赋值 m ,n 在for之前################
	m=right;n=mid+1;
	for i in range(right,left+1):
		if m>mid:
			lst[i]=lst_copy[n-right]
			n+=1
		elif n>left:
			lst[i]=lst_copy[m-right]
			m+=1
		elif lst_copy[m-right]>=lst_copy[n-right]:  
			lst[i]=lst_copy[n-right]
			n+=1
		else :
			lst[i]=lst_copy[m-right]
			m+=1
#	print(lst)
#	print("end")
if __name__== "__main__":
	lst=[12,10,23,14,34,5,6,3,2,7,10,54]
	merge(lst)



堆排序

1.创建最大堆(Build_Max_Heap):将堆所有数据重新排序

2.堆排序(HeapSort):移除位在第一个数据的根节点,并做最大堆调整的递归运算

时间复杂度:O(nlogn),最优时间复杂度:O(nlogn),平均时间复杂度:O(nlogn)

def heap(lst):
	N=len(lst)
	for i in range(N//2,0,-1):
		sink(lst,i,N)
	#print(lst)
	while N>0:
		lst[0],lst[N-1]=lst[N-1],lst[0]
		N=N-1
		sink(lst,1,N)


def sink(lst,k,N):
	while 2*k<=N:
		j=2*k
		if j<N and lst[j-1]<lst[j]:
			j=j+1
		if lst[k-1]>lst[j-1]:
			break;
		lst[k-1],lst[j-1]=lst[j-1],lst[k-1]
		k=j

if __name__== "__main__":
	lst=[12,10,23,14,34,5,6,3,2,7,10,54]
	heap(lst)
	print(lst)



快速排序

1.从数列中挑出一个元素,称为"基准"(pivot),
2.重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的 摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
3.递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

时间复杂度:O(n^2),最优时间复杂度:O(nlogn),平均时间复杂度:O(nlogn) 快排的时间复杂度跟选取基准的方法有关,一下是默认选择了第一个元素作为基准,随机性较大。

可以在序列中选取开始中间结尾三个数的中位数作为基准,进行优化。

from random import randint
#include lst[left]
def quick(lst,l,r):
	if l<r:
		#可有可无 选择一个随机数和最后一位交换
		pivot= randint(l,r)
		lst[r],lst[pivot]=lst[pivot],lst[r]
		
		split =partition(lst,l,r)
		quick(lst,l,split-1)
		quick(lst,split+1,r)

def partition(array, l, r):  
    x = array[r]  
    i = l - 1  
    for j in range(l, r):  
        if array[j] <= x:  
            i += 1  
            array[i], array[j] = array[j], array[i]  
    array[i + 1], array[r] = array[r], array[i+1]
    return i + 1  


if __name__== "__main__":
	lst=[12,10,23,14,34,5,6,3,2,7,10,54]
	quick(lst,0,len(lst)-1)
	print(lst)

用栈来实现quick排序

#用栈来解决快速排序
def quick_sort(array, l, r):  
    if l >= r:  
        return  
    stack = []  
    stack.append(l)  
    stack.append(r)  
    while stack:  
        high = stack.pop()  
        low = stack.pop()  
        if high - low <= 0:  
            continue;  
        x = array[high]  
        i = low - 1  
        for j in range(low, high):  
            if array[j] <= x:  
                i += 1  
                array[i], array[j] = array[j], array[i]  
        array[i + 1], array[high] = array[high], array[i + 1]  
        stack.extend([low, i, i + 2, high]) 

if __name__== "__main__":
    lst=[12,10,23,14,34,5,6,3,2,7,10,54]
    quick_sort(lst,0,len(lst)-1)
    print(lst)