我以爲做爲前端學學算法也是有益處的吧,因此今天就先來說講最基礎的排序算法。提高咱們程序員的內功~前端
插入排序是n^2的基礎排序方法,大體思想是假設一個數組的前n個元素已經有序,而後考慮把第n+1個未排序的元素給插入到有序數組中去。現將n+1和第n個元素比較,若是n+1比n小,那麼就交換一下位置。以後咱們要排序的元素就在n這個位置上了,接着咱們繼續比較n和第n-1個元素的大小。如此反覆,直到咱們要插入的元素找到適合他的位置。
下面來示範一下
6--7--8--9--3--1--4--6--3--8--9--5
6--7--8--9已經有序,咱們要插入的元素是n=4這個元素3。比較9和3的大小,9比3大。交換一下位置
6--7--8--3--9,就變成了這個樣子。接着比較8和3的大小,8比3大,交換一下位置
6--7--3--8--9,繼續比較7和3的大小,7比3大,交換一下位置
6--3--7--8--9,繼續比較6和3的大小,6比3大,交換一下位置
3--6--7--8--9。到這裏循環結束,就已經排好序了。接着比較第n=5的元素1應該插入的位置,如此往復就把數組給排好了序了。
一下是代碼。程序員
//寫一個隨機生成數組的函數 function randomArr(count) { var arr = [] for (var i = 0; i < count; i++) { var number = Math.ceil(Math.random() * 5000) arr.push(number) } return arr } // 交換元素位置的函數 function swap(arr, i, j) { var temp = arr[i] arr[i] = arr[j] arr[j] = temp } var arr = randomArr(5000) // 插入排序函數 function insertionSort(arr) { var length = arr.length // 第0個元素默認就是有序的,由於只有一個元素,因此從第一個元素開始。arr[i]就是要插入的那個元素 for (var i = 1; i < length; i++) { // 從第i-1個元素往前都是已經排好序的元素。因此最後一個開始往前比較 for (var j = i - 1; j >= 0; j--) { // 這裏的j+1等於i這個元素。也就是arr[i] === arr[j+1] if (arr[j] > arr[j + 1]) { swap(arr, j + 1, j) } else { break } } } return arr } insertionSort(arr)
因爲是兩層for循環,因此它的時間複雜度是n^2級別的。
到這裏其實尚未完,插入排序仍是有能夠優化的地方的。如今的這個插入排序函數要swap頻繁的交換位置,咱們能夠這樣算法
function insertionSort(arr) { var length = arr.length // 第0個元素默認就是有序的,由於只有一個元素,因此從第一個元素開始。arr[i]就是要插入的那個元素 for (var i = 1; i < length; i++) { // **用一個變量保存要插入的元素** var value = arr[i] // 從第i-1個元素往前都是已經排好序的元素。因此最後一個開始往前比較 for (var j = i - 1; j >= 0; j--) { // 這裏的j+1等於i這個元素。也就是arr[i] === arr[j+1] if (arr[j] > value) { // 若是比要插入的元素大,把值arr[j]往右移一位 arr[j+1] = arr[j] // 邊界條件,直到j等於0的時候終止循環,將value賦給arr[0],結束循環 if (j === 0){arr[j] = value; break} } else { // 不然把value賦給arr[j]循環結束 arr[j] = value break } } } return arr }
雖然插入排序是n^2級別的算法,可是在一個近乎有序的數組裏去實現插入排序,那麼他的效率會變的很是高。數組
有興趣能夠寫一個生成近乎有序數組的函數去實驗一下。dom
// 近乎有序數組 function nearlySorted(arr) { return arr }
選擇排序就是在循環中不停的選擇最小的元素,而後交換位置。
下面來示範一下
6--7--8--9--3--1--4--6--3--8--9--5
找到數組中最小的元素1,而後記錄1的位置是5。接着交換位置變成
1--7--8--9--3--6--4--6--3--8--9--5
接着在剩下的數組裏7--8--9--3--6--4--6--3--8--9--5找到最小的元素3,記錄下它的下標位置是4,而後交換位置變成
1--3--8--9--7--6--4--6--3--8--9--5。如此往復直到排好序。函數
function randomArr(count) { var arr = [] for (var i = 0; i < count; i++) { var number = Math.ceil(Math.random() * 5000) arr.push(number) } return arr } function swap(arr, i, j) { var temp = arr[i] arr[i] = arr[j] arr[j] = temp } var arr = randomArr(5000) function selectionSort(arr) { var length = arr.length var value, pos for (var i = 0; i < length; i++) { value = arr[i] pos = i for (var j = i; j < length; j++) { var cur = arr[j] if (value > cur) { value = cur pos = j } } swap(arr, i, pos) } return arr } selectionSort(arr)
到此兩個基礎排序就實現了。總結一下,插入排序優於選擇排序。優化
插入排序能夠提早終止內層循環,若是數組近乎有序,那麼效率會很高。而選擇排序沒法提早終止循環。
不過最好的排序算法仍是nlogn級別的算法。如歸併排序和快速排序。
個人寫的不是最好的,僅僅是解釋概念,有興趣的同窗能夠本身寫一個更好的插入排序和選擇排序。code