python數據結構《排序專題復習》

目錄

常見的三種排序方法

冒泡排序

插入排序

選擇排序

其他經典的排序方法

快速排序

堆排序

歸并排序

?希爾排序

?不同排序方法的各維度對比


排序方式的穩定性:若兩個相同的元素在排序前后的相對位置不發生改變的排序為穩定排序,否則不穩定排序

常見的三種排序方法

以【3,2,2,1,1】為例

冒泡排序

冒泡排序思路:不斷地對比相鄰的兩個元素,將若前面的元素 大于(注意不含等于) 后面的元素,則兩個元素進行位置交換。

# 冒泡排序,復雜度為O(n^2)
def bubble_sorted(li:list)->list:for i in range(len(li)):# 第幾趟exchanged = False# 這個是為了防止多余的遍歷,如果前面的元素已經是排序好的,那就不需要再進行比較了,減少運行時間for j in range(len(li)-1):# 遍歷列表元素if li[j] > li[j+1]:li[j],li[j+1] = li[j+1],li[j]exchanged = Trueif not exchanged:return li

第一趟

32(1)2(2)1(1)1(2)
2(1)32(2)1(1)1(2)
2(1)2(2)31(1)1(2)
2(1)2(2)1(1)31(2)
2(1)2(2)1(1)1(2)3

第二趟

第三趟

第四趟? 、第五趟、第六趟

可見在經過冒泡排序后,相同元素的相對前后位置沒有發生改變 ,因此排序是穩定的。

插入排序

插入排序的思路:從左到右,分為有序區和無序區,每次都是將無序區的第一個元素取出插入到有序區間中。然后從右往左遍歷有序區,當遍歷的有序元素大于該元素時,有序元素右移一位,繼續遍歷有序區;直到遍歷的有序元素小于等于無序區元素第一個元素時,停止遍歷,并且將該元素插入到停止遍歷有序元素的后一個位置

# 插入排序,復雜度為O(n^2),思路是從左到右抽取一個元素,將這個元素,與左邊鄰近的元素比較,若比左邊的小,則左邊元素右移,
# 若不比左邊的小了或者已經到最左邊了,則將抽取的元素賦值給原本左邊元素
def insert_sorted(li:list)->list:for i in range(1,len(li)):# 趟數,也就是抽牌的順序,從第一張牌開始抽tmp = li[i]j = i - 1# 左邊元素while j >= 0 and li[i] < li[j]:# 若抽取的元素小于鄰近左邊的元素,則將左邊元素右移一格li[j+1] = li[j]j -= 1# 這時候的j已經不滿足上述條件了,因此這個j位置上的元素沒有移動,而j+1上位置的元素移動了是空的li[j+1] = tmpreturn li
32(1)2(2)1(1)1(2)
2(1)32(2)1(1)1(2)
2(1)2(2)31(1)1(2)
1(1)2(1)2(2)31(2)
1(1)1(2)2(1)2(2)3

可見在經過插入排序后,相同元素的相對前后位置沒有發生改變 ,因此排序是穩定的。?

選擇排序

選擇排序的思路:分為有序區和無序區,每次將無序區的最小元素放在無序區的第一個位置,期間會發生元素的交換

# 選擇排序,復雜度為O(n^2),思路是遍歷一趟元素后,選擇最小的值放在無序區的第一位
def select_sorted(li:list)->list:for i in range(len(li)):min_loc = i# 初始化最小值的位置為第一個for j in range(i+1,len(li)-1):if li[j]<li[min_loc]:li[j],li[min_loc] = li[min_loc],li[j]# 交換元素return li

?第一趟

32(1)2(2)1(1)1(2)
2(1)32(2)1(1)1(2)
2(1)32(2)1(1)1(2)
1(1)32(2)2(1)1(2)

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

?在第一趟的選擇排序種,我們可以看到相同元素2(1)和2(2)的相對位置在排序前后發生了變化,因此是不穩定排序

其他經典的排序方法

快速排序

快排的思路:先取序列首元素作為基準值,將序列中小于基準值的元素放在左邊,大于基準值的元素放在右邊(相等的元素放在任一邊均可)。然后以該基準值作為邊界,對左右子序列遞歸進行快速排序即可實現排序

具體步驟:

1)選擇序列首元素作為基準值,左指針指向序列首位,右指針指向序列尾部;

2)若右指針的元素值大于基準值,右指針繼續左移;否則將右指針指向的元素賦值給左指針;

3)賦值完后,移動左指針,若左指針的元素小于基準值,左指針右移,否則將左指針指向的元素賦值給右指針處;

4)重復2)3)直到左右指針重合,將基準值賦值給重合的位置;

