日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python数据结构与算法之排序

發布時間:2024/4/15 python 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python数据结构与算法之排序 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

排序算法的穩定性:

假設有一串數據:(4,1)(3,1)(3,7)(5,6);要求按照第一個數排序,結果如下:

第一種:(3,1)(3,7)(4,1)(5,6)(3相同,維持原來的次序)

第二種:(3,7)(3,1)(4,1)(5,6)(3相同,次序被改變)

第一種是穩定的。

冒泡排序(以從小到大排為例):

每次走一遍把最大的元素冒泡,排到最后。

''' 冒泡排序:它也可以用于之前講的鏈表什么的,只是交換部分稍微煩一點,思想一樣。這里簡單一點 ,以數字為例 ''' def bubble_sort(alist):'''冒泡排序,參數為列表'''n = len(alist)-1for j in range(n):for i in range(n-j):if alist[i]>alist[i+1]:# 前一個大于后一個,交換alist[i], alist[i+1] = alist[i+1], alist[i] # 這樣寫在python這種動態語言中可以if __name__ == '__main__':a = [2,0,5,1,10]bubble_sort(a)print(a)

冒泡排序的時間復雜度為:最壞可以認為是O(n^2),穩定的

改進:假如傳入的序列就是有序的,比如[1,2,3,4,5,6]。此時按照上面代碼還是要一步步比較,復雜度是一樣的。改進之后,最優時間復雜度為O(n),最壞時間復雜度不變。

def bubble_sort(alist):'''冒泡排序,參數為列表'''n = len(alist)-1for j in range(n):count = 0for i in range(n-j):if alist[i]>alist[i+1]:# 前一個大于后一個,交換alist[i], alist[i+1] = alist[i+1], alist[i] # 這樣寫在python這種動態語言中可以count += 1if count == 0:return

選擇排序:

思想解釋:每次找到最小的值,與無序數中的一個數交換,比如:

a = [52,100,23,43,55,20,17,108]

找到最小值是17,將17與52交換,得:

a = [17,100,23,43,55,20,52,108]

看除了第一個數17外,其他最小的為20,與“第一個數”100交換:

a = [17,20,23,43,55,100,52,108]

此時,前面兩個數已經有序,以此往下。

def select_sort(alist):"""選擇排序,既然是研究數據結構與算法,這里不用min()函數"""n = len(alist)for j in range(n-1):# 記錄最小值的位置,這里首次默認是無序中的第一個min_index = jfor i in range(j+1,n):if alist[i]<alist[min_index]:min_index = ialist[j], alist[min_index] = alist[min_index], alist[j]

選擇排序的時間復雜度:O(n^2),不穩定

插入排序算法:

思想理解,與上面選擇排序有點雷士,其實還是將序列無形的分為兩部分。比如序列[52,100,23,43,55,20,17,108]。

將序列分為[52, ? ? ? ? ? ? ? ? ? ?? 100,23,43,55,20,17,108],第一部分是有序的。

然后將無序中的第一個100與有序中52比較,放在正確的位置[52,100, ? ? ? ? ? ? ? ? ? ?? 23,43,55,20,17,108],

同理接著比較23與[52,100],將其插入正確的位置[23,52,100, ? ? ? ? ? ? ? ? ? ? ? ? ?? 43,55,20,17,108]

?注意:插入的過程其實就是一個小排序,比如插入23時,先與100比,然后與52........

def insert_sort(alist):"""插入排序"""for j in range(1,len(alist)):i = j# 從無序部分選一個插入到有序部分的過程while i>0:if alist[i]<alist[i-1]:alist[i], alist[i-1] = alist[i-1], alist[i]i -= 1else:# 因為有序部分是有序的,只要前一個數比當前數小,那前面所有的數都比當前數小break

最壞時間復雜度是O(n^2),最優時間復雜度是O(n),穩定的

希爾排序:

它其實就是插入排序的改進版,思想百度百科一下就可以了。

簡單介紹:它有一個gap(間隙),假設gap=4。原序列為54,26,93,17,77,31,44,55,20;

因為gap=4,索引相差四的抽出,那原序列變成4層:

54, ? ? ? ? ? ? ? ? ?? 77 , ? ? ? ? ? ? 20

? ?? 26, ? ? ? ? ? ? ? ? ?? 31,

? ? ? ? ? 93, ? ? ? ? ? ? ? ? ?? 44

? ? ? ? ? ? ? 17 ? ? ? ? ? ? ? ? ? ? ?? 55

每一層排序后再插入回去,即經過第一次排序之后:20,26,44,17,54,31,93,55,77;

再取gap=2,原序列變成兩層:

20 ? ? ? ?? 44 ? ? ? ? ? 54 ? ? ? ? ?? 93 ? ? ? ?? 77

? ? ? 26 ? ? ? ?? 17 ? ? ? ?? 31 ? ? ? ? ? ?? 55

同理每層子序列用插入算法,再取gap=1.得到最后的結果。

