数组去重
原始数组: [4, 2, 5, 5, 8, 12, 43, 7, 2]
检测浏览器是否支持ECMA5
// 判断浏览器是否支持indexOf ,indexOf 为ecmaScript5新方法 IE8以下(包括IE8, IE8只支持部分ecma5)不支持 if (!Array.prototype.indexOf){ // 新增indexOf方法 Array.prototype.indexOf = function(item){ var result = -1, a_item = null; if (this.length == 0){ return result; } for(var i = 0, len = this.length; i < len; i++){ a_item = this[i]; if (a_item === item){ result = i; break; } } return result; } }
普通遍历数组法:
// 最简单数组去重法 function unique1(array){ var n = []; //一个新的临时数组 //遍历当前数组 for(var i = 0; i < array.length; i++){ //如果当前数组的第i已经保存进了临时数组,那么跳过, //否则把当前项push到临时数组里面 if (n.indexOf(array[i]) == -1) n.push(array[i]); } return n; }
对象键值对法:
// 速度最快, 占空间最多(空间换时间) function unique2(array){ var n = {}, r = [], len = array.length, val, type; for (var i = 0; i < array.length; i++) { val = array[i]; type = typeof val; if (!n[val]) { n[val] = [type]; r.push(val); } else if (n[val].indexOf(type) < 0) { n[val].push(type); r.push(val); } } return r; }
数组下标判断法
function unique3(array){ var n = [array[0]]; //结果数组 //从第二项开始遍历 for(var i = 1; i < array.length; i++) { //如果当前数组的第i项在当前数组中第一次出现的位置不是i, //那么表示第i项是重复的,忽略掉。否则存入结果数组 if (array.indexOf(array[i]) == i) n.push(array[i]); } return n; }
排序后相邻去除法
// 将相同的值相邻,然后去除 function unique4(array){ array.sort(); var re=[array[0]]; for(var i = 1; i < array.length; i++){ if( array[i] !== re[re.length-1]) { re.push(array[i]); } } return re; }
优化遍历数组法,代码思路来自: 数组快速去重
// 思路:获取没重复的最右一值放入新数组 function unique5(array){ var r = []; for(var i = 0, l = array.length; i < l; i++) { for(var j = i + 1; j < l; j++) if (array[i] === array[j]) j = ++i; r.push(array[i]); } return r; }
数组排序算法总结:日本人编写的排序动画
原始数组: [5,6,3,4,9,7,8,12,10,11,2,1]
原理图:
插入排序算法
// 插入排序 从下标1开始每增1项排序一次,越往后遍历次数越多 function sort1(array) { var len = array.length, i, j, tmp, result; // 设置数组副本 result = array.slice(0); for(i=1; i < len; i++){ tmp = result[i]; j = i - 1; while(j>=0 && tmp < result[j]){ result[j+1] = result[j]; j--; } result[j+1] = tmp; } return result; }
原理图:
二分插入排序
// 先在有序区通过二分查找的方法找到移动元素的起始位置,然后通过这个起始位置将后面所有的元素后移 function sort2(array) { var len = array.length, i, j, tmp, low, high, mid, result; // 赋予数组副本 result = array.slice(0); for(i = 1; i < len; i++){ tmp = result[i]; low = 0; high = i - 1; while(low <= high){ mid = parseInt((low + high)/2, 10); if(tmp < result[mid]) high = mid - 1; else low = mid + 1; } for(j = i - 1; j >= high+1; j--){ result[j+1] = result[j]; } result[j+1] = tmp; } return result; }
原理图:
希尔排序
// 希尔排序:先将整个待排序记录序列分割成若干个子序列,在在序列内分别进行直接插入排序,待整个序列基本有序时,再对全体记录进行一次直接插入排序 function sort3(array){ var len = array.length, gap = parseInt(len/2), i, j, tmp, result; // 复制数组 result = array.slice(0); while(gap > 0){ for(i = gap; i < len; i++){ tmp = result[i]; j = i - gap; while(j>=0 && tmp < result[j]){ result[j + gap] = result[j]; j = j - gap; } result[j + gap] = tmp; } gap = parseInt(gap/2); } return result; }
原理图:
冒泡排序
// 冒泡排序 每次将最小元素推至最前 function sort4(array) { var len = array.length, i, j, tmp, result; result = array.slice(0); for (i = 0; i < len; i++) { for (j = len - 1; j > i; j--) { if (result[j] < result[j - 1]) { tmp = result[j - 1]; result[j - 1] = result[j]; result[j] = tmp; } } } return result; }
原理图:
改进冒泡排序
// 如果在某次的排序中没有出现交换的情况,那么说明在无序的元素现在已经是有序了,就可以直接返回了。 function sort5(array) { var len = array.length, i, j, tmp, exchange, result; result = array.slice(0); for (i = 0; i < len; i++) { exchange = 0; for (j = len - 1; j > i; j--) { if (result[j] < result[j - 1]) { tmp = result[j]; result[j] = result[j - 1]; result[j - 1] = tmp; exchange = 1; } } if (!exchange) return result; } return result; }
原理图:
快速排序
//(1)在数据集之中,选择一个元素作为"基准"(pivot)。 //(2)所有小于"基准"的元素,都移到"基准"的左边;所有大于"基准"的元素,都移到"基准"的右边。 //(3)对"基准"左边和右边的两个子集,不断重复第一步和第二步,直到所有子集只剩下一个元素为止。 function sort6(array) { var tmp_array = array.slice(0), result, quickSort = function(arr) { if (arr.length <= 1) { return arr; } var pivotIndex = Math.floor(arr.length / 2); var pivot = arr.splice(pivotIndex, 1)[0]; var left = []; var right = []; for (var i = 0; i < arr.length; i++){ if (arr[i] < pivot) { left.push(arr[i]); } else { right.push(arr[i]); } } return quickSort(left).concat([pivot], quickSort(right)); }; result = quickSort(tmp_array); return result; }
原理图:
选择排序
// 在无序区中选出最小的元素,然后将它和无序区的第一个元素交换位置。 // 原理跟冒泡排序一样,算是冒泡的衍生版本 function sort7(array) { var len = array.length, i, j, k, tmp, result; result = array.slice(0); for (i = 0; i < len; i++) { k = i; for (j = i + 1; j < len; j++) { if (result[j] < result[k]) k = j; } if (k != i) { tmp = result[k]; result[k] = result[i]; result[i] = tmp; } } return result; }
堆排序原理太复杂,一张图表达不了:详情请看: 堆排序原理分析
堆排序
// 1) 初始堆:将原始数组调整成大根堆的方法——筛选算法:子节点都比父节点小 // 2) 堆排序: 每次将堆顶元素与数组最后面的且没有被置换的元素互换。 // 参考代码: http://bubkoo.com/2014/01/14/sort-algorithm/heap-sort/ function sort8(array) { var result = array.slice(0); function swap(array, i, j) { var temp = array[i]; array[i] = array[j]; array[j] = temp; } function maxHeapify(array, index, heapSize) { var iMax, iLeft, iRight; while (true) { iMax = index; iLeft = 2 * index + 1; iRight = 2 * (index + 1); if (iLeft < heapSize && array[index] < array[iLeft]) { iMax = iLeft; } if (iRight < heapSize && array[iMax] < array[iRight]) { iMax = iRight; } if (iMax != index) { swap(array, iMax, index); index = iMax; } else { break; } } } function buildMaxHeap(array) { var i, iParent = Math.floor(array.length / 2) - 1; for (i = iParent; i >= 0; i--) { maxHeapify(array, i, array.length); } } function sort(array) { buildMaxHeap(array); for (var i = array.length - 1; i > 0; i--) { swap(array, 0, i); maxHeapify(array, 0, i); } return array; } return sort(result); }
原理图:
归并排序
// 合并排序:将无序的数组 拆成N部分进行有序处理,然后合并; // 参考代码: https://gist.github.com/paullewis/1982121 function sort9(array) { var result = array.slice(0); // 递归调用合并函数 function sort(array) { var length = array.length, mid = Math.floor(length * 0.5), left = array.slice(0, mid), right = array.slice(mid, length); if (length === 1) { return array; } return merge(sort(left), sort(right)); } // 合并 两有序的数组 function merge(left, right) { var result = []; while (left.length || right.length) { if (left.length && right.length) { if (left[0] < right[0]) { result.push(left.shift()); } else { result.push(right.shift()); } } else if (left.length) { result.push(left.shift()); } else { result.push(right.shift()); } } return result; } return sort(result); }
显示随机数组
原始数组: [8,2, 3, 55, 12, 20, 16, 18, 15, 20, 11, 7]
对应代码:
// 随机从数组中获取 N个不重复的值, 默认从数组取一个值 function ran1(array, n){ var _result = [], _index = 0, _arrayTemp; // 防止原数组被改变 _arryTemp = array.slice(0); if (array == null || array.length == 0 || array.length < n){ return _result; } // 随机获取一个值 if (n == null){ _index = Math.floor(Math.random() * array.length); _result.push(array[_index]); }else{ // 随机获取N个值 for (var i = 0; i < n; i++){ _index = Math.floor(Math.random() * _arrayTemp.length); _result.push(_arrayTemp[_index]); // 删除该元素 _arrayTemp.splice(_index, 1); } } return _result; }
对应代码:
// 随机打乱数组,使数组内元素与原来位置完全不同 function ran2(array){ var array_tmp = [], i , j, len, new_a = [], a_obj; // 添加数组原位置标志位 for (i = 0, len = array.length; i < len; i++) { a_obj = { 'key': i, 'val': array[i] }; array_tmp.push(a_obj); } for (i = 0, len = array.length; i < len; i++) { j = ranCount(array_tmp.length); // 如下标位置与原值重复,重新随机 while ( i === array_tmp[j].key ) { j = ranCount(array_tmp.length); } new_a.push( array_tmp[j].val ); // 删除数组 array_tmp.splice(j,1); } // 获得给定数字的随机数, 出错返回-1 function ranCount(n){ var result = parseInt(n, 10); if ( isNaN(result) ) { result = -1; } result = Math.floor(Math.random() * result) return result; } return new_a; }
对应代码:
// 从指定范围内(暂定为100以内),随机获取N(暂定为10)个值的数组 function ran3(){ var result = [], SCOPE_NO = 100, COUNT = 10; result = getRandomNo(SCOPE_NO, COUNT); function getRandomNo(scope_no, count){ var i, s_n, ran_n, _result = []; s_n = parseInt(scope_no, 10); for (i = 0; i < count; i++) { ran_n = Math.floor(Math.random() * s_n); _result.push(ran_n); } return _result; } return result; }
数组深度优先遍历
原始数组: [ ['a', 'b', 'c'], ['1', '2', '3'], ['x', 'y', 'z'] ]
var result, results, garr; // 递归函数实现遍历 function dfs(arr, depth) { for (var i = 0; i < arr[depth].length; i++) { result[depth] = arr[depth][i]; if (depth != arr.length - 1) { dfs(arr, depth + 1); } else { results.push(result.join('')); } } } function test(arr) { results = []; result = []; dfs(arr, 0); console.log(results.length, results.join(',')); } garr = [ ['a', 'b', 'c'], ['1', '2', '3'], ['x', 'y', 'z'] ]; test(garr);