排序算法一直都是筆試和麪試的一個必考點,這次我們就通過實例的講解,給出JavaScript版本的排序算法。
我們先初始化一個算法的構造函數,然後將各種排序算法都作爲方法寫在構造函數的內部,構造函數如下所示:
function ArrayList() {
var array = [];
this.insert = function (item) {
array.push(item);
};
this.toString = function () {
return array.join();
};
// 交換變量的值
function swap(index1, index2){
var flag = array[index1];
array[index1] = array[index2];
array[index2] = flag;
};
}
//構建數組實例
function CreateSortArray(num) {
var array = new ArrayList();
for(var i = num; i > 0; i--){
array.insert(i);
}
return array;
}
冒泡排序 — 時間複雜度O(n^2)
冒泡雙循環,外層循環控制需要確立元素回到正確位置的次數,最後一個元素自動回到正確的位置上面;內層循環將相鄰的元素兩兩進行比較,如果第一個比第二個大,就交換他們,直至結束。因爲數組後面的元素已經是有序的,所以內層循環次數必須減去排序好元素的大小。
代碼如下:
this.bubbleSort = function () {
for(var i = 0; i < array.length; i++)
for(var j = 0; j < array.length - 1 - i; j++)
{
if(array[j] > array[j + 1])
{
swap(j, j + 1);
}
}
};
選擇排序 – 時間複雜度O(n^2)
算法思想: 首先我們假定第一個元素爲最小的元素,在後面的元素中找出最小的,與第一個進行位置交換,若第一個本身都是最小的,我們則不變位置,以此類推,得到數組的升序排列。
代碼如下:
this.selectionSort = function () {
var length = array.length;
for(var i = 0; i < length - 1; i++){
indexMin = i;
for(var j = i + 1; j < length; j++)
{
if(array[i] > array[j])
{
indexMin = j;
}
}
if(i !== indexMin)
{
swap(i, indexMin);
}
}
};
插入排序 — 時間複雜度O(n^2)
算法思想:假定第一個元素是已經排過序的,後面的元素與前面的元素進行比較,比自身大的就交換位置,小的則位置不變。
代碼如下:
this.insertionSort = function () {
var temp;
for(var i = 1; i < array.length; i++)
{
j = i;
temp = array[i];
while(j > 0 && array[j] < array[j - 1])
{
array[j] = array[j - 1];
j--;
}
array[j] = temp;
}
return array;
};
歸併排序 — 時間複雜度O(nlog * n)
算法思想:使用遞歸將一個大的數組分成n(n代表數組的長度)個只有一個元素的列表,然後再使用合併算法進行合併,相當於數組拆分,再給元素進行排序合併,效果圖如下:
在理解了思想後,我們來看看代碼:
this.mergeSort = function () {
array = mergeSortRec(array);
};
var mergeSortRec = function (array) {
var length = array.length;
if(length === 1)
{
return array;
}
var mid = Math.floor(length / 2);
var left = array.slice(0, mid);
var right = array.slice(mid, length);
return merge(mergeSortRec(left), mergeSortRec(right));
};
var merge = function (left, right) {
var result = [];
var il = 0, ir = 0;
while(il < left.length && ir < right.length)
{
if(left[il] < right[ir])
{
result.push(left[il++]);
}else{
result.push(right[ir++]);
}
}
while(il < left.length)
{
result.push(left[il++]);
}
while(ir < right.length)
{
result.push(right[ir++]);
}
return result;
};
快速排序 — 時間複雜度O(nlog^n)
算法思想:我們先從數組的中間確定一個元素爲主元,將其劃分爲無限小的序列,然後從數組的頭部確立頭指針,尾部確立尾指針。依次與主元進行比較,左邊比主元大的,右邊比主元小的,將依次交互位置,重複 以上操作,實現快速升序排列,快速排序的性能比其它同複雜度的要好。
代碼如下:
this.quickSort = function() {
quick(array, 0, array.length - 1);
};
var quick = function (array, left, right){
var index;
if(array.length > 1){
index = partition(array, left, right);
if(left < index - 1){
quick(array, left, index - 1);
}
if(index < right){
quick(array, index, right);
}
}
};
var partition = function (array, left, right) {
var provt = array[Math.floor((left + right) / 2)];
var i = left,
j = right;
while(i <= j) {
while(array[i] < provt) {
i++;
}
while(array[j] > provt) {
j--;
}
if(i <= j) {
swapQuickSort(array, i, j);
i++;
j--;
}
}
return i;
};
var swapQuickSort = function (array, index1, index2) {
var flag = array[index1];
array[index1] = array[index2];
array[index2] = flag;
};
二分搜索法
算法思想: 在數組中尋找一個特定的值,我們可以從數組的中間將其分隔開,當然前提是數組是已經排序過的,同中間值進行比較,然後重複之前的操作,直至找出來要比較的值。
代碼如下:
this.binarySearch = function (item) {
this.quickSort(); //使用快排進行排序
var low = 0,
high = array.length - 1,
mid,
element;
while(low <= high){
mid = Math.floor((low + high) /2);
element = array[mid];
if(item < element) {
high = mid - 1;
}else if(item > element){
low = mid + 1;
}else{
return mid;
}
}
return -1;
};
代碼測試
var array = new CreateSortArray(5);
console.log(array.toString());
array.bubbleSort();
console.log(array.toString());
array.selectionSort();
console.log(array.toString());
array.insertionSort();
console.log(array.toString());
array.mergeSort();
console.log(array.toString());
array.quickSort();
console.log(array.toString());
console.log(array.binarySearch(1));
效果圖如下所示:
源碼:git源碼地址
以上就是對算法的一些複習,如果有什麼不足,望大家指出來,一起進步。