def shell_sort(alist):"""希爾排序,核心部分其實是插入排序"""n = len(alist)gap = n//2 # 其實有最優的gap值,這里直接用長度的一半取整# gap變化為0前,插入算法執行的次數while gap>=1:# 內層循環其實就是插入算法,與普通的插入算法的區別在于gapfor j in range(gap,n):i = jwhile i>0:if alist[i]<alist[i-gap]:alist[i], alist[i-gap] = alist[i-gap], alist[i]i -= gapelse:breakgap //= 2

最壞時間復雜度O(n^2),最優時間復雜度根據gap值不同的而不同(優化問題)。不穩定

快速排序

具體思想介紹可以百度一下,其實有點像冒泡的改進。舉個例子:

假設原序列為:54,26,93,17,77,31,44,55,20;

先找到第一個數54在有序情況下的位置,怎么找?設定兩個游標,游標low先指向26,游標high先指向最后一個數20.

當low指向的數小于54時,可以繼續向high的方向移動,否則先靜止;同理當high指向的數大于54時可以向low的方向移動,否則靜止;

按照上面的要求,此時54,26,93(low),17,77,31,44,55,20(high);

卡主不動了,這時候交換93,20的位置,數據變成54,26,20(low),17,77,31,44,55,93(high);這時不卡了,繼續移動(先動low),一直到low與high重合,如下:

54, ? ? ? ?? 26,20,17,31,44(low_and_high),77,55,93

此時確定54的位置:26,20,17,31,44, ? ? ? ? ? ? ? ?? 54 ? ? ? ? ? ? ? ? ? ? ,77,55,93同理處理54前后兩部分;

?

大致思想是這樣,為了方便編程,稍微變通一下(仍然是快速排序):

序列還是上面那個,一開始low指向54,high指向20,設一個mid_value=54(把第一個數存起來),游標還是往中間動;

high先動,能動的條件一樣,此時20,high游標不能動,就將20代替low指向的數(54早已存起來)。變成20(low),26,93,17,77,31,44,55,空(high);

這時候low動起來,一直到:20,26,93(low),17,77,31,44,55,空(high)

替換:20,26,空(low),17,77,31,44,55,93(high);high動

最終:20,26,44,17,31,空(low_high),77,55,93

讓空=54,20,26,44,17,31, ? ? ? ? ? 54, ? ? ? ? ?? 77,55,93,同理處理54兩邊。

1 def quick_sort(alist): 2 """快速排序,錯誤示范,錯誤的地方在下面遞歸""" 3 n = len(alist) 4 mid_value = alist[0] 5 low = 0 6 high = n-1 7 8 while low < high: 9 # high左移動(等于的情況放一邊處理比較好) 10 while low < high and alist[high] >= mid_value: 11 high -= 1 12 alist[low] = alist[high] 13 # low右移 14 while low < high and alist[low] < mid_value: 15 low += 1 16 alist[high] = alist[low] 17 # 從while退出,low等于high 18 alist[low] = mid_value 19 20 # mid_walue兩邊處理方式與上面一樣 21 quick_sort(alist[:low-1]) #不能切片傳,這等于傳一個新的列表了,也就是說操作的不是一個列表 22 quick_sort(alist[low+1:]) 錯誤示范 def quick_sort(alist, first, last):"""快速排序:param alist: 列表:param first: 列表的第一個元素索引,0:param last: 列表最后一個元素,len()-1:return:"""# 遞歸的終止條件if first >= last:returnmid_value = alist[first]low = firsthigh = lastwhile low < high:# high左移動(等于的情況放一邊處理比較好)while low < high and alist[high] >= mid_value:high -= 1alist[low] = alist[high]# low右移while low < high and alist[low] < mid_value:low += 1alist[high] = alist[low]# 從while退出,low等于highalist[low] = mid_value# mid_walue兩邊處理方式與上面一樣quick_sort(alist, first, low-1)quick_sort(alist, low+1, last)if __name__ == '__main__':b = [54,26,93,17,77,31,44,55,20]quick_sort(b,0,len(b)-1)print(b)

快速排序的最優時間復雜度O(nlogn),最壞時間復雜度O(n^2),不穩定。

歸并排序:

思想:百度一下就好

def Merge_Sort(lists):if len(lists) <= 1:return listsmid = int(len(lists) / 2)# left 采用歸并排序后形成的有序的新的列表left = Merge_Sort(lists[:mid])# right 采用歸并排序后形成的有序的新的列表right = Merge_Sort(lists[mid:])# 將兩個有序的子序列合并# Merge(left, right)r, l=0, 0 # 為兩個指針result=[]while l<len(left) and r<len(right):if left[l] < right[r]:result.append(left[l])l += 1else:result.append(right[r])r += 1result += list(left[l:])result += list(right[r:])return resultif __name__ == '__main__':b = [54,26,93,17,77,31,44,55,20]b = Merge_Sort(b)print(b)

上面代碼遞歸有點復雜,執行流程可看https://www.bilibili.com/video/av21540971/?p=35

最壞與最優時間復雜度都是:O(nlogn),穩定。

堆排序沒介紹,可以百度一下,快速排序用的比較多。

?

轉載于:https://www.cnblogs.com/maxiaonong/p/10521552.html

總結

以上是生活随笔為你收集整理的python数据结构与算法之排序的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。