javascript中的基本排序演算法
對計算機中儲存的資料執行的兩種最常見操作是排序和檢索,排序和檢索演算法對於前端開發尤其重要,對此我會對這兩種演算法做深入的研究,而不會和書上一樣只是會貼程式碼而已,下面我會一步步從自己的理解的思路來一步步學習各個排序的思想。不過這些演算法依賴於javascript中的陣列來儲存資料。最後我會來測試下基本演算法(氣泡排序,選擇排序,插入排序)的那個效率更高!
下面啊,我們先可以來封裝常規陣列操作的函式,比如:插入新資料,顯示陣列資料,還有交換陣列元素等操作來呼叫不同的排序演算法。
我們先來封裝一個類 CArray,程式碼如下:
function CArray(numElements) { this.dataStore = []; this.pos = 0; this.numElements = numElements; this.insert = insert; this.toString = toString; this.clear = clear; this.swap = swap; for(var i = 0; i < numElements.length; i++) { this.dataStore[i] = numElements[i]; } }
其中this.dataStore 是一個陣列來儲存陣列中的所有元素,this.pos是一個索引值,預設為0,從第一個開始,this.numElements是儲存所有的陣列元素,insert方法是向陣列中插入一個元素的方法;toString是顯示陣列中所有元素的方法;clear方法是清除陣列中所有的元素,swap方法是交換陣列中元素的位置的方法,此方法對排序很有用處,下面我們會用到他們。下面我們來封裝下各個方法如下:
function clear() { for(var i = 0; i < this.dataStore.length; i++) { this.dataStore[i] = 0; } } function insert(element) { this.dataStore[this.pos++] = element; } function toString() { var restr = ""; for(var i = 0; i < this.dataStore.length; i++) { restr += this.dataStore[i] + " "; if(i > 0 && i % 10 == 0) { restr+= "\n"; } } return restr; } function swap(arr,index1,index2) { var temp = arr[index1]; arr[index1] = arr[index2]; arr[index2] = temp; }
上面方法封裝先放在這裡,下面我們先來研究下排序演算法,稍後會使用到上面的方法。
一:氣泡排序:
氣泡排序在三種基本排序(氣泡排序,選擇排序,插入排序)中效率是最慢的一種排序演算法;它的實現原理是:陣列裡面的資料值會像氣泡一樣從陣列的一端漂浮到另一端。假設正在將一組數字按照升序排列,那麼較大的值會浮動到陣列的右側,而較小的值會浮動到陣列的左側。之所以會產生這種現象是因為演算法會多次在陣列中移動,比較相鄰的資料,當左側值大於右側值時會將他們進行交換。
下面我們先來看一下簡單的氣泡排序的demo如下:
E A D B H
經過第一次排序後,這個列表變成:
A E D B H
前2個元素進行了交換。接下來再次排序又會變成如下:
A D E B H
第二個和第三個元素進行了互換。繼續進行排序
A D B E H
第三個和第四個元素進行了互換,最後,第二個和第三個元素還會再次互換,得到最終順序為: A B D E H
下面我們可以來寫一個氣泡排序的函式 bubbleSort(),程式碼如下:
function bubbleSort() { var numElements = this.dataStore.length; var temp; for(var outer = numElements; outer >= 2; --outer) { for(var inner = 0; inner <= outer -1; ++inner) { if(this.dataStore[inner] > this.dataStore[inner + 1]) { swap(this.dataStore,inner,inner+1); } } } }
下面是所有的JS程式碼如下
function CArray(numElements) { this.dataStore = []; this.pos = 0; this.numElements = numElements; this.insert = insert; this.toString = toString; this.clear = clear; this.swap = swap; this.bubbleSort = bubbleSort; for(var i = 0; i < numElements.length; i++) { this.dataStore[i] = numElements[i]; } } function clear() { for(var i = 0; i < this.dataStore.length; i++) { this.dataStore[i] = 0; } } function insert(element) { this.dataStore[this.pos++] = element; } function toString() { var restr = ""; for(var i = 0; i < this.dataStore.length; i++) { restr += this.dataStore[i] + " "; if(i > 0 && i % 10 == 0) { restr+= "\n"; } } return restr; } function swap(arr,index1,index2) { var temp = arr[index1]; arr[index1] = arr[index2]; arr[index2] = temp; } function bubbleSort() { var numElements = this.dataStore.length; var temp; for(var outer = numElements; outer >= 2; --outer) { for(var inner = 0; inner <= outer -1; ++inner) { if(this.dataStore[inner] > this.dataStore[inner + 1]) { swap(this.dataStore,inner,inner+1); } } } }
// 氣泡排序測試程式碼
var numElements = [0,9,1,8,7,6,2,3,5,4];
var myNums = new CArray(numElements);
myNums.bubbleSort();
console.log(myNums.toString());
程式碼分析如下:
假設陣列為 [0,9,1,8,7,6,2,3,5,4];
1. outer為10的時候
1. inner為0,值為0,inner+1為1,值為9,不符合,不交換。
2. inner為1,值為9,inner+1為2 值為1,交換,陣列變為[0,1,9,8,7,6,2,3,5,4]
3. inner為2,值為9,inner+1為3,值為8,交換 陣列變為[0,1,8,9,7,6,2,3,5,4]
4. inner為3,值為9,inner+1 為4,值為7,交換,陣列變為[0,1,8,7,9,6,2,3,5,4]
5, inner為4,值為9,inner+1 為5,值為6,交換,陣列變為 [0,1,8,7,6,9,2,3,5,4]
6. inner為5,值為9,inner+1 為6,值為2,交換,陣列變為[0,1,8,7,6,2,9,3,5,4]
7. inner為6,值為9,inner+1 為7,值為3,交換,陣列變為[0,1,8,7,6,2,3,9,5,4]
8. inner為7,值為9,inner+1 為8,值為5,交換,陣列變為[0,1,8,7,6,2,3,5,9,4]
9. inner為8,值為9,inner+1為9,值為4,交換,陣列變為[0,1,8,7,6,2,3,5,4,9]
10. inner為9,值為9,inner+1 不符合,不交換。
2. outer為9的時候
1. inner為0,值為0,inner+1 不符合,不交換。
2. inner為1 值為1,inner+1值為8 不符合 不交換。
3. inner為2 值為8,inner+1值為7,交換,陣列變為 [0,1,7,8,6,2,3,5,4,9]
4. inner為3,值為8,inner+1值為6,交換,陣列變為[0,1,7,6,8,2,3,5,4,9]
5. inner為4 值為8 inner+1值為2 交換 陣列變為 [0,1,7,6,2,8,3,5,4,9]
6. inner為5 值為8,inner+1值為3,交換,陣列變為[0,1,7,6,2,3,8,5,4,9]
7. inner為6 值為8,inner+1值為5,交換 陣列變為[0,1,7,6,2,3,5,8,4,9]
8. inner為7 值為8,inner+1值為4,交換 陣列變為[0,1,7,6,2,3,5,4,8,9]
9. inner為8 值為8,inner+1值為9,不符合 不交換。
3. outer為8的時候
1. inner為0,值為0,inner+1 不符合,不交換。
2. inner為1 值為1,inner+1值為7 不符合 不交換。
3. inner為2 值為7,inner+1值為6,交換 陣列變為 [0,1,6,7,2,3,5,4,8,9]
4. inner為3 值為7,inner+1值為2,交換,陣列變為[0,1,6,2,7,3,5,4,8,9]
5. inner為4 值為7,inner+1值為3,交換,陣列變為[0,1,6,2,3,7,5,4,8,9]
6 inner為5 值為7 inner+1值為5,交換,陣列變為[0,1,6,2,3,5,7,4,8,9]
7. inner為6 值為7 inner+1 值為4,交換,陣列變為[0,1,6,2,3,5,4,7,8,9]
8. inner為7 值為7,inner+1值為8,不符合。
4. outer為7的時候
1. inner為0,值為0,inner+1 不符合,不交換。
2. inner為1 值為1,inner+1值為6 不符合 不交換。
3. inner為2 值為6,inner+1值為2,交換 陣列變為[0,1,2,6,3,5,4,7,8,9]
4. inner為3 值為6,inner+1值為3,交換,陣列變為[0,1,2,3,6,5,4,7,8,9]
5 inner為4 值為6 inner+1值為5,交換,陣列變為[0,1,2,3,5,6,4,7,8,9]
6 inner為5 值為6 inner+1值為4,交換 陣列變為[0,1,2,3,5,4,6,7,8,9]
7 inner為6 值為6,inner+1 值為7,不符合。
5. outer為6的時候
1. inner為0,值為0,inner+1 不符合,不交換。
2. inner為1 值為1,inner+1值為2 不符合 不交換。
3. inner為2 值為2,inner+1值為3 不符合 不交換。
4. inner為3 值為3,inner+1值為5,不符合 不交換。
5. inner為4 值為5,inner+1 值為4 交換,陣列變為[0,1,2,3,4,5,6,7,8,9]
再下面繼續迴圈都不符合條件,所以如上就是最後一步了。這就是氣泡排序。
二:選擇排序
原理:選擇排序從陣列的開頭開始,將第一個元素和其他元素進行比較。檢查完所有元素後,最小的元素會被放到陣列的第一個位置,然後演算法會從第二個位置繼續。這個過程一直進行,當進行到陣列的倒數第二個位置時,所有的資料便完成了排序。
選擇排序會用到巢狀迴圈。外迴圈從陣列的第一個元素移動到倒數第二個元素,內迴圈從第二個陣列元素移動到最後一個元素,查詢比當前外迴圈所指向的元素小的元素。每次內迴圈迭代後,陣列中最小的值都會被賦值到合適的位置。
以下是一個對只有五個元素的列表進行選擇排序的簡單列子,初始列表為:
E A D H B
第一次排序會找到最小值,並將它和列表的第一個元素進行互換。
A E D H B
接下來查詢第一個元素後面的最小值(第一個元素此時已經就位),並對他們進行互換。
A B D H E
D也已經就位,因此下一步會對E和H進行互換,列表已按順序排好;
A B D E H
下面我們就可以來編寫選擇排序演算法的selectionSort()方法了;如下程式碼:
function selectionSort() { var min,temp; for(var outer = 0; outer <= this.dataStore.length -2; ++outer) { min = outer; for(var inner = outer + 1; inner <= this.dataStore.length - 1; ++inner) { if(this.dataStore[inner] < this.dataStore[min]) { swap(this.dataStore,inner,min); } } } }
下面是所有的JS程式碼如下:
function CArray(numElements) { this.dataStore = []; this.pos = 0; this.numElements = numElements; this.insert = insert; this.toString = toString; this.clear = clear; this.swap = swap; this.selectionSort = selectionSort; for(var i = 0; i < numElements.length; i++) { this.dataStore[i] = numElements[i]; } } function clear() { for(var i = 0; i < this.dataStore.length; i++) { this.dataStore[i] = 0; } } function insert(element) { this.dataStore[this.pos++] = element; } function toString() { var restr = ""; for(var i = 0; i < this.dataStore.length; i++) { restr += this.dataStore[i] + " "; if(i > 0 && i % 10 == 0) { restr+= "\n"; } } return restr; } function swap(arr,index1,index2) { var temp = arr[index1]; arr[index1] = arr[index2]; arr[index2] = temp; } function selectionSort() { var min,temp; for(var outer = 0; outer <= this.dataStore.length -2; ++outer) { min = outer; for(var inner = outer + 1; inner <= this.dataStore.length - 1; ++inner) { if(this.dataStore[inner] < this.dataStore[min]) { swap(this.dataStore,inner,min); } } } }
// 選擇排序測試程式碼
var numElements = [9,0,1,8,7,6,2,3,5,4];
var myNums = new CArray(numElements);
myNums.selectionSort();
console.log("------");
console.log(myNums.toString());
程式碼分析如下:
假設陣列為:[9,0,1,8,7,6,2,3,5,4]
1. 當min為0的時候,值為9,inner為1,值為0,所以調換位置,陣列變為[0,9,1,8,7,6,2,3,5,4]
2. 當min為0的時候都不符合,所以當min為1的時候,值為9,inner為2,值為1,所以陣列變為[0,1,9,8,7,6,2,3,5,4]
3. 當min為1的時候,值為1,內部迴圈也不符合,所以現在當min為2的時候,值為9,inner為3的時候,值為8,所以調換位置,陣列變為
[0,1,8,9,7,6,2,3,5,4]
4. 當min為2的時候,值為8,inner為4的時候,值為7,所以調換位置,陣列為[0,1,7,9,8,6,2,3,5,4].
5. 當min為2的時候,值為7,inner為5的時候,值為6,所以調換位置,陣列為[0,1,6,9,8,7,2,3,5,4].
6. 當min為2的時候,值為6,inner為6的時候,值為2,所以調換位置 陣列為[0,1,2,9,8,7,6,3,5,4].
7. 當min為2的時候,值為2,不符合條件,所以當min為3的時候,值為9,所以inner為4,值為8,所以調換位置,陣列變為[0,1,2,8,9,7,6,3,5,4]
8. 當min為3的時候,值為8,inner為5的時候值為7,所以調換位置,陣列變為[0,1,2,7,9,8,6,3,5,4]
9. 當min為3的時候,值為7,inner為6的時候值為6,所以調換位置 陣列變為[0,1,2,6,9,8,7,3,5,4]
10 當min為3的時候,值為6,inner為7的時候值為3 所以調換位置 陣列變為[0,1,2,3,9,8,7,6,5,4]
11 當min為3的時候 值為3 不符合條件,所以當min為4的時候,值為9,inner為5的時候,值為8,所以調換位置,陣列變為
[0,1,2,3,8,9,7,6,5,4]
12 當min為4的時候,值為8,inner為6的時候,值為7,所以調換位置,陣列變為[0,1,2,3,7,9,8,6,5,4].
13 當min為4的時候,值為7,inner為7的時候,值為6,所以調換位置,陣列變為[0,1,2,3,6,9,8,7,5,4].
14 當min為4的時候,值為6,inner為8的時候,值為5,所以調換位置,陣列變為[0,1,2,3,5,9,8,7,6,4].
15 當min為4的時候,值為5,inner為9的時候,值為4,所以調換位置,陣列變為[0,1,2,3,4,9,8,7,6,5].
16 當min為5的時候,值為9,inner為6的時候,值為8,所以調換位置,陣列變為[0,1,2,3,4,8,9,7,6,5].
17 當min為5的時候,值為8,inner為7的時候,值為7,所以調換位置,陣列變為[0,1,2,3,4,7,9,8,6,5].
18 當min為5的時候,值為7,inner為8的時候,值為6,所以調換位置,陣列變為[0,1,2,3,4,6,9,8,7,5].
19 當min為5的時候,值為6,inner為9的時候,值為5,所以調換位置,陣列變為[0,1,2,3,4,5,9,8,7,6].
20 當min為6的時候,值為9,inner為7的時候,值為8,所以調換位置,陣列變為[0,1,2,3,4,5,8,9,7,6].
21 當min為6的時候,值為8,inner為8的時候,值為7,所以調換位置,陣列變為[0,1,2,3,4,5,7,9,8,6].
22 當min為6的時候,值為7,inner為9的時候,值為6,所以調換位置,陣列變為[0,1,2,3,4,5,6,9,8,7].
23.當min為7的時候,值為9,inner為8的時候,值為8,所以調換位置,陣列變為[0,1,2,3,4,5,6,8,9,7].
24 當min為7的時候,值為8,inner為9的時候,值為7,所以調換位置,陣列變為[0,1,2,3,4,5,6,7,9,8].
25 當min為8的時候,值為9,inner為9的時候 值為8,所以調換位置,陣列最終變為[0,1,2,3,4,,5,6,7,8,9]
三:插入排序
原理:插入排序類似於人類按數字或字母順序對資料進行排序。列如:讓班裡的每個學生上交一張寫有他的名字,學生證號以及個人簡介的索引卡片。學生交上來的卡片是沒有順序的,但是我想讓這些卡片按字母順序排好,這樣就可以很容易地與班級花名冊進行對照了。
我將卡片帶回辦公室,清理好書桌,然後拿起第一張卡片,卡片上的姓氏是Smith。我把它放到桌子的左上角,然後再拿起第二張卡片。這張卡片上的姓氏是Brown。我把Smith移右,把Brown放到Smith的前面。下一張卡片是Williams,可以把它放到桌面的最右邊,而不用移動其他任何卡片,下一張卡片是Acklin。這張卡片必須放在這些卡片的最前面,因此其他所有卡片必須向右移動一個位置來為Acklin這張卡片來騰出位置。這就是插入排序的原理;
插入排序有2個迴圈。外迴圈將陣列元素挨個移動,而內迴圈則對外迴圈中選中的元素及它後面的那個元素進行比較。如果外迴圈中選中的元素比內迴圈選中的元素小,那麼陣列元素會向右移動,為內迴圈中的這個元素騰出位置。
插入排序的程式碼如下:
// 插入排序 function insertionSort() { var temp,inner; for(var outer=1; outer <= this.dataStore.length - 1; ++outer) { temp = this.dataStore[outer]; inner = outer; while(inner > 0 && (this.dataStore[inner-1] >= temp)) { this.dataStore[inner] = this.dataStore[inner -1]; --inner; } this.dataStore[inner] = temp; } }
下面是所有的JS程式碼如下:
function CArray(numElements) { this.dataStore = []; this.pos = 0; this.numElements = numElements; this.insert = insert; this.toString = toString; this.clear = clear; this.swap = swap; this.insertionSort = insertionSort; for(var i = 0; i < numElements.length; i++) { this.dataStore[i] = numElements[i]; } } function clear() { for(var i = 0; i < this.dataStore.length; i++) { this.dataStore[i] = 0; } } function insert(element) { this.dataStore[this.pos++] = element; } function toString() { var restr = ""; for(var i = 0; i < this.dataStore.length; i++) { restr += this.dataStore[i] + " "; if(i > 0 && i % 10 == 0) { restr+= "\n"; } } return restr; } function swap(arr,index1,index2) { var temp = arr[index1]; arr[index1] = arr[index2]; arr[index2] = temp; } // 插入排序 function insertionSort() { var temp,inner; for(var outer=1; outer <= this.dataStore.length - 1; ++outer) { temp = this.dataStore[outer]; inner = outer; while(inner > 0 && (this.dataStore[inner-1] >= temp)) { this.dataStore[inner] = this.dataStore[inner -1]; --inner; } this.dataStore[inner] = temp; } }
// 插入排序的測試程式碼
var numElements = [9,0,1,8,7,6,2,3,5,4];
var myNums = new CArray(numElements);
myNums.insertionSort();
console.log("------");
console.log(myNums.toString());
程式碼分析如下:
陣列為 [9,0,1,8,7,6,2,3,5,4];
1. outer為1的時候
temp值為0,inner等於1,this.dataStore[inner-1]值為9 >= 0 因此while條件為true,
this.dataStore[inner] = this.dataStore[inner -1];執行這句程式碼後,this.dataStore[1] = 9,inner自減1 inner為0
因此this.dataStore[0] = 0;因此陣列變為[0,9,1,8,7,6,2,3,5,4]
2. outer為2的時候
1. temp = this.dataStore[outer];temp值為1,inner等於2,this.dataStore[inner-1]值為9 >=1 因此while條件為true,
this.dataStore[inner] = this.dataStore[inner -1];執行這句程式碼後,this.dataStore[2] = 9,inner自減1 inner為1
因此this.dataStore[1] = 1;因此陣列變為[0,1,9,8,7,6,2,3,5,4]
2. inner為1,temp值為1,this.dataStore[inner-1]值為0 >= 1 因此while條件為false.不成立
3. outer為3的時候
1. temp = this.dataStore[outer];temp值為8,inner等於3,this.dataStore[inner-1]值為9 >=8 因此while條件為true,
this.dataStore[inner] = this.dataStore[inner -1];執行這句程式碼後,this.dataStore[3] = 9,inner自減1 inner為2
因此this.dataStore[2] = 8;因此陣列變為[0,1,8,9,7,6,2,3,5,4]
2. inner為2,temp為8,this.dataStore[inner-1]值為1 >= 8 false不成立。同理inner為1的時候 也不成立。
4. outer為4的時候
1. temp = this.dataStore[outer];temp值為7,inner等於4,this.dataStore[inner-1]值為9 >=7 因此while條件為true,
this.dataStore[inner] = this.dataStore[inner -1];執行這句程式碼後,this.dataStore[4] = 9,inner自減1 inner為3
因此this.dataStore[3] = 7;因此陣列變為[0,1,8,7,9,6,2,3,5,4]
2. inner為3的時候,temp為7,this.dataStore[inner-1]值為8 >=7 因此while條件為true,this.dataStore[inner] = this.dataStore[inner -1];執行這句程式碼後,this.dataStore[3] = 8,inner自減1 inner為2
因此this.dataStore[2] = 7;因此陣列變為[0,1,7,8,9,6,2,3,5,4]
3. inner為2的時候,temp為7,this.dataStore[inner-1]值為1 >=7 while條件為false,不成立,同理inner為1的時候,也為false,也不成立。
5. outer為5的時候:
1. temp = this.dataStore[outer];temp值為6,inner等於5,this.dataStore[inner-1]值為9 >=6 因此while條件為true,
this.dataStore[inner] = this.dataStore[inner -1];執行這句程式碼後,this.dataStore[5] = 9,inner自減1 inner為4
因此this.dataStore[4] = 6;因此陣列變為[0,1,7,8,6,9,2,3,5,4]
2.inner為4的時候,temp為6,this.dataStore[inner-1]值為8 >=6,因此while條件為true,
this.dataStore[inner] = this.dataStore[inner -1];執行這句程式碼後,this.dataStore[4] = 8,inner自減1 inner為3
因此this.dataStore[3] = 6;因此陣列變為[0,1,7,6,8,9,2,3,5,4]
3.inner為3的時候,temp為6,this.dataStore[inner-1]值為7 >=6,因此while條件為true,
this.dataStore[inner] = this.dataStore[inner -1];執行這句程式碼後,this.dataStore[3] = 7,inner自減1 inner為2
因此this.dataStore[2] = 6;因此陣列變為[0,1,6,7,8,9,2,3,5,4]
4. inner為2的時候,temp為6,this.dataStore[inner-1]值為1 >=6,條件為false不符合,同理inner=1也不符合。
6. outer為6的時候
1. temp = this.dataStore[outer];temp值為2,inner等於6,this.dataStore[inner-1]值為9 >=2 因此while條件為true,
this.dataStore[inner] = this.dataStore[inner -1];執行這句程式碼後,this.dataStore[6] = 9,inner自減1 inner為5
因此this.dataStore[5] = 2;因此陣列變為[0,1,6,7,8,2,9,3,5,4]
2.inner為5的時候,temp為2,this.dataStore[inner-1]值為8 >=2,因此while條件為true,
this.dataStore[inner] = this.dataStore[inner -1];執行這句程式碼後,this.dataStore[5] = 8,inner自減1 inner為4
因此this.dataStore[4] = 2;因此陣列變為[0,1,6,7,2,8,9,3,5,4]
3. inner為4的時候,temp為2,this.dataStore[inner-1]值為7 >=2,因此while條件為true,
this.dataStore[inner] = this.dataStore[inner -1];執行這句程式碼後,this.dataStore[4] = 7,inner自減1 inner為3
因此this.dataStore[3] = 2;因此陣列變為[0,1,6,2,7,8,9,3,5,4]
4. inner為3的時候,temp為2,this.dataStore[inner-1]值為6 >=2,因此while條件為true,
this.dataStore[inner] = this.dataStore[inner -1];執行這句程式碼後,this.dataStore[3] = 6,inner自減1 inner為2
因此this.dataStore[2] = 2;因此陣列變為[0,1,2,6,7,8,9,3,5,4]
5. inner為2的時候 不符合,同理inner=1的時候也不符合。
7. outer為7的時候
1. temp = this.dataStore[outer];temp值為3,inner等於7,this.dataStore[inner-1]值為9 >=3 因此while條件為true,
this.dataStore[inner] = this.dataStore[inner -1];執行這句程式碼後,this.dataStore[7] = 9,inner自減1 inner為6
因此this.dataStore[6] = 3;因此陣列變為[0,1,2,6,7,8,3,9,5,4]
2. temp = this.dataStore[outer];temp值為3,inner等於6,this.dataStore[inner-1]值為8 >=3 因此while條件為true,
this.dataStore[inner] = this.dataStore[inner -1];執行這句程式碼後,this.dataStore[6] = 8,inner自減1 inner為5
因此this.dataStore[5] = 3;因此陣列變為[0,1,2,6,7,3,8,9,5,4]
3. temp = this.dataStore[outer];temp值為3,inner等於5,this.dataStore[inner-1]值為7 >=3 因此while條件為true,
this.dataStore[inner] = this.dataStore[inner -1];執行這句程式碼後,this.dataStore[5] = 7,inner自減1 inner為4
因此this.dataStore[4] = 3;因此陣列變為[0,1,2,6,3,7,8,9,5,4]
4. temp = this.dataStore[outer];temp值為3,inner等於4,this.dataStore[inner-1]值為6 >=3 因此while條件為true,
this.dataStore[inner] = this.dataStore[inner -1];執行這句程式碼後,this.dataStore[4] = 6,inner自減1 inner為3
因此this.dataStore[3] = 3;因此陣列變為[0,1,2,3,6,7,8,9,5,4]
5. 當inner為3的時候 this.dataStore[inner-1]值為2 >=3 條件為false,所以不成立,同理inner==2或者1.
8 outer為8的時候
1. temp = this.dataStore[outer];temp值為5,inner等於8,this.dataStore[inner-1]值為9 >=5 因此while條件為true,
this.dataStore[inner] = this.dataStore[inner -1];執行這句程式碼後,this.dataStore[8] = 9,inner自減1 inner為7
因此this.dataStore[7] = 5;因此陣列變為[0,1,2,3,6,7,8,5,9,4]
2. temp = this.dataStore[outer];temp值為5,inner等於7,this.dataStore[inner-1]值為8 >=5 因此while條件為true,
this.dataStore[inner] = this.dataStore[inner -1];執行這句程式碼後,this.dataStore[7] = 8,inner自減1 inner為6
因此this.dataStore[6] = 5;因此陣列變為[0,1,2,3,6,7,5,8,9,4]
3. temp = this.dataStore[outer];temp值為5,inner等於6,this.dataStore[inner-1]值為7 >=5 因此while條件為true,
this.dataStore[inner] = this.dataStore[inner -1];執行這句程式碼後,this.dataStore[6] = 7,inner自減1 inner為5
因此this.dataStore[5] = 5;因此陣列變為[0,1,2,3,6,5,7,8,9,4]
4. temp = this.dataStore[outer];temp值為5,inner等於5,this.dataStore[inner-1]值為6 >=5 因此while條件為true,
this.dataStore[inner] = this.dataStore[inner -1];執行這句程式碼後,this.dataStore[5] = 6,inner自減1 inner為4
因此this.dataStore[4] = 5;因此陣列變為[0,1,2,3,5,6,7,8,9,4]
5. 當inner為4的時候 this.dataStore[inner-1]值為3 >=5 因此while條件為false,同理inner=3或者2或者1的時候,都不成立。
9. outer為9的時候
1. temp = this.dataStore[outer];temp值為4,inner等於9,this.dataStore[inner-1]值為9 >=4 因此while條件為true,
this.dataStore[inner] = this.dataStore[inner -1];執行這句程式碼後,this.dataStore[9] = 9,inner自減1 inner為8
因此this.dataStore[8] = 4;因此陣列變為[0,1,2,3,5,6,7,8,4,9]
2. temp = this.dataStore[outer];temp值為4,inner等於8,this.dataStore[inner-1]值為8 >=4 因此while條件為true,
this.dataStore[inner] = this.dataStore[inner -1];執行這句程式碼後,this.dataStore[8] = 8,inner自減1 inner為7
因此this.dataStore[7] = 4;因此陣列變為[0,1,2,3,5,6,7,4,8,9]
3. temp = this.dataStore[outer];temp值為4,inner等於7,this.dataStore[inner-1]值為7 >=4 因此while條件為true,
this.dataStore[inner] = this.dataStore[inner -1];執行這句程式碼後,this.dataStore[7] = 7,inner自減1 inner為6
因此this.dataStore[6] = 4;因此陣列變為[0,1,2,3,5,6,4,7,8,9]
4. temp = this.dataStore[outer];temp值為4,inner等於6,this.dataStore[inner-1]值為6 >=4 因此while條件為true,
this.dataStore[inner] = this.dataStore[inner -1];執行這句程式碼後,this.dataStore[6] = 6,inner自減1 inner為5
因此this.dataStore[5] = 4;因此陣列變為[0,1,2,3,5,4,6,7,8,9]
5. temp = this.dataStore[outer];temp值為4,inner等於5,this.dataStore[inner-1]值為5 >=4 因此while條件為true,
this.dataStore[inner] = this.dataStore[inner -1];執行這句程式碼後,this.dataStore[5] = 5,inner自減1 inner為4
因此this.dataStore[4] = 4;因此陣列變為[0,1,2,3,4,5,6,7,8,9]
以上所有的步驟都是插入排序的過程;
四:基本排序演算法的計時比較;
下面是所有的JS程式碼如下:
function CArray(numElements) { this.dataStore = []; this.pos = 0; this.numElements = numElements; this.insert = insert; this.toString = toString; this.clear = clear; this.setData = setData; this.swap = swap; this.bubbleSort = bubbleSort; this.selectionSort = selectionSort; this.insertionSort = insertionSort; /** // 氣泡排序 選擇排序 插入排序 for(var i = 0; i < numElements.length; i++) { this.dataStore[i] = numElements[i]; } **/ // 下面是為了測試效能的for迴圈 for(var i = 0; i< numElements; ++i) { this.dataStore[i] = i; } } function setData() { for(var i = 0; i < this.dataStore.length; i++) { this.dataStore[i] = Math.floor(Math.random() * (this.numElements + 1)); } } function clear() { for(var i = 0; i < this.dataStore.length; i++) { this.dataStore[i] = 0; } } function insert(element) { this.dataStore[this.pos++] = element; } function toString() { var restr = ""; for(var i = 0; i < this.dataStore.length; i++) { restr += this.dataStore[i] + " "; if(i > 0 && i % 10 == 0) { restr+= "\n"; } } return restr; } function swap(arr,index1,index2) { var temp = arr[index1]; arr[index1] = arr[index2]; arr[index2] = temp; } function bubbleSort() { var numElements = this.dataStore.length; var temp; for(var outer = numElements; outer >= 2; --outer) { for(var inner = 0; inner <= outer -1; ++inner) { if(this.dataStore[inner] > this.dataStore[inner + 1]) { swap(this.dataStore,inner,inner+1); } } } } function selectionSort() { var min,temp; for(var outer = 0; outer <= this.dataStore.length -2; ++outer) { min = outer; for(var inner = outer + 1; inner <= this.dataStore.length - 1; ++inner) { if(this.dataStore[inner] < this.dataStore[min]) { swap(this.dataStore,inner,min); } } } } // 插入排序 function insertionSort() { var temp,inner; for(var outer=1; outer <= this.dataStore.length - 1; ++outer) { temp = this.dataStore[outer]; inner = outer; while(inner > 0 && (this.dataStore[inner-1] >= temp)) { this.dataStore[inner] = this.dataStore[inner -1]; --inner; } this.dataStore[inner] = temp; } }
現在我們來分別對上面三種排序先設定10000個隨機元素進行排序後,所花費的多長時間,
1. 氣泡排序測試程式碼如下:
var numElements = 10000;
var myNums = new CArray(numElements);
myNums.setData();
var start = new Date().getTime();
myNums.bubbleSort();
var stop = new Date().getTime();
var t1 = stop - start;
console.log("對"+numElements+"個元素執行氣泡排序消耗的時間為:"+t1+"毫秒");
一直重新整理會有不同的時間 在chrome瀏覽器下大概會在700毫秒左右,我就選擇了一次的列印如下:
對10000個元素執行氣泡排序消耗的時間為:709毫秒
2. 對選擇排序的測試程式碼如下:
var numElements = 10000; var myNums = new CArray(numElements); myNums.setData(); var start2 = new Date().getTime(); myNums.selectionSort(); var stop2 = new Date().getTime(); var t2 = stop2 - start2; console.log("對"+numElements+"個元素執行選擇排序消耗的時間為:"+t2+"毫秒");
同理和上面一樣操作,最後的時間會在200毫秒左右,我一樣選擇了一次的列印時間如下:
對10000個元素執行選擇排序消耗的時間為:224毫秒
3. 對插入排序的測試程式碼如下:
var numElements = 10000; var myNums = new CArray(numElements); myNums.setData(); var start3 = new Date().getTime(); myNums.insertionSort(); var stop3 = new Date().getTime(); var t3 = stop3 - start3; console.log("對"+numElements+"個元素執行插入排序消耗的時間為:"+t3+"毫秒");
列印會在100毫秒左右,如下所示:
對10000個元素執行插入排序消耗的時間為:61毫秒
所以這三種基本排序的效能分別為 插入排序 > 選擇排序 > 氣泡排序;
基本排序的理解先到此為止;下次我們會來理解下高階排序演算法;