js算法初窥07(算法复杂度)
算法复杂度是我们来衡量一个算法执行效率的一个度量标准,算法复杂度通常主要有时间复杂度和空间复杂度两种。时间复杂度就是指算法代码在运行最终得到我们想要的结果时所消耗的时间,而空间复杂度则是指算法中用来存储的数据结构所占用的空间。往往一个时间复杂度比较低的算法拥有着较高的空间复杂度,两者是互相影响的,我们前面讲解数据结构中的一些例子和代码也足以说明这一点。本文会简单介绍一下用于描述算法的性能和复杂程度的大O表示法。
我们先来看一段简单的代码,来帮助我们理解什么是大O表示法:
function increment(num) {
    return ++num;
}
console.log(increment(1));
上面的代码声明了一个函数,然后调用它。这样的代码无论我们传入的参数是什么,它都会返回自增后的结果。也就是说该函数的执行时间跟我们传入的参数没有任何关系,执行的时间都是X。因此,我们称该函数的复杂度是O(1),常数的。
我们再来看看前面讲过的顺序搜索算法,我们直接把代码拿过来用就好了。
//顺序搜索
function sequentialSearch(array,item) {
for(var i = 0; i < array.length; i++) {
if(item === array[i]) {
return i;
};
};
return -1;
};
现在我们假设要搜索的数组是[1,2,3...9,10],然后我们搜索1这个元素,那么在第一次判断时就能找到想要搜索的元素。那么我们这里先假设每执行一次循环的开销是1。那么我们还想搜索11,数组中没有这个元素,sequentialSearch 就会执行十次遍历整个数组,发现没有后返回-1。那么在最坏的情况下,数组的长度大小决定了算法的搜索时间。这样的函数的时间复杂度就是O(n),线性的,这里的n就是数组的长度。
那么,我们来稍微修改一下sequentialSearch让它可以计算开销:
//顺序搜索
function sequentialSearch(array,item) {
var cost = 0;
for(var i = 0; i < array.length; i++) {
cost++;
if(item === array[i]) {
return i;
};
};
console.log(array.length,cost);
return -1;
}; sequentialSearch([1,2,3,4,5,6,7,8,9,10],11);
很简单,就是加上了一个cost变量来计数。那么我们下面再来看看冒泡排序的时间复杂度是怎样的,这里我们不再浪费篇幅,直接在代码中加入计数器:
function swap(array,index1,index2) {
    var aux = array[index1];
    array[index1] = array[index2];
    array[index2] = aux;
}
function bubbleSort(array) {
    var length = array.length;
    var cost = 0;
    for (var i = 0; i < length; i++) {
        cost++;
        for (var j = 0; j < length - 1; j++) {
            cost++;
            if(array[j] > array[j + 1]) {
                swap(array,j,j+1);
            }
        }
    }
    console.log(length,cost);
}
bubbleSort([2,3,4,1,8,7,9,10]);
代码本身没什么好说的,我们发现,如果数组的长度是8,那么我们排序所消耗的时间就是64,如果长度是10,消耗的时间就是100。换句话说,冒泡排序的时间复杂度就是数组长度的平方,也就是O(n2)。
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<style>
body { background-color: #DDDDDD; font: 30px sans-serif; }
</style>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load('visualization', '1.0', {'packages':['corechart']});
google.setOnLoadCallback(drawChart); function drawChart() { var data = new google.visualization.DataTable();
data.addColumn('string', 'n');
data.addColumn('number', 'O(1)');
data.addColumn('number', 'O(log n)');
data.addColumn('number', 'O(n)');
data.addColumn('number', 'O(n log n)');
data.addColumn('number', 'O(n^2)');
data.addColumn('number', 'O(2^n)'); for (var i = 0; i <= 30; i++) {
data.addRow([i+'', 1, Math.log(i), i, Math.log(i)*i, Math.pow(i,2), Math.pow(2,i)]);
} var options = {'title':'Big O Notation Complexity Chart',
'width':700,
'height':600,
'backgroundColor':{stroke:'#CCC',strokeWidth:1},
'curveType':'function',
'hAxis':{
title:'Elements (n)',
showTextEvery:5
},
'vAxis':{
title:'Operations',
viewWindowMode:'explicit',
viewWindow:{min:0,max:450}
}
}; var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
</script>
</head>
<body>
<div id='chart_div'></div>
</body>
</html>
上面的代码是用js画的一幅图,其中有一些常用的大O表示法所对应的时间复杂度,大家可以把代码COPY到本地自行去看一下,这样会才会对大O表示法有更好的理解,为了偷点懒,也为了大家可以确实的自己去看一下图标。我这里不会把图给大家贴上的。
下面给大家贴上几张图,来看看我们之前学习的一些数据结构和算法的时间复杂度是怎样的。
1、常用数据结构的时间复杂度

2、图的时间复杂度

表格中的V代表顶点,E代表边。
3、排序算法

4、搜索算法的时间复杂度

终于,我们了解了几乎我们前面学过的所有的数据结构和算法的时间复杂度,这样我们在选择算法的时候可以更确切地评估它的效率。
那么,我们本系列的文章也将告一段落。后面准备深入的学习一下CSS。可能会把其中一些比较有意思的地方贴出来与大家分享。
最后,由于本人水平有限,能力与大神仍相差甚远,若有错误或不明之处,还望大家不吝赐教指正。非常感谢!
  最后,感谢大家的阅读。如果您觉得或许还有那么点用处,可以把我的主页加入你的收藏夹中以便需要的时候可以快速的找到。
js算法初窥07(算法复杂度)的更多相关文章
- js算法初窥05(算法模式02-动态规划与贪心算法)
		在前面的文章中(js算法初窥02(排序算法02-归并.快速以及堆排)我们学习了如何用分治法来实现归并排序,那么动态规划跟分治法有点类似,但是分治法是把问题分解成互相独立的子问题,最后组合它们的结果,而 ... 
- js算法初窥01(排序算法01-冒泡、选择、插入)
		排序,我想大家一定经历过或者正在经历着.或许你不懂算法,对排序算法一无所知,但是你一定用过一些第三方库的api来一键排序,那么,在你享受便捷的同时,你是否想过它的底层是如何实现的?这样的算法实现方式是 ... 
- Python <算法思想集结>之初窥基础算法
		1. 前言 数据结构和算法是程序的 2 大基础结构,如果说数据是程序的汽油,算法则就是程序的发动机. 什么是数据结构? 指数据在计算机中的存储方式,数据的存储方式会影响到获取数据的便利性. 现实生活中 ... 
- js算法初窥02(排序算法02-归并、快速以及堆排序)
		上一篇,我们讲述了一些简单的排序算法,其实说到底,在前端的职业生涯中,不涉及node.不涉及后台的情况下,我目前还真的没想到有哪些地方可以用到这些数据结构和算法,但是我在前面的文章也说过了.或许你用不 ... 
- js算法初窥03(简单搜索及去重算法)
		前面我们了解了一些常用的排序算法,那么这篇文章我们来看看搜索算法的一些简单实现,我们先来介绍一个我们在实际工作中一定用到过的搜索算法--顺序搜索. 1.顺序搜索 其实顺序搜索十分简单,我们还是以第一篇 ... 
- js算法初窥04(算法模式01-递归)
		终于来到了有点意思的地方--递归,在我最开始学习js的时候,基础课程的内容就包括递归,但是当时并不知道递归的真正意义和用处.我只是知道,哦...递归是自身调用自身,递归要记得有一个停止调用的条件.那时 ... 
- js算法初窥03(搜索及去重算法)
		前面我们了解了一些常用的排序算法,那么这篇文章我们来看看搜索算法的一些简单实现,我们先来介绍一个我们在实际工作中一定用到过的搜索算法——顺序搜索. 1.顺序搜索 其实顺序搜索十分简单,我们还是以第一篇 ... 
- js算法初窥06(算法模式03-函数式编程)
		在解释什么是函数式编程之前,我们先要说下什么是命令式编程,它们都属于编程范式的一种.命令式编程其实就是一块一块的代码,其中包括了我们要执行的逻辑或者判断或者一些运算.也就是按部就班的一步一步完成我们所 ... 
- 数据结构(逻辑结构,物理结构,特点)  C#多线程编程的同步也线程安全  C#多线程编程笔记  String 与 StringBuilder (StringBuffer)  数据结构与算法-初体验(极客专栏)
		数据结构(逻辑结构,物理结构,特点) 一.数据的逻辑结构:指反映数据元素之间的逻辑关系的数据结构,其中的逻辑关系是指数据元素之间的前后件关系,而与他们在计算机中的存储位置无关.逻辑结构包括: 集合 数 ... 
随机推荐
- cordova AndroidStudio3.0 升级报错问题
			http://blog.csdn.net/z_Xiaozuo/article/details/78962701 ionic3 打包 安卓项目遇到的问题,当时比较冲忙升级了下android studio ... 
- LeetCode(76): 最小覆盖子串
			Hard! 题目描述: 给定一个字符串 S 和一个字符串 T,请在 S 中找出包含 T 所有字母的最小子串. 示例: 输入: S = "ADOBECODEBANC", T = &q ... 
- 《剑指offer》 调整数组顺序使得奇数在偶数前面
			本题来自<剑指offer> 调整数组顺序使得奇数在偶数前面 题目: 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分, ... 
- PDF文件编辑技巧之PDF书签怎么设置
			纸质的文件想要添加书签就直接拿笔书写就可以,Word文件怎么添加书签相信大家也都知道,那么PDF文件的书签要怎么设置的呢,是不是有很多小伙伴不知道该怎么做呢,不要担心,今天小编就来跟大家分享一下在PD ... 
- 论坛IP地址追踪&路由器密码嗅探
			一.论坛IP地址查询 1.任何应用程序部可以调用一个标准的库函数来查看给定名称的主机IP地址.类似地,系统还提供一个逆函致—给定主机的IP地址,查看它所对应的主机名.大多数使用主机名作为参数的应用程序 ... 
- hdu5015构造转移矩阵
			/* 构造转移矩阵: 先推公式: 首先是第0行:A[0][j+1]=A[0][j]*10+3 1-n行: A[i][j+1]=A[i][j]+A[i-1][j+1]=... =A[i][j]+A[i- ... 
- bzoj1912 树形dp求直径(新写法),求直径的两端点
			通过回溯法可以求出直径的两个端点,同时注意有负权边的树求直径不可以用两次dfs来求,而必须用dp做 /* 分情况讨论问题 一条边也不加的情况,显然每条边要扫描两次, 该情况的答案是2(n-1) 只加一 ... 
- poj2116 模拟题
			不知道错在哪里 /* 给定两个斐波那契表示数,要求用标准化表达方式表达 然后将这两个数加起来,和也用标准化方式表达 思路:显然要将这两个数先用十进制表示,和也用十进制表示 然后在转化成二进制即可 1 ... 
- poj3107树的重心
			/*树的重心求法:两次dfs,第一次dfs处理出每个结点的size,以此求每个结点大儿子的size,第二次dfs将每个结点大儿子的size和余下结点数进行比较,所有结点里两个值之间差值最小的那个点就是 ... 
- linux 将自己的服务添加到系统service服务
			前言 我们在linux上要启动一个程序得时候, 往往都是要写一堆路径, 找到要启动得服务程序, 再用 ./*** 启动服务. 那么我们有没有快速启动方法吗, 答案是肯定得 service 介绍 官方介 ... 
