什么是算法(Algorithm)?
计算方法,解决某种特定问题的思路
常见的算法
冒泡排序、选择排序、快速排序、插入排序等等
哈希算法(加密、散列)
数据结构
通俗来说是在计算机中,存储和组织数据的方式
数组、堆栈结构、队列结构、链表等等
数组
数组是一种线性结构,并且可以在数组的任意位置插入和删除数据
栈结构
栈是一种受限的线性表,后进先出
其限制是仅允许在表的一端进行插入和删除运算。这一端被称为栈顶,相对地,把另一端称为栈底
向一个栈插入新元素又称为进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之称为新的栈顶元素
从一个栈删除元素又称作出栈或退栈,他是把栈元素删除掉,使其相邻的元素成为新的栈顶元素
栈常见操作
push:添加一个新的元素到栈顶位置
pop():移除栈顶元素,同时返回被移除的元素
peek():返回栈顶的元素,不对栈做任何修改(这个方法不会移除栈顶的元素,仅仅返回它)
isEmpty():如果栈里没有任何元素就返回true,否则返回false
size():返回栈里的元素个数,这个方法跟数组的length属性很类似
toString():将栈结构的内容以字符的形式返回
十进制转二进制
function dec2bin(decNumber){
//1.定义栈对象
var stack = new Stack()
//2.循环操作
while (decNumber > 0){
//2.1 获取余数,并且放入到栈中
stack.push(decNumber % 2)
//2.2 获取整除后的结果,作为下一次运行的数字
decNumber = Math.floor(decNumber / 2)
}
//3.从栈中取出0和1
var binaryString = ''
while(!stack.isEmpty()){
binaryString +=stack.pop()
}
return binaryString
}
队列结构
队列,它是一种受限的线性表,先进先出
受限之处在于他只允许在表的前端进行删除操作,在表的后端进行插入操作
队列的应用
打印队列: 在打印时,文档会按照次序放入到打印列表,打印机会一次从队列中取出文档,优先放入文档,优先被取出,以此类推
线程队列: 在开发中,为了让任务可以并行处理,通常会开启多个线程,但是我们不能让大量的线程同时运行处理任务(占用过多的资源),这时候处理我们就会使用线程队列,依照次序启动线程,并且处理对应的任务
队列类的创建
队列的实现和栈一样,有两种方案:1.基于数组实现,2.基于链表实现
队列的常见操作
enqueue:向队列尾部添加一个(或多个)新的项
dequeue():移除队列的第一个(即排在队列最前面的)项,并返回被移除的元素
front():返回队列中第一个元素---最先被添加,也将是最先被移除的元素。队列不做任何变动
isEmpty():如果列表里没有任何元素就返回true,否则返回false
size():返回列表里的元素个数,这个方法跟数组的length属性很类似
toString():将列表结构的内容以字符的形式返回
优先级队列
优先级队列,在插入一个元素的时候会考虑该数据的优先级
生活中的例子:
机场登机(头等餐和商务舱乘客的优先级要高于经济舱);急诊(病情严重,一般情况下是按照排序)
链表
链表和数组一样,可以用于存储一系列的元素,但是链表和数组的实现机制完全不同,它是用于存储数据的线性结构
链表类似于火车:有一个火车头,火车头会连接一个节点,节点上有乘客(类似于数据),并且这个节点会连接下一个节点,以此类推
链表的优势
要存储多个元素,另外一个选择就是链表
链表中的元素在内存中不必是连续的空间
链表的每个元素由一个存储元素本身的节点和一个指向下一个元素的引用组成
因此相对于数组,链表有一些优点:
内存空间不是必须连续,可以充分利用计算机的内存,实现灵活的内存动态管理
链表不必在创建时就确定大小,并且大小可以无限的延伸下去
链表在插入和删除数据时,时间复杂度可以达到o(1),相对数组效率高很多
链表的缺点
链表访问任何一个位置的元素时,都需要从头开始访问(无法跳过第一个元素访问任何一个元素)
无法通过下标直接访问元素,需要从头一个个访问,直到找到对应的元素
链表常见操作
append(el):向队列尾部添加一个新的项
insery(position,el):想列表特定位置插入一个新的项
get(position):获取对应位置的元素
indexOf(el):返回元素在列表中的索引。如果列表中没有该元素则返回-1
updata(position):修改某个位置的元素
removeAt(position):从列表的特定位置移除一项
remove(el):从列表中移除一项
isEmpty():如果链表里没有任何元素就返回true,否则返回false
size():返回链表里的元素个数,这个方法跟数组的length属性很类似
toString():由于列表使用了Node类,就需要重写继承自JavaScript对象默认的toString方法,让其只输出元素的值
双向链表
单向链表:
只能从头遍历到尾或者从尾遍历到头
也就是链表相连接的过程是单向的
实现的原理是一个链表中有一个指向下一个的引用
双向链表:
既可以从头遍历到尾,又可以从尾遍历到头
一个节点既有向前连接的引用,也有一个向后连接的引用
缺点:内存空间更大一些
特点:第一个节点的prev是null 最后的节点的next是null
集合
集合通常由一组无序的,不能重复的元素构成
集合常见操作
add(value):向集合添加一个新的值
remove(value):从集合中移除一个值
has(value):如果值在集合中就返回true,否则返回false
clear():移除集合中的所有项
size():返回集合里的元素个数,这个方法跟数组的length属性很类似
values():返回一个包含集合中所有值得数组
字典
字典的主要特点一一对应的关系
哈希表
优点:
可以提供非常快速的插入-删除-查找操作
无论多少数据,插入和删除值需要接近常量的时间:即O(1)的时间级,实际上,只需要几个机器指令即可完成
哈希表的速度比树还要快,基本可以瞬间查找到想要的元素
缺点:
哈希表中的数据是没有顺序的,所以不能以一种固定的方式(比如从小到大)来遍历其中的元素
通常情况下,哈希表中的key是不允许重复的,不能放置相同的key,用于保存不同的元素