主要參考:數據結構(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)
代碼摘自: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 a
非遞歸的寫法:
詳細講解可參考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