5)對左右子序列遞歸使用1)-4)步驟,這樣就實現了對序列的快速排序,遞歸終止條件為序列含有1個元素,即left<right這里保證有兩個元素的時候進行遞歸,否則退出

def partition(li:list,left:int,right:int)->int:'''這是根據路飛商城的思路來的將p元素歸位的函數:取第一個元素為p元素,移動right,若right指針的值大于P,則right繼續往左移動,否則停止移動,將值賦值給left所在的位置;然后再移動left,若left指針的值小于P,則left繼續往右移動,否則停止移動,將值賦值給right所在的位置;如此交替移動,直到left=right時,停止,并將P值賦值給left(right):param li: 需要歸位的列表:param left: 列表左指針索引,初始值為0:param right: 列表右指針索引,初始值為len(li)-1:return: 返回p歸位的索引'''#得到要歸位的元素(第一個元素)p = li[left]#當列表有兩個元素時,才進行排序while left < right:# 保證有兩個元素#這里我們從列表的右邊開始進行元素的比較while left < right and p < li[right]: # 至少兩個元素并且p元素值小于等于right指針指向的值時,右指針左移right -= 1 # right 左移一步li[left] = li[right] # 不滿足上述循環條件時,停止移動right,并且將right上的值賦值給left#右指針停止移動后,開始進行左指針的移動while left < right and p > li[left]:left += 1li[right] = li[left]#當left = right時,說明已經歸位了,將p賦值給歸位位置li[left] = preturn leftdef quickSorted(li,left,right):'''對列表進行快排:param li: 需要排序的列表:param left: 左索引:param right: 右索引:return: 返回排好序的列表'''if left < right:mid = partition(li, left, right)  # 首先得到第一個歸位索引# 對左邊列表進行排序quickSorted(li,left,mid-1)# 對右邊列表進行排序quickSorted(li,mid + 1,right)

?第一趟

基準值p = 5

54(1)94(2)8
54(1)94(2)8
4(2)4(1)94(2)8
4(2)4(1)998
4(2)4(1)598

?由上面可以看出,在進行一趟排序后,兩個4的相對位置發生了改變,因此快速排序是不穩定的

?。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

堆排序

堆排序是利用了二叉樹的數據結構來實現的,穩定排序

歸并排序

歸并排序的思路:將兩個有序序列利用雙指針進行合并

難點:如何將待排序的序列變成兩個有序序列,當元素只有一個的時候序列是有序的,這個是比較容易理解的。因此這里利用遞歸的方式,先將列表拆成一個個單元素列表,然后再一個個元素(有序序列)合并,回溯即可實現排序

'''
歸并排序的主要思路:將兩個有序的子列表歸并為一個有序的大列表
'''#歸并函數,假設li是由左右兩個有序的子列表組成,假設兩個子列表都是從小到大排好序的列表
def merge(li,low,mid,high):''':param li: 由左右兩個有序的子列表組成的大列表:param low: 列表的起始索引:param mid: 兩個子列表的分解處的索引,這里取前面子列表的最后一個元素的索引為mid:param high: 大列表最后一個索引:return: 從小到大排序的列表'''# 當列表中有兩個元素時進行歸并操作i = low # 第一個子列表的起始索引j = mid + 1 # 第二個子列表的起始索引比較好了的元素lTmp = [] # 用于保存while i <= mid and j <= high: # 當兩個子列表都沒有遍歷完時if li[i] > li[j]:lTmp.append(li[j])j += 1else:lTmp.append(li[i])i += 1while i <= mid:# 當右列表訪問結束后,直接將左列表進行添加lTmp.append(li[i])i += 1while j <= high:lTmp.append(li[j])j += 1li[low:high+1] = lTmp#歸并排序
def mergeSorted(li,low,high):''':param li: 列表:param low: 列表起始索引:param high: 列表結束索引:return: '''if low < high: # 保證列表有兩個元素mid = (low + high)//2mergeSorted(li,low,mid) # 對左列表進行排序mergeSorted(li,mid+1,high) # 對右列表進行排序merge(li,low,mid,high) # 將排好序的兩個列表進行歸并

?歸并排序是穩定排序方式,因為在進行有序列表的合并時,這里看成左右子序列的合并,只有當左序列中的元素大于右子序列的元素的時候,才會將右子序列的元素添加到列表中,這也就保證了在左右序列中有相等元素時,會先將左序列的元素存放在列表中,然后再將右序列的元素存放在列表中

?希爾排序

希爾排序思路:希爾排序的思路其實和歸并排序是類似的,都是利用分治的方法實現,不同的是歸并排序是另開一個數組來合并兩個有序的序列進而實現序列的排序;而希爾排序則是利用插入的方式將兩個子序列合并在一起,在序列原地進行修改

