主要参考:数据结构(C语言版)-严蔚敏
目录
排序分为内部排序和外部排序。
内部排序:待排记录存放在计算机随机存储器中进行的排序过程;
内部排序:待排记录的数量非常大,内存不能全部容纳,在排序过程中尚需对外存访问的排序过程。
排序可以分为稳定排序和不稳定排序。
稳定排序:两个相同数字,排序前后相对位置不变;
不稳定排序:两个相同数字,排序前后相对位置改变。
插入排序
插入的序列是有序的
1-直接插入排序
原理:将一个记录插入到一组已经排序好的有序表中,涉及两个操作:比较大小和移动到正确位置(在n值较小时,效率很高)
时间复杂度:最好 O(N),最坏O(),平均O(),稳定排序
最好仅需要比较n-1次,最坏 2+3+4+...+n-1+n= (n+2)(n-1)/2 = O()
空间复杂度O(1)
a = [49,38,65,97,76,13,27,49] #从小到达
def straight_insertion_sort(a):
for i in range(1,len(a)):
j = i
temp = a[j] #
while(j>0 and temp < a[j-1]):
a[j] = a[j-1] #大的元素往后移动
j -= 1 #继续寻找下一个更小的
##终止,当前元素就找见了应该插入的位置
a[j] = temp
return a
2-折半(二分)插入排序
在直接插入排序的基础上,缩减查找需要的次数->折半查找。
时间复杂度:平均O(),稳定排序
空间复杂度:O(1)
想看例子可看:https://blog.csdn.net/weixin_42245157/article/details/80458542
def half_insertion_sort(a):
for i in range(1,len(a)):
temp = a[i] #待排
low,high = 0,i-1 #从 前面i-1 个中找位置
while(low <= high): #找合适的位置
m = (low+high)// 2
if a[m] > temp:
high = m-1
else:
low = m+1
for j in range(i-1,high-1,-1): ##high+1的位置是应该插入的地方
a[j+1] = a[j] #移动位置给a[i]
a[j+1] = temp
return a
3-希尔排序
希尔排序又称为“缩小增量排序”,基本思想:先将待排序列分割成几个子序列进行直接插入排序,待排序序列基本有序时,在对全体记录进行一次直接插入排序(序列基本有序时且n较小时,直接插入排序算法效率很高)。
时间复杂度:
空间复杂度:O(1)
def shell_insert(a,k):
for i in range(k+1,len(a)):
if a[i] < a[i-k]: #按照k的比较
temp = a[i]
j = i-k
while( j>=0 and temp < a[j]): #找位置
a[j+k] = a[j]
j -= k
a[j+k] = temp
def shell_sort(a):
dlta = [5,3,1]
## 增量是素数
## 最后一个必须是1,作用就是最后一遍的直接插入排序
for i in range(0,len(dlta)):
shell_insert(a,dlta[i])
return a
快速排序
快速排序是借助“交换”的方式,来进行排序的。
1-冒泡排序(起泡排序)
原理:每一次将最大的放在最后面,然后再往比较前n-1个,继续这个过程
时间复杂度:最坏O(),最好O(N),平均O()
空间复杂度:O(1)
def bubble_sort(a):
for i in range(0,len(a)-1):
temp = a[i]
for j in range(i+1,len(a)):
if a[j] < temp:
t = a[j]
a[j] = temp
temp = t
a[i] = temp
return a
2-快速排序
原理:采用分治思想,以任意一个数为基准,将其分成两个部分,其中一个部分都比此数小,一个都比此数大,这样就找到了该数据在数组中的正确位置。然后再在两个部分利用此思想,递归完成所有排序。具体例子可看:https://blog.csdn.net/nrsc272420199/article/details/82587933
时间复杂度:最坏O(),平均和最好:O(NlogN)
空间复杂度:O(logN):因为递归需要栈空间来实现,每一趟都分割成相同的两个子序列,那么栈空间的最大深度为:,如果中枢偏向某一侧,则最大深度为n。利用上述方法,栈的最大深度为 O(logN)。
解释一下为什么是log2N,因为每次都是平均分成两个部分,那么每一次都是 n/2/2/2....这样的形式,先进行中枢左面的,然后在进行中枢右面的,所以共需要 log2N存储空间的向下取整+1。
a = [1,2,4,11,31,0,3] ##从大到小
def one_sort(a,low,high):
temp = a[low]
while(low < high):
while(low<high and a[high] < temp):
high -= 1
a[low] = a[high]
while(low<high and a[low] > temp):
low += 1
a[high] = a[low]
a[low] = temp
return low
def quick_sort(a,low,high):
if low<high :
index = one_sort(a,low,high)
quick_sort(a,low,index-1)
quick_sort(a,index+1,high)
return a
print(quick_sort(a,0,len(a)-1))
选择排序
1-简单选择排序
原理:从N个数字中挑出最小的,拿出来放在第一位,然后再找第二小的再放。
时间复杂度:最好,最坏,平均,都是O()
空间复杂度:O(1)
def simple_selection_sort(a):
for i in range(0,len(a)-1):
index = i
for j in range(i+1,len(a)):
if a[j] > a[index]:
index = j
temp = a[i]
a[i] = a[index]
a[index] = temp
return a
2-堆排序
堆排序(Heap Sort)对于记录较小的文件不好用,但对于较大的文件还是比较有效的。
时间复杂度: 最坏O(NlogN) 平均 O(NlogN) 不稳定排序
空间复杂度:O(1)
例子可见:https://www.jianshu.com/p/d174f1862601
def heapadjust(a,start,end):
temp = a[start]
j = 2*start
while j <= end :
if j < end and a[j] < a[j+1]:
j += 1
if temp >= a[j]:
break
else:
a[start] = a[j]
start = j
j *= 2
a[start] = temp
def Heap_sort(a):
i = len(a)//2
for i in range(i,-1,-1): #建堆
heapadjust(a,i,len(a)-1)
for i in range(len(a)-1,0,-1):
temp= a[i]
a[i] = a[0]
a[0] = temp ##将堆顶记录和未经排序最后一个记录交换
heapadjust(a,0,i-1) #重调堆
return a
归并排序
“归并”的含义是将两个或两个以上的有序表组合成一个新的有序表。
2-路归并排序
时间复杂度:O(NlogN) 稳定排序
空间复杂度:O(N) ## 主要是在“合”的过程中使用container的空间。
代码摘自:https://blog.csdn.net/perfer258/article/details/81985349(有详细的例子)
a = [49,38,65,97,76,13,27,49] ##从小到大
def sort(arr, low, high): ##平分过程
if low < high:
mid = (low + high) // 2
sort(arr, low, mid)
sort(arr, mid+1, high)
merge(arr, low, mid, high)
def merge(arr, low, mid, high):
container = [] # 用于存储有序数字
i, j = low, mid+1
while i <= mid and j <= high: ##比较合并过程
if arr[i] <= arr[j]:
container.append(arr[i])
i += 1
else:
container.append(arr[j])
j += 1
if i <= mid:
container.extend(arr[i:mid+1])
elif j <= high:
container.extend(arr[j:high+1])
arr[low:high+1] = container
def merge_sort(arr):
sort(arr, 0, len(arr)-1)
return arr
非递归的写法:
详细讲解可参考https://www.cnblogs.com/edwinchen/p/4783218.html
def merge_sort(a):
i = 1 # i是步长
while i < len(a):
low = 0
while low < len(a):
mid = low +i-1
#mid指向左边有序序列最后一个,mid+1是右边有序的开始
high = min(low+2*i-1,len(a)-1)
merge(a, low, mid, high) #递归例子中的merge
low += 2*i
i *= 2
return a
基数排序
基数排序(Radix Sorting)不需要进行记录关键字间的比较,是一种借助于多关键字排序的思想对单逻辑关键字进行排序的方法。基数排序是借助分配和收集对单逻辑关键字进行排序的一种内部排序方法。
其他排序
1-桶排序
不想写了,看这个博客。https://www.jianshu.com/p/204ed43aec0c