1. 程式人生 > 其它 >快速修改陣列的某個值_我用Python,3分鐘快速實現,9種經典排序演算法的視覺化...

快速修改陣列的某個值_我用Python,3分鐘快速實現,9種經典排序演算法的視覺化...

技術標籤:快速修改陣列的某個值

a63c21aecb918395a5e58a41fb80f356.png

最近在某網站上看到一個視訊,是關於排序演算法的視覺化的,看著挺有意思的,也特別喜感。

6分鐘演示15種排序演算法

https://v.qq.com/x/page/t0396emm8oy.html

不知道作者是怎麼做的,但是突然很想自己實現一遍,而且用python實現特別快,花了一天的時間,完成了這個專案。主要包括希爾排序(Shell Sort)、選擇排序(Selection Sort)、快速排序(Quick Sort)、歸併排序(Merge Sort)等九種排序。

附上原始碼連結:

https://github.com/ZQPei/Sorting_Visualization

下面具體講解以下實現的思路,大概需要解決的問題如下:

  • 如何表示陣列
  • 如何得到隨機取樣陣列,陣列有無重複資料
  • 如何實現排序演算法
  • 如何把陣列可視化出來

一、如何表示陣列

python提供了list型別,很方便可以表示C++中的陣列。標準安裝的Python中用列表(list)儲存一組值,可以用來當作陣列使用,不過由於列表的元素可以是任何物件,因此列表中所儲存的是物件的指標。這樣為了儲存一個簡單的[1,2,3],需要有3個指標和三個整數物件。對於數值運算來說這種結構顯然比較浪費記憶體和CPU計算時間,再次就不詳細論述。

二、如何得到隨機取樣陣列,陣列有無重複資料

假設我希望陣列長度是100,而且我希望陣列的大小也是在[0,100)內,那麼如何得到100個隨機的整數呢?可以用random庫。

示例程式碼:

import randomdata = list(range(100))data = random.choices(data, k=100)print(data)[52, 33, 45, 33, 48, 25, 68, 28, 78, 23, 78, 35, 24, 44, 69, 88, 66, 29, 82, 77, 84, 12, 19, 10, 27, 24, 57, 42, 71, 75, 25, 1, 77, 94, 44, 81, 86, 62, 25, 69, 97, 86, 56, 47, 31, 51, 40, 21, 41, 21, 17, 56, 88, 41, 92, 46, 56, 80, 23, 70, 49, 96, 83, 54, 16, 36, 82, 24, 68, 60, 16, 98, 16, 81, 10, 13, 11, 24, 68, 35, 56, 39, 23, 44, 6, 30, 3, 60, 56, 66, 38, 28, 47, 47, 25, 90, 89, 38, 68, 21]

但是以上程式碼有個問題,random.choices是對一個序列進行重複取樣,得到的陣列存在重複資料,那如果不希望存在重複資料,而是希望進行無重複取樣,怎麼辦?

可以用random.sample函式,示例程式碼:

data = random.sample(data, k=100)print(data)[49, 28, 56, 28, 44, 62, 81, 25, 48, 33, 54, 38, 30, 16, 13, 19, 23, 56, 60, 66, 41, 24, 68, 68, 77, 92, 78, 24, 66, 3, 80, 94, 78, 41, 84, 88, 21, 56, 25, 25, 75, 24, 38, 82, 31, 52, 23, 10, 71, 40, 27, 46, 33, 35, 56, 51, 1, 23, 12, 25, 89, 16, 21, 21, 11, 42, 47, 44, 81, 35, 86, 88, 29, 36, 77, 16, 39, 6, 57, 69, 96, 68, 24, 86, 97, 90, 69, 10, 68, 98, 56, 44, 83, 47, 70, 17, 47, 82, 60, 45]

這樣就可以得到無重複取樣資料了。

三、如何實現排序演算法

演算法種類較多,就不一一舉例;再次就以希爾排序(Shell Sort)為例講講:

爾排序的原理:希爾排序(Shell Sort)是插入排序的一種。也稱縮小增量排序,是直接插入排序演算法的一種更高效的改進版本。

希爾排序是把記錄按下標的一定增量分組,對每組使用直接插入排序演算法排序;隨著增量逐漸減少,每組包含的關鍵詞越來越多,當增量減至1時,整個檔案恰被分成一組,演算法便終止。

基礎的插入法排序是兩重迴圈,希爾排序是三重迴圈,最外面一重迴圈,控制增量gap,並逐步減少gap的值。二重迴圈從下標為gap的元素開始比較,依次逐個跨組處理。最後一重迴圈是對組內的元素進行插入法排序。這樣進行排序的優點在於每次迴圈,整個序列的元素都將小元素的值逐步向前移動,數值比較大的值向後移動。

示例程式碼:

from data import DataSeqdef ShellSort(ds): assert isinstance(ds, DataSeq), "Type Error" Length = ds.length D = Length//2 while D>0: i=0 while i=1 and ds.data[j-D]>tmp: ds.SetVal(j, ds.data[j-D]) j-=D ds.SetVal(j, tmp) i+=D D//=2if __name__ == "__main__": ds=DataSeq(64) ds.Visualize() ds.StartTimer() ShellSort(ds) ds.StopTimer() ds.SetTimeInterval(0) ds.Visualize()

四、如何把陣列可視化出來

有了隨機陣列初始化方法,再實現好排序函式,我們還差一步,就是把排序函式中每次移動陣列後將陣列視覺化並輸出。

對陣列進行視覺化,很容易想到python的視覺化工具matplotlib!但是在專案中我並沒有用matplotlib,而是用了numpy+opencv。

為什麼不用matplotlib?

因為在排序過程中,每次修改陣列,都希望能夠實時修改圖片並輸出,matplotlib確實很方便,但是matplotlib的效率實在是不高,而且每次修改陣列前後的兩幅圖片其實是差不多的。如果用matplotlib,每次都是要重新繪製圖片,非常耗時!!!

所以考慮自己生成圖片,在每次修改陣列後,只將圖片中改動的那兩列進行修改即可!這樣就比用matplotlib每次重新繪製圖片效率高得多!

陣列中主要有兩種操作,一種是對某個idx賦值,一種是交換某兩個idx的值。

示例程式碼:

class DataSeq: WHITE = (255,255,255) RED = (0,0,255) BLACK = (0,0,0) YELLOW = (0,127,255) def __init__(self, Length, time_interval=1, sort_title="Figure