'''
希爾排序:將列表分成多組,對每一組進行插入排序,最后合并在一起,d1=len//2,di=d(i-1)//2,直到di=1,退出
'''def insert_sorted_shell(li:list,gap:int)->list:''':param li: 列表:param gap: 分組的組數和每個元素在大列表中的間隔:return: '''for i in range(gap,len(li)):# 趟數,也就是抽牌的順序,從第一張牌開始抽tmp = li[i]j = i - gap# 左邊元素while j >= 0 and li[i] < li[j]:# 若抽取的元素小于鄰近左邊的元素,則將左邊元素右移一格li[j+gap] = li[j]j -= gap# 這時候的j已經不滿足上述條件了,因此這個j位置上的元素沒有移動,而j+1上位置的元素移動了是空的li[j+gap] = tmpreturn lidef shellSorted(li):n = len(li)d = n//2while d >= 1:insert_sorted_shell(li,d)d //= 2

注意:快速排序、歸并排序的左右索引都是閉區間

?不同排序方法的各維度對比

排序方法冒泡排序插入排序選擇排序快速排序歸并排序希爾排序
穩定性穩定穩定不穩定不穩定穩定穩定
時間復雜度O(n^2)O(n^2)O(n^2)O(nlgn)O(nlogn)O(n^(3/2) )
空間復雜度O(1)O(1)O(1)O(1)O(n)O(1)

從時間復雜度(性能)上來說,一般選擇快速排序,是一種排序比較快的排序方法

從穩定性來說,一般選擇的是歸并排序

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/255868.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/255868.shtml
英文地址,請注明出處:http://en.pswp.cn/news/255868.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

BZOJ2844 albus就是要第一個出場

AC通道&#xff1a;http://www.lydsy.com/JudgeOnline/problem.php?id2844 這題貌似HDU上有一道差不多的題&#xff0c;不過我沒做過&#xff0c;也就沒管了。 首先講一個線性基的東西&#xff0c;大概就是這樣&#xff1a; 然后就是一個什么性質&#xff1a;S異或起來會出現重…

HTG Explains: Why Linux Doesn’t Need Defragmenting

If you’re a Linux user, you’ve probably heard that you don’t need to defragment your Linux file systems. You’ll also notice that Linux distributions don’t come with disk-defragmenting utilities. But why is that? To understand why Linux file systems d…

Spring AOP 實戰運用

Spring AOP 實戰 看了上面這么多的理論知識, 不知道大家有沒有覺得枯燥哈. 不過不要急, 俗話說理論是實踐的基礎, 對 Spring AOP 有了基本的理論認識后, 我們來看一下下面幾個具體的例子吧.下面的幾個例子是我在工作中所遇見的比較常用的 Spring AOP 的使用場景, 我精簡了很多有…

VC Ws2_32.lib

該庫對應WS2_32.DLL&#xff0c;提供了對以下網絡相關API的支持&#xff0c;若使用其中的API&#xff0c;則應該將ws2_32.lib加入工程&#xff08;否則要動態載入WS2_32.DLL&#xff09;。acceptbindcloseSOCKETconnectgetpeernamegetsocknamegetsockopthtonlhtonsioctlsocketi…

大話設計模式之策略模式

第二章&#xff1a;商場促銷——策略模式 策略模式的定義:策略模式是一種定義一系列算法的方法&#xff0c;從概念上來看&#xff0c;所有這些算法完成的都是相同的工作&#xff0c;知識實現不同&#xff0c;他可以以相同的方式調用所有的算法&#xff0c;減少了各類算法類與使…

【Python學習】——語言風格(變量賦值、深淺拷貝、for循環陷阱)

目錄 1、賦值 2、賦值的分類——引用賦值、值賦值 1) 不可變對象引用賦值——字符串、數值、元組等 2&#xff09;可變對象引用賦值——列表、集合、字典 3&#xff09;可變與不可變對象的引用賦值內部分析 4&#xff09;在py文件中&#xff0c;和作用域有關&#xff0c;如…

underscore.js 頁面數據渲染

1.underscore.js 源碼 // Underscore.js 1.8.3 // http://underscorejs.org // (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors // Underscore may be freely distributed under the MIT license.(function() {// …

判斷莊家是否出貨

1. 大盤處于強勢的時候 日平均線在橫盤的時候&#xff0c;緩慢拉升然后急劇下跌 高位盤整的時候 2. 有利好消息發布的時候 因為莊家會利用這個對于散戶來說這個買入時機來進行出貨操作&#xff0c;可見莊家真是陰險狡詐轉載于:https://www.cnblogs.com/dcz1001/p/6115893.html

