动态可视化十大排序算法之冒泡排序
點(diǎn)擊上方藍(lán)字關(guān)注我們
提到排序算法呀,我想你肯定不陌生。這應(yīng)該是學(xué)習(xí)編程時(shí)學(xué)到的第一個(gè)算法了吧。
我現(xiàn)在還能記得自己當(dāng)時(shí)在 VC++ 6.0 上按照譚浩強(qiáng)老師的 C 語言教材敲出第一個(gè)冒泡排序時(shí)的激動(dòng)心情。滿滿的成就感,不得不說,編程愛好者的快樂就是如此簡單。
雖然排序在我們?nèi)粘I钪泻艹R姟⒊S谩5菍?duì)于那時(shí)的自己來說還是很難理解的。而且自己也是在對(duì)比著書修改了很多遍才正確的編譯運(yùn)行。
當(dāng)時(shí)我就想著要是有一個(gè)算法執(zhí)行過程的動(dòng)態(tài)圖那就好了。我一直也在這樣嘗試著這樣做,今天我就帶你來體驗(yàn)下冒泡排序算法的動(dòng)態(tài)執(zhí)行過程。
話不多說,直接上干貨,先帶你看下效果,包你滿意。
不僅是簡單的算法執(zhí)行過程,我還會(huì)為你介紹一些改進(jìn)的技巧,讓你更加游刃有余,顯示出自己的內(nèi)功修養(yǎng)。
有必要手動(dòng)寫排序算法嗎?
可能有人覺得現(xiàn)在不需要自己手動(dòng)寫排序算法了,用的時(shí)候直接調(diào)用編程語言內(nèi)置的庫函數(shù)就行了。
在日常的工作學(xué)習(xí)中,我覺得大部分人也就是這樣做的,包括我自己在內(nèi)。而且你自己寫排序算法有 Bug 不說,就算沒有 Bug,肯定也沒有編程語言內(nèi)置的庫函數(shù)高效。
但是這并不能說我們不需要掌握排序算法了,我覺得主要原因有兩個(gè)吧。
掌握排序算法可以幫助我們更好的理解計(jì)算機(jī)程序的執(zhí)行過程,訓(xùn)練我們的編程邏輯。而且排序算法有很多變形,這些變形在特定的應(yīng)用場景下會(huì)非常高效。
另外一個(gè)我覺得就是應(yīng)對(duì)職場的面試了。數(shù)據(jù)結(jié)構(gòu)和算法直接對(duì)應(yīng)了你能不能通過筆試,進(jìn)入面試。我之前做過一個(gè)互聯(lián)網(wǎng)大廠的筆試,筆試就是 4 道編程題,時(shí)間一個(gè)半小時(shí)。我當(dāng)時(shí)一道題都沒 AC,心態(tài)直接爆炸,結(jié)果也就涼涼了。。。
冒泡排序
接下來,我們就來看一看冒泡排序算法,前面的動(dòng)畫不知道你看懂了嗎?沒看懂的話可以再看一遍。
但是看懂就代表你可以寫出完整的代碼來嗎?答案并不一定哦。
話不多說,先看下代碼:
#!/usr/bin/python #?-*-?coding:UTF-8?-*- from?typing?import?List#?Bubble?Sort def?bubble_sort(array:?List[int])?->?None:for?i?in?range(len(array)?-?1):flag?=?False#?如果前面的比后面的元素大,就交換for?j?in?range(len(array)?-?1?-?i):if?array[j]?>?array[j?+?1]:array[j],?array[j?+?1]?=?array[j?+?1],?array[j]flag?=?True#?如果一輪完成,沒有一個(gè)元素進(jìn)行交換,則表明元素有序,退出循環(huán)if?not?flag:breakarray?=?[3,?44,?38,?5,?47,?15] print(array) bubble_sort(array) print(array)??冒泡排序的思想就是比較相鄰之間的元素,如果?array[j] < array[j + 1],則就會(huì)互換相鄰之間的元素。這樣每輪迭代完后,總有一個(gè)元素可以到達(dá)此元素應(yīng)該到達(dá)的位置。
每次到位的元素也就是第 K 大元素,舉例說,第一次到位的是第一大元素,也就是最大值。第二次到位的是第二大元素,也就是次大值。
如何評(píng)價(jià)一個(gè)排序算法?
通過上面的程序,我們就實(shí)現(xiàn)了冒泡排序算法,那么如何評(píng)價(jià)一個(gè)排序算法呢?我想這個(gè)你在學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法的時(shí)候一定都學(xué)過。
主要有以下指標(biāo):
時(shí)間復(fù)雜度
空間復(fù)雜度
穩(wěn)定性
這里我就不再一一敘述了,冒泡排序算法的時(shí)間復(fù)雜度是 O(n2),空間復(fù)雜度是 O(1),是穩(wěn)定的排序算法。
優(yōu)化
時(shí)間復(fù)雜度是 O(n2) 的排序算法是比較耗時(shí)的,適用于小規(guī)模的數(shù)據(jù),不適用于大規(guī)模的數(shù)據(jù)排序,那有沒有優(yōu)化的方法呢?
要想從時(shí)間復(fù)雜度的量級(jí)上優(yōu)化,這個(gè)就只能換排序算法了。但是呢?有一些其他的技巧,可以減少算法的運(yùn)行時(shí)間。是什么呢?
就是在第奇數(shù)次迭代的時(shí)候,從前往后比較,而偶數(shù)次迭代的時(shí)候,從后往前比較。這樣雖然理論上還是 O(n2) 的時(shí)間復(fù)雜度,但是運(yùn)行時(shí)間會(huì)降低不少。
#!/usr/bin/python # -*- coding: UTF-8 -*- import random import time# Bubble Sort def bubble_sort(array):for i in range(len(array) - 1):flag = Falsefor j in range(len(array) - 1 - i):if array[j] > array[j + 1]:array[j], array[j + 1] = array[j + 1], array[j]flag = Trueif not flag:breakdef optim_bubble_sort(array):for i in range(len(array) - 1):flag = Falseif i % 2:for j in range(len(array) - 1 - (i // 2), (i // 2), -1):if array[j] < array[j - 1]:array[j], array[j - 1] = array[j - 1], array[j]flag = Trueelse:for j in range((i // 2), len(array) - 1 - (i // 2)):if array[j] > array[j + 1]:array[j], array[j + 1] = array[j + 1], array[j]flag = Trueif not flag:breakif __name__ == "__main__":num = 10000array = [random.randint(0,num) for _ in range (num)]array_copy = array[:]#print(array)start = time.perf_counter()bubble_sort(array)end = time.perf_counter()#print(array)print(end - start)start = time.perf_counter()optim_bubble_sort(array_copy)end = time.perf_counter()#print(array_copy)print(end - start)從運(yùn)行結(jié)果上看,運(yùn)行時(shí)間還是有提高的。這是 num 設(shè)置為 10000 的時(shí)候。提前給你打個(gè)預(yù)防針,如果你?num?設(shè)置的過大,比如 100000,很有可能排序需要等20分鐘。。。
總結(jié)
冒泡排序是一種時(shí)間復(fù)雜度較高的排序算法,所以呢大部分時(shí)候都是在教科書中出現(xiàn),在實(shí)際的項(xiàng)目或者使用過程中很少有它的身影。
但是這種思想對(duì)于剛接觸編程的人來說,還是比較容易理解的,如果上來就讓你理解遞歸,理解快排,我覺得還是比較難的。有了前面的基礎(chǔ),在學(xué)習(xí)后面算法的過程中也會(huì)容易很多。
這個(gè)我覺得大多數(shù)人應(yīng)該都能理解,但理解不代表掌握了。就像我在手寫這些代碼的時(shí)候還要調(diào)試一會(huì)呢,相信你也可以看到我代碼字里行間的調(diào)試信息,所以建議你花點(diǎn)時(shí)間自己練習(xí)下。
下篇文章我們一起學(xué)習(xí)選擇排序算法。
一個(gè)人可以走的更快,一群人可以走得更遠(yuǎn)
長按掃碼關(guān)注我們
總結(jié)
以上是生活随笔為你收集整理的动态可视化十大排序算法之冒泡排序的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux学习笔记 -- 系统编程
- 下一篇: 文本关键词的提取算法实验