python 下的数据结构与算法---6:6大排序算法
頂先最后推薦:哈哈,意思是放到頂部強(qiáng)調(diào)其重要性,但是應(yīng)該我總結(jié)的六種算法看完了后再看的一篇醍醐灌頂?shù)奈恼?/p>
?
一:冒泡排序(Bubble Sort)
原理:假設(shè)有n個(gè)數(shù),第一輪時(shí):從第一個(gè)元素開始,與相鄰的元素比較,如果前面的元素小就交換,直到第n-1個(gè)元素時(shí),這樣的結(jié)果是將最大的元素放到了最后,同理,第二輪還是從第一個(gè)元素開始比較,直到第n-2個(gè)元素,這樣能夠把剩下的n-1個(gè)數(shù)中的最大的數(shù)放到第n-1的位置,一直這樣進(jìn)行n-1輪就能夠完成排序。?
1 def Bublesort(seq): 2 i = 0 3 j = 0 4 while i < len(seq): 5 while j < len(seq)-i-1: 6 if seq[j] > seq[j+1]: 7 seq[j],seq[j+1] = seq[j+1],seq[j] 8 else: 9 j+=1 10 j=0 11 i+=1 12 13 a=[3,4,6,2,1] 14 Bublesort(a) 15 print(a) 冒泡排序由代碼可知,其時(shí)間復(fù)雜度為O(n2).
?
二:選擇排序(Selection Sort)
原理:選擇排序的思路非常簡(jiǎn)單,每次都遍歷找出上次剩下的元素中的最大數(shù),然后和剩下數(shù)中隨后一個(gè)元素交換位置,一個(gè)進(jìn)行n-1次
1 #coding:utf-8 2 #Attention:max標(biāo)志需取為seq[0],我剛開始取了0,這會(huì)導(dǎo)致最后一次比較時(shí)出問(wèn)題 3 def SelectionSort(seq): 4 i,j,maxel = 0,0,seq[0] 5 while i < len(seq): 6 while j < len(seq)-i: 7 if seq[j] > maxel: 8 maxel = j 9 j+=1 10 seq[maxel],seq[len(seq)-i-1] = seq[len(seq)-i-1],seq[maxel] 11 j,maxel=0,seq[0] 12 i+=1 13 14 a=[3,4,6,2,1] 15 SelectionSort(a) 16 print(a) 選擇排序可以看出的是,其時(shí)間復(fù)雜度依然是O(n2),看起來(lái)和冒泡排序一樣,但由于每輪其交換位置的次數(shù)少,故實(shí)際上其比冒泡排序好。
?
三:插入排序(Insertion Sort)
原理:如下圖所示,將第一個(gè)元素作為標(biāo)準(zhǔn),每次將下一個(gè)元素放到前面正確的位置中去。
技巧:從已排好序元素最后一個(gè)開始遍歷比較,因?yàn)椴迦胍苿?dòng)只會(huì)移動(dòng)其后面的元素。
1 def insertion_sort(a_list): 2 for index in range(1, len(a_list)): 3 current_value = a_list[index] 4 position = index 5 while position > 0 and a_list[position - 1] > current_value: #從目前元素開始向前,若>目前值就后移一位 6 a_list[position] = a_list[position - 1] 7 position = position - 1 8 a_list[position] = current_value 9 10 a = [54, 26, 93, 17, 77, 31, 44, 55, 20] 11 insertion_sort(a) 12 print(a) 插入排序
依舊可以看出的是,其時(shí)間復(fù)雜度為O(n2),但是他的不同之處在于其始終保持了一個(gè)部分有序的序列
?
四:希爾排序(Shell Sort)
希爾排序這章書里面的配圖不好,導(dǎo)致我理解錯(cuò)誤直到運(yùn)行程序出錯(cuò)才發(fā)現(xiàn)錯(cuò)誤,后來(lái)看了些其他資料弄明白了。其實(shí)希爾排序就是跳躍式插入排序,我們?cè)囅胍幌?#xff0c;如果一個(gè)元素集是9,8,7,6,5,4,3,2,1,那么每次插入排序都要全部后移了,這樣效率極低,如果能夠不按順序的進(jìn)行插入排序就好多了,雖然每次并沒(méi)有完全排好序,但是能夠讓他們離真實(shí)的位置更近,這就是其優(yōu)勢(shì)所在了。
實(shí)現(xiàn)原理:每次取一個(gè)gap,第一次取集合元素個(gè)數(shù)整除2的結(jié)果,然后對(duì)從首元素開始每gap距離的元素組合成一個(gè)組并對(duì)其進(jìn)行插入排序,假設(shè)集合[54, 26, 93, 17, 77, 31, 44, 55, 20],那么第一次gap為9//2=4,那么就能夠有這些組:[54,77,20],[26,31],[93,44],[17,55],注意,并不是對(duì)其真的分組,只是將其看作一組后進(jìn)行插入排序,那么結(jié)果是:[20, 26, 44, 17, 54, 31, 93, 55, 77],到此,第一次完成。第二次把gap改為上次gap//2的結(jié)果,也就是2,所以對(duì)上次的結(jié)果分組為[20,44,54,93,77],[26,17,31,55],對(duì)其進(jìn)行插入排序后的結(jié)果是[20, 17, 44, 26, 54, 31, 77, 55, 93],到此第二次完成。第三次gap為1,注意,當(dāng)gap為1時(shí)就表明是最后一輪了,最上此結(jié)果[20, 17, 44, 26, 54, 31, 77, 55, 93]全部進(jìn)行插入排序就能夠得到結(jié)果了。【仔細(xì)看看就能夠發(fā)現(xiàn)其每次排序后真的是數(shù)字離其真實(shí)位置更近了】。
注意:有個(gè)控制循環(huán)的條件就是每次分組的組數(shù)其實(shí)就是gap的值,容易看出是兩層控制,外層控制進(jìn)入的哪組分組,內(nèi)層控制具體每組的插入排序
1 def shell_sort(a_list): 2 sublist_count = len(a_list) // 2 3 while sublist_count > 0: 4 for start_position in range(sublist_count): 5 gap_insertion_sort(a_list, start_position, sublist_count) 6 print("After increments of size", sublist_count, "The list is",a_list) 7 sublist_count = sublist_count // 2 8 9 def gap_insertion_sort(a_list,start, gap): 10 for i in range(start + gap, len(a_list), gap): 11 current_value = a_list[i] 12 position = i 13 while position >= gap and a_list[position - gap] > current_value: 14 a_list[position] = a_list[position - gap] 15 position = position - gap 16 a_list[position] = current_value 17 18 a_list = [54, 26, 93, 17, 77, 31, 44, 55, 20] 19 shell_sort(a_list) 20 print(a_list) 希爾排序
?五:歸并排序(Merge Sort)
原理圖:由圖可以看出,其也是用了遞歸原理,base就是只剩一個(gè)元素時(shí)返回其本身
1 def partition(seq, start, mid, stop): 2 lst = [] 3 i = start 4 j = mid 5 while i < mid and j < stop: 6 if seq[i] < seq[j]: 7 lst.append(seq[i]) 8 i+=1 9 else: 10 lst.append(seq[j]) 11 j+=1 12 while i < mid: 13 lst.append(seq[i]) 14 i+=1 15 while j < stop: 16 lst.append(seq[j]) 17 j+=1 18 for i in range(len(lst)): 19 seq[start+i]=lst[i] 20 21 def mergeSortRecursively(seq, start, stop): 22 if start >= stop-1: 23 return 24 mid = (start + stop) // 2 25 mergeSortRecursively(seq, start, mid) 26 mergeSortRecursively(seq, mid, stop) 27 partition(seq, start, mid, stop) 28 29 a=[3,4,6,8,2,1,5,9] 30 mergeSortRecursively(a, 0, len(a)) 31 print(a) 歸并排序
來(lái)分析下其時(shí)間復(fù)雜度吧,由于每次都將list二分,這是logn,而每次排列是n,由于這兩小步組成一步,故時(shí)間復(fù)雜度為O(nlogn)
?
六:快速排序(Quick Sort)
原理:如下,第一次以第一個(gè)元素為標(biāo)志,將后面小的放他左邊,大的放他右邊,而后將其放到中間。第二次分別在其兩邊重復(fù)這樣的過(guò)程,最后直到每組只有一個(gè)數(shù)據(jù)。
有個(gè)需要注意的是最壞情況下為以排好序的集合,那么后面的數(shù)都標(biāo)志大或者小,操作太多或者無(wú)效,最理想的是標(biāo)志能夠是平均值左右,故最好對(duì)數(shù)據(jù)進(jìn)行隨機(jī)化處理。
還有,看完代碼后注意比較,可以是快速排序與歸并排序是某種程度相反的,歸并到了最后兩個(gè)元素才開始排序,從部分有序積累到全部有序,而二分是反的,從第一次二分就是整個(gè)數(shù)列的二分,,最后二分到只有兩個(gè)元素時(shí),此時(shí)完成了全部有序。
1 import random 2 def partition(seq, start, stop): 3 pivotIndex = start 4 pivot = seq[pivotIndex] 5 i = start+1 6 j = stop-1 7 while i <= j: 8 while pivot > seq[i]: 9 i+=1 10 while pivot < seq[j]: 11 j-=1 12 if i < j: 13 seq[j],seq[i] = seq[i],seq[j] 14 i+=1 15 j-=1 16 seq[pivotIndex],seq[j] = seq[j],pivot 17 return j 18 19 def quicksortRecursively(seq, start, stop): 20 if start >= stop-1: 21 return 22 pivotIndex = partition(seq, start, stop) 23 quicksortRecursively(seq, start, pivotIndex) 24 quicksortRecursively(seq, pivotIndex+1, stop) 25 26 def quicksort(seq): 27 # randomize the sequence first 28 for i in range(len(seq)): 29 j = random.randint(0,len(seq)-1) 30 seq[i],seq[j] = seq[j],seq[i] 31 32 quicksortRecursively(seq, 0, len(seq)) 33 34 a=[3,4,6,8,2,1,5,9] 35 quicksort(a) 36 print(a) 快速排序同理可以分析出其時(shí)間復(fù)雜度為O(nlogn)
轉(zhuǎn)載于:https://www.cnblogs.com/pengsixiong/p/5323772.html
總結(jié)
以上是生活随笔為你收集整理的python 下的数据结构与算法---6:6大排序算法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Ubuntu MySQL 授权语句错误
- 下一篇: python做圆柱绕流_Fluent学习