Rust 代碼在編寫過程當中與其它語言的略有不一樣,由於它的編譯器不容許有任何不安全的寫法,遂代碼編寫過程當中花費時間最長的莫過於查找編譯報錯的緣由。這樣也有好處——代碼寫好以後,穩定性高得一筆!git
如下是來自菜鳥教程中的排序定義和動圖示意:github
插入排序(英語:Insertion Sort)是一種簡單直觀的排序算法。它的工做原理是經過構建有序序列,對於未排序數據,在已排序序列中從後向前掃描,找到相應位置並插入。
咱們來捋一捋,插入排序的主要邏輯爲:算法
如今有一組須要排序的元素:安全
[7, 21, 9, 13, 109, 9, 2, 50, 33, -1, 20, 11]
按照插入排序的邏輯外循環指定第一個數 7,選定後 for 循環將從下標爲 1 的元素開始循環。代碼表現爲:async
for i in 1..vectors.len(){}
下標爲 0 的第一個數 7 是排序好的,那麼 for 循環從下標爲 1 的第二個數 21 開始。在內循環中將這個外循環指定數與左側數 [7] 逐個比較,當外循環指定數小於左邊元素時交換位置,不然不動。spa
此時進入下一輪外循環,指定下標爲 2 的第三個數 9。在內循環中將這個外循環指定數與左側數 [7, 21] 逐個比較,當外循環指定數小於左邊元素 21 時交換位置,遇到 7 不動。遂元素組變爲 :code
[7, 9, 21, 13, 109, 9, 2, 50, 33, -1, 20, 11]blog
此時進入下一輪外循環,指定下標爲 3 的第四個數 13。在內循環中將這個外循環指定數與左側數 [7, 9, 21] 逐個比較,當外循環指定數小於左邊元素 21 時交換位置,遇到 9 不動。遂元素組變爲 :排序
[7, 9, 13, 21, 109, 9, 2, 50, 33, -1, 20, 11]教程
依此類推 ...
此時進入第 N 輪外循環,指定下標爲 5 的第六個數 9。在內循環中將這個外循環指定數與左側數 [7, 9, 13, 21, 109] 逐個比較:
遇到 9 不動。遂元素組變爲 :
[7, 9, 9, 13, 21, 109, 2, 50, 33, -1, 20, 11]
此時進入第 N 輪外循環,指定下標爲 6 的第七個數 2。在內循環中將這個外循環指定數與左側數 [7, 9, 9, 13, 21, 109] 逐個比較:
遍歷至元素組左側盡頭,此時 j 不大於等於 0,內循環結束。遂元素組變爲 :
[2, 7, 9, 9, 13, 21, 109, 50, 33, -1, 20, 11]
在此以前,2 的左側有不少元素,它須要與這些元素逐個比較並交換位置。數字 2 的位置變化過程以下:
[7, 9, 9, 13, 21, 2, 109, 50, 33, -1, 20, 11] [7, 9, 9, 13, 2, 21, 109, 50, 33, -1, 20, 11] [7, 9, 9, 2, 13, 21, 109, 50, 33, -1, 20, 11] [7, 9, 2, 9, 13, 21, 109, 50, 33, -1, 20, 11] [7, 2, 9, 9, 13, 21, 109, 50, 33, -1, 20, 11] [2, 7, 9, 9, 13, 21, 109, 50, 33, -1, 20, 11]
從過程當中可看到,內循環的每一輪,數字 2 都會往左移動,直到前面沒有比 2 大的數字。
以此規則類推,元素排序的最終結果爲:
[-1, 2, 7, 9, 9, 11, 13, 20, 21, 33, 50, 109]
首先定義一組元素,並打印:
fn main() { let mut vectors = vec![7, 21, 9, 13, 109, 9, 2, 50, 33, -1, 20, 11]; println!("vectors: {:?}", vectors); }
而後定義排序方法:
fn insert_sort(vectors: &mut Vec<i32>) -> &Vec<i32>{ vectors }
排序方法的外循環是 for 循環:
fn insert_sort(vectors: &mut Vec<i32>) -> &Vec<i32>{ for i in 1..vectors.len(){ } vectors }
這裏將外層元素賦值給可變變量 current,同時設定內循環左側元素的下標:
fn insert_sort(vectors: &mut Vec<i32>) -> &Vec<i32>{ for i in 1..vectors.len(){ let mut current = vectors[i]; let mut j = i - 1; } vectors }
在內循環中的將這個外循環指定數與左側數逐個比較,當外循環指定數小於左側元素時交換位置,不然不動。
與左側元素比較用 j = i - 1, vectors[j] 表示;
不停地與左側元素比較用 while j >= 0, j = j -1 表示;
比較用 current < vectors[j] 表示;
交換位置沒法像 Python 那樣 a, b = b, a,只能用 c = a, a = b, b = c 這種加入第三個數的方式倒騰。遂代碼以下
fn insert_sort(vectors: &mut Vec<i32>) -> &Vec<i32>{ for i in 1..vectors.len(){ let mut current = vectors[i]; let mut j = i - 1; while j >= 0 && current < vectors[j]{ let middle = vectors[j+1]; vectors[j+1] = vectors[j]; vectors[j] = middle; j = j - 1; } } vectors }
不過這樣寫的話,外循環指定數爲比左側全部數都小的狀況下會沒法經過編譯的。例如外循環指定數爲 2 時須要與左側全部數進行比較,直到 j = 0,但 while 中最後一句是 j = j - 1,運行到這裏後 j = -1。按照正常運行流程,程序會進入到下一輪 while j >= 0 的內循環,但因爲 j = -1,就不會進入 while 循環體。Python 語言這樣寫是沒問題的,但 Rust 的編譯器不容許,遂須要在 j = j - 1 外層增長控制語句 if j = 0。
上面的理論看似有理有據使人信服,但究竟對不對呢?
有沒有可能分析錯誤呢?
雖然程序是對的,但萬一描述出來的邏輯有誤呢?
咱們能夠經過打印程序執行過程當中的外循環指定數 current、內循環左側第一個數和每次交換位置後元素組 vectors 來觀察循環比較時元素位置的變化狀況。添加了打印語句的代碼以下:
fn insert_sort(vectors: &mut Vec<i32>) -> &Vec<i32>{ for i in 1..vectors.len(){ let mut current = vectors[i]; let mut j = i - 1; println!("current vectors: {:?}", vectors); println!("current: {} < vectors[j]: {}", current, vectors[j]); while j >= 0 && current < vectors[j]{ let middle = vectors[j+1]; vectors[j+1] = vectors[j]; vectors[j] = middle; if j > 0{ /* rust 不容許while j >=0 中 j = 0 時還減 1 致使 j 在 while 中爲負數這種危險寫法*/ j = j - 1; // j 遞減即不斷地跟左邊比較 } println!("after vectors: {:?}", vectors); } } vectors }
代碼運行後的打印結果如爲:
vectors: [7, 21, 9, 13, 109, 9, 2, 50, 33, -1, 20, 11] current vectors: [7, 21, 9, 13, 109, 9, 2, 50, 33, -1, 20, 11] current: 21 < vectors[j]: 7 current vectors: [7, 21, 9, 13, 109, 9, 2, 50, 33, -1, 20, 11] current: 9 < vectors[j]: 21 after vectors: [7, 9, 21, 13, 109, 9, 2, 50, 33, -1, 20, 11] current vectors: [7, 9, 21, 13, 109, 9, 2, 50, 33, -1, 20, 11] current: 13 < vectors[j]: 21 after vectors: [7, 9, 13, 21, 109, 9, 2, 50, 33, -1, 20, 11] current vectors: [7, 9, 13, 21, 109, 9, 2, 50, 33, -1, 20, 11] current: 109 < vectors[j]: 21 current vectors: [7, 9, 13, 21, 109, 9, 2, 50, 33, -1, 20, 11] current: 9 < vectors[j]: 109 after vectors: [7, 9, 13, 21, 9, 109, 2, 50, 33, -1, 20, 11] after vectors: [7, 9, 13, 9, 21, 109, 2, 50, 33, -1, 20, 11] after vectors: [7, 9, 9, 13, 21, 109, 2, 50, 33, -1, 20, 11] current vectors: [7, 9, 9, 13, 21, 109, 2, 50, 33, -1, 20, 11] current: 2 < vectors[j]: 109 after vectors: [7, 9, 9, 13, 21, 2, 109, 50, 33, -1, 20, 11] after vectors: [7, 9, 9, 13, 2, 21, 109, 50, 33, -1, 20, 11] after vectors: [7, 9, 9, 2, 13, 21, 109, 50, 33, -1, 20, 11] after vectors: [7, 9, 2, 9, 13, 21, 109, 50, 33, -1, 20, 11] after vectors: [7, 2, 9, 9, 13, 21, 109, 50, 33, -1, 20, 11] after vectors: [2, 7, 9, 9, 13, 21, 109, 50, 33, -1, 20, 11] current vectors: [2, 7, 9, 9, 13, 21, 109, 50, 33, -1, 20, 11] current: 50 < vectors[j]: 109 after vectors: [2, 7, 9, 9, 13, 21, 50, 109, 33, -1, 20, 11] current vectors: [2, 7, 9, 9, 13, 21, 50, 109, 33, -1, 20, 11] current: 33 < vectors[j]: 109 after vectors: [2, 7, 9, 9, 13, 21, 50, 33, 109, -1, 20, 11] after vectors: [2, 7, 9, 9, 13, 21, 33, 50, 109, -1, 20, 11] current vectors: [2, 7, 9, 9, 13, 21, 33, 50, 109, -1, 20, 11] current: -1 < vectors[j]: 109 after vectors: [2, 7, 9, 9, 13, 21, 33, 50, -1, 109, 20, 11] after vectors: [2, 7, 9, 9, 13, 21, 33, -1, 50, 109, 20, 11] after vectors: [2, 7, 9, 9, 13, 21, -1, 33, 50, 109, 20, 11] after vectors: [2, 7, 9, 9, 13, -1, 21, 33, 50, 109, 20, 11] after vectors: [2, 7, 9, 9, -1, 13, 21, 33, 50, 109, 20, 11] after vectors: [2, 7, 9, -1, 9, 13, 21, 33, 50, 109, 20, 11] after vectors: [2, 7, -1, 9, 9, 13, 21, 33, 50, 109, 20, 11] after vectors: [2, -1, 7, 9, 9, 13, 21, 33, 50, 109, 20, 11] after vectors: [-1, 2, 7, 9, 9, 13, 21, 33, 50, 109, 20, 11] current vectors: [-1, 2, 7, 9, 9, 13, 21, 33, 50, 109, 20, 11] current: 20 < vectors[j]: 109 after vectors: [-1, 2, 7, 9, 9, 13, 21, 33, 50, 20, 109, 11] after vectors: [-1, 2, 7, 9, 9, 13, 21, 33, 20, 50, 109, 11] after vectors: [-1, 2, 7, 9, 9, 13, 21, 20, 33, 50, 109, 11] after vectors: [-1, 2, 7, 9, 9, 13, 20, 21, 33, 50, 109, 11] current vectors: [-1, 2, 7, 9, 9, 13, 20, 21, 33, 50, 109, 11] current: 11 < vectors[j]: 109 after vectors: [-1, 2, 7, 9, 9, 13, 20, 21, 33, 50, 11, 109] after vectors: [-1, 2, 7, 9, 9, 13, 20, 21, 33, 11, 50, 109] after vectors: [-1, 2, 7, 9, 9, 13, 20, 21, 11, 33, 50, 109] after vectors: [-1, 2, 7, 9, 9, 13, 20, 11, 21, 33, 50, 109] after vectors: [-1, 2, 7, 9, 9, 13, 11, 20, 21, 33, 50, 109] after vectors: [-1, 2, 7, 9, 9, 11, 13, 20, 21, 33, 50, 109] results: [-1, 2, 7, 9, 9, 11, 13, 20, 21, 33, 50, 109]
因而可知,理論部分的描述是正確的
完整的 Rust 插入排序代碼以下:
Rust 算法代碼倉庫地址 https://github.com/asyncins/a...