排序算法(Sorting algorithm)是计算机科学最古老、最基本的课题之一。要想成为合格的程序员,就必须理解和掌握各种排序算法。
目前,最常见的排序算法大概有七八种,其中"快速排序"(Quicksort)使用得最广泛,速度也较快。
思想:
(1)在数据集之中,选择一个元素作为"基准"(pivot)。
(2)所有小于"基准"的元素,都移到"基准"的左边;所有大于"基准"的元素,都移到"基准"的右边。
(3)对"基准"左边和右边的两个子集,不断重复第一步和第二步,直到所有子集只剩下一个元素为止。
var 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));
};
——摘自阮一峰老师的:快速排序(Quicksort)的Javascript实现.
冒泡排序: 一次比较两个元素,如果它们的顺序错误就把它们交换过来。
function test1(arr){
for(var i =0;i<arr.length;i++){
for(var j =0;j<arr.length-1-i;j++){
var t ;
if(arr[j]>=arr[j+1]){
t = arr[j];
arr[j]=[j+1];
arr[j] = t;
// ES6用解构赋值来交换两个值 [arr[j],arr[j+1]] = [arr[j+1],arr[j]]
}
return arr
}
简单选择排序:每次循环找到最小的取出来,之后递归。
function test3(arr){
if(arr.length<=1){
return arr
}
var iMin = arr[0];
var index =0;
for(var i = 0;i<arr.length;i++){
if(arr[i]<iMin){
iMin = arr[i] ; //每次循环找到最小的
index = i;
}
}
var aa = arr.splice(index,1);
return aa.concat( arguments.callee(arr)) //递归
}
去重:
对于数组去重,只要写过程序的,立刻就能得到第一个解法:
function unique(arr) {
var ret = []
for (var i = 0; i < arr.length; i++) {
var item = arr[i]
if (ret.indexOf(item) === -1) {
ret.push(item)
}
}
return ret
}
上面这个函数很正确,性能也不错。但前端最大的悲哀也是挑战之处在于,要支持各种运行环境。在 IE6-8 下,数组的 indexOf 方法还不存在。直觉方案要稍微改造一下:
var indexOf = [].indexOf ?
function(arr, item) {
return arr.indexOf(item)
} :
function indexOf(arr, item) {
for (var i = 0; i < arr.length; i++) {
if (arr[i] === item) {
return i
}
}
return -1
}
这里是封装一个array的一个indexOf方法
function unique(arr) {
var ret = []
for (var i = 0; i < arr.length; i++) {
var item = arr[i]
if (indexOf(ret, item) === -1) {
ret.push(item)
}
}
return ret
}
但是两层循环总是很不爽的。
第二种方法是我们利用json对象:
思路如下
1.创建一个新的数组存放结果;
2.创建一个空对象;
3.for循环时,每次取出一个元素与对象进行对比,如果这个元素不重复,则把它存放到结果数组中,同时把这个元素的内容作为对象的一个属性,并赋值为1,存入到第2步建立的对象中。
说明:至于如何对比,就是每次从原数组中取出一个元素,然后到对象中去访问这个属性,如果能访问到值,则说明重复。
Array.prototype.unique = function(){
var res = [];
var json = {};
for(var i = 0; i < this.length; i++){
if(!json[this[i]]){ res.push(this[i]);
json[this[i]] = 1;
}
}
return res;
}
但是这里判断1和“1”是相同的,这里修复下
------------------------------------------
functionunique(arr){
varres=[]
var json={}
for(vari=0;i<arr.length;i++){
varitem=arr[i]
varkey=typeof(item)+item
if(!json[key]){
res.push(item)
json[key]=1
}
}
return ret
}
当然这里面还可能有些问题,到时候根据实际项目来定
函数式编程:去重
function test2(arr) {
var json = {};
return arr.filter(function(item,index,arr){
if(!json[item]){
json[item] = 1;
return true
}
})
}
ES6去重方法:
Set是一个类似数组对象,并且它的每个值都不相同;
Array.from() 可以将累数组对象和可遍历对象转换成真正的数组
function u(arr) {return Array.form(new Set(arr))
}
or
function unique (arr) {
const seen = new Map()
return arr.filter((a) => !seen.has(a) && seen.set(a, 1))
}
斐波那契数列 1 ,1,2,3,5,8,13,21
方法1:递归
function test(n) {
if(n <= 2) {
return 1
}
return arguments.callee(n - 1) + arguments.callee(n - 2) //利用递归
}
// console.log(test(8)) //21
function t(n) {
var aaa = [];
for(var i = 1; i <= n; i++) {
(function() { //外层这个闭包没必要,可以去掉
return aaa.push(test(i))
})(i)
}
return aaa
}
console.log(t(8)) //1 ,1,2,3,5,8,13,21
方法二: 迭代
function aa(n){
var num1 = 1;
var num2 =1;
var num3 =0;
if(n<3){
num3 = 1
}
for( var i =3;i<=n;i++){
num3 = num1 +num2;
num1=num2;
num2 = num3 //当n=4时,这时候的num1的值是num2,num2的值是num3
}
return num3;
}
console.log(aaa(8)) //21
function tt(n){
var a = []
for(var i = 1;i<=n;i++){
(function(){ //外层这个闭包没必要可以去掉
return a.push(aa(i))
})(i)
}
return a;
}
console.log(tt(8)) //1 ,1,2,3,5,8,13,21
方法三尾递归优化:
递归非常耗内存,因为需要同时保存成千上百个调用帧,很容易发生‘栈溢出’(stack overflow)。但对于尾递归优化来说,由于只存在一个调用帧,所以永远不会发生栈溢出。
function F(n,ac1 = 1,ac2 = 1){
if( n <=1 ){ return ac2}
return F(n - 1,ac2,ac1 +ac2)
}
尾递归的实现,往往需要改写递归函数,确保最后一步只调用自身。做到这一点的方法,就是把所有用到的内部变量改写成函数的参数.
方法四利用函数记忆功能