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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > python >内容正文

python

python数据结构与算法之排序

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

排序算法的穩(wěn)定性:

假設(shè)有一串?dāng)?shù)據(jù):(4,1)(3,1)(3,7)(5,6);要求按照第一個(gè)數(shù)排序,結(jié)果如下:

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

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

第一種是穩(wěn)定的。

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

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

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

冒泡排序的時(shí)間復(fù)雜度為:最壞可以認(rèn)為是O(n^2),穩(wěn)定的

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

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

選擇排序:

思想解釋:每次找到最小的值,與無(wú)序數(shù)中的一個(gè)數(shù)交換,比如:

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

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

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

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

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

此時(shí),前面兩個(gè)數(shù)已經(jīng)有序,以此往下。

def select_sort(alist):"""選擇排序,既然是研究數(shù)據(jù)結(jié)構(gòu)與算法,這里不用min()函數(shù)"""n = len(alist)for j in range(n-1):# 記錄最小值的位置,這里首次默認(rèn)是無(wú)序中的第一個(gè)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]

選擇排序的時(shí)間復(fù)雜度:O(n^2),不穩(wěn)定

插入排序算法:

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

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

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

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

?注意:插入的過(guò)程其實(shí)就是一個(gè)小排序,比如插入23時(shí),先與100比,然后與52........

def insert_sort(alist):"""插入排序"""for j in range(1,len(alist)):i = j# 從無(wú)序部分選一個(gè)插入到有序部分的過(guò)程while i>0:if alist[i]<alist[i-1]:alist[i], alist[i-1] = alist[i-1], alist[i]i -= 1else:# 因?yàn)橛行虿糠质怯行虻?#xff0c;只要前一個(gè)數(shù)比當(dāng)前數(shù)小,那前面所有的數(shù)都比當(dāng)前數(shù)小break

最壞時(shí)間復(fù)雜度是O(n^2),最優(yōu)時(shí)間復(fù)雜度是O(n),穩(wěn)定的

希爾排序:

它其實(shí)就是插入排序的改進(jìn)版,思想百度百科一下就可以了。

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

因?yàn)間ap=4,索引相差四的抽出,那原序列變成4層:

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

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

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

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

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

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

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

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

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

def shell_sort(alist):"""希爾排序,核心部分其實(shí)是插入排序"""n = len(alist)gap = n//2 # 其實(shí)有最優(yōu)的gap值,這里直接用長(zhǎng)度的一半取整# gap變化為0前,插入算法執(zhí)行的次數(shù)while gap>=1:# 內(nèi)層循環(huán)其實(shí)就是插入算法,與普通的插入算法的區(qū)別在于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

最壞時(shí)間復(fù)雜度O(n^2),最優(yōu)時(shí)間復(fù)雜度根據(jù)gap值不同的而不同(優(yōu)化問(wèn)題)。不穩(wěn)定

快速排序

具體思想介紹可以百度一下,其實(shí)有點(diǎn)像冒泡的改進(jìn)。舉個(gè)例子:

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

先找到第一個(gè)數(shù)54在有序情況下的位置,怎么找?設(shè)定兩個(gè)游標(biāo),游標(biāo)low先指向26,游標(biāo)high先指向最后一個(gè)數(shù)20.

當(dāng)low指向的數(shù)小于54時(shí),可以繼續(xù)向high的方向移動(dòng),否則先靜止;同理當(dāng)high指向的數(shù)大于54時(shí)可以向low的方向移動(dòng),否則靜止;

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

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

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

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

?

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

序列還是上面那個(gè),一開始low指向54,high指向20,設(shè)一個(gè)mid_value=54(把第一個(gè)數(shù)存起來(lái)),游標(biāo)還是往中間動(dòng);

high先動(dòng),能動(dòng)的條件一樣,此時(shí)20,high游標(biāo)不能動(dòng),就將20代替low指向的數(shù)(54早已存起來(lái))。變成20(low),26,93,17,77,31,44,55,空(high);

這時(shí)候low動(dòng)起來(lái),一直到:20,26,93(low),17,77,31,44,55,空(high)

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

最終: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 """快速排序,錯(cuò)誤示范,錯(cuò)誤的地方在下面遞歸""" 3 n = len(alist) 4 mid_value = alist[0] 5 low = 0 6 high = n-1 7 8 while low < high: 9 # high左移動(dòng)(等于的情況放一邊處理比較好) 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]) #不能切片傳,這等于傳一個(gè)新的列表了,也就是說(shuō)操作的不是一個(gè)列表 22 quick_sort(alist[low+1:]) 錯(cuò)誤示范 def quick_sort(alist, first, last):"""快速排序:param alist: 列表:param first: 列表的第一個(gè)元素索引,0:param last: 列表最后一個(gè)元素,len()-1:return:"""# 遞歸的終止條件if first >= last:returnmid_value = alist[first]low = firsthigh = lastwhile low < high:# high左移動(dòng)(等于的情況放一邊處理比較好)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)

快速排序的最優(yōu)時(shí)間復(fù)雜度O(nlogn),最壞時(shí)間復(fù)雜度O(n^2),不穩(wěn)定。

歸并排序:

思想:百度一下就好

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:])# 將兩個(gè)有序的子序列合并# Merge(left, right)r, l=0, 0 # 為兩個(gè)指針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)

上面代碼遞歸有點(diǎn)復(fù)雜,執(zhí)行流程可看https://www.bilibili.com/video/av21540971/?p=35

最壞與最優(yōu)時(shí)間復(fù)雜度都是:O(nlogn),穩(wěn)定。

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

?

轉(zhuǎn)載于:https://www.cnblogs.com/maxiaonong/p/10521552.html

總結(jié)

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

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。