【深度學習】——常見深度學習模型總結、anchor-free和anchor-based

目錄 1、faster rcnn&#xff1a; 2、SSD&#xff1a; 3、YOLOv1: 小結&#xff1a; 拓展&#xff1a;anchor-based和anchor-free anchor 1、faster rcnn&#xff1a; FasterRcnn 算法原理講解筆記&#xff08;非常詳細&#xff09;https://blog.csdn.net/xjtdw/article…

PHP PDO函數庫詳解

PDO是一個“數據庫訪問抽象層”&#xff0c;作用是統一各種數據庫的訪問接口&#xff0c;與mysql和mysqli的函數庫相比&#xff0c;PDO讓跨數據庫的使用更具有親和力&#xff1b;與ADODB和MDB2相比&#xff0c;PDO更高效。目前而言&#xff0c;實現“數據庫抽象層”任重而道遠&…

數據交互相關分享

Python與web Python Web.py與AJAX交互轉載于:https://juejin.im/post/5a40af3d6fb9a044ff31b1f5

springMVC 相對于 Structs 的優勢

智者說&#xff0c;沒有經過自己的思考和估量&#xff0c;就不能接受別人的東西。資料只能是一個參考&#xff0c;至于是否正確&#xff0c;還得自己去分辨 SpringMVC相對于Structs的幾個優勢&#xff1a; 1、springMVC安全性更高&#xff0c;structs2框架是類級別的攔截&#…

YOLOV1學習

YOLOV1學習&#xff08;輸入的圖像固定大小為448X448X3&#xff09; 參考文獻 模型結構 將輸入的圖像歸一化為大小為448x448x3的圖像&#xff0c;然后將經過中間24層的卷積后得到了7x7x1024的特征圖&#xff0c;然后后面連接的是兩個全連接層&#xff0c;分別是4096和1470&am…

KUKA通信 CREAD問題

嗨。 我想通過串行端口1發送X&#xff0c;Y&#xff0c;Z&#xff0c;A&#xff0c;B&#xff0c;C坐標給機器人。 G1: ...... CREAD(HANDLE,SR_T,MR_T,TIMEOUT,OFFSET,"%F",X) P.XX CREAD(HANDLE,SR_T,MR_T,TIMEOUT,OFFSET,"%F",Y) P.YY ...... GOTO G1…

bzoj 1901: Zju2112 Dynamic Rankings

Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 6245 Solved: 2593[Submit][Status][Discuss]Description 給定一個含有n個數的序列a[1],a[2],a[3]……a[n]&#xff0c;程序必須回答這樣的詢問&#xff1a;對于給定的i,j,k&#xff0c;在a[i],a[i1],a[i2]……a[j]中第k小的…

第 36 章 RRDTool

36.1. install $ apt-get install rrdtool原文出處&#xff1a;Netkiller 系列 手札 本文作者&#xff1a;陳景峯 轉載請與作者聯系&#xff0c;同時請務必標明文章原始出處和作者信息及本聲明。

手機號碼已經注冊寫到數據庫中,如何利用相同手機號碼再次注冊?

手機號碼已經注冊寫到數據庫中&#xff0c;如何利用相同手機號碼再次注冊&#xff1f; 解&#xff1a;刪除數據庫中以前注冊的手機號碼就可以了啊&#xff0c;delete那條記錄&#xff0c;轉載于:https://www.cnblogs.com/panxuejun/p/6122499.html

騰訊技術研究類和數據分析第一次筆試(2021.8.22)——Python

第一題&#xff1a;開鎖——數學期望 # 最優策略&#xff1a;鑰匙的選擇先從消耗時間最少的開始選擇&#xff0c;然后選擇第二小的依次類推 # 開鎖概率1/n def openLockTime(n, m, time):time_reverse [] # (n,m)->(m,n)for i in range(m):m_time []for j in range(n):m…

教你怎樣選擇伺服電機控制方式

伺服電機一般都有三種控制方式&#xff1a;速度控制方式&#xff0c;轉矩控制方式&#xff0c;位置控制方式 。 速度控制和轉矩控制都是用模擬量來控制的。位置控制是通過發脈沖來控制的。具體采用什么控制方式要根據客戶的要求&#xff0c;滿足何種運動功能來選擇。 …

.Net Discovery系列之四 深入理解.Net垃圾收集機制(下)

上一節給大家介紹了 .Net GC的運行機制&#xff0c;下面來講下與GC相關的重要方法。 第二節&#xff0e;GC關鍵方法解析 1.Dispose()方法 Dispose可用于釋放所有資源&#xff0c;包括托管的和非托管的&#xff0c;需要自己實現。 大多數的非托管資源都要求手動釋放&#xff0c;…