学习算法想要深入的话,必须要学习数据结构,无奈本科学过现在忘的差不多,只能花了一天时间来总结一下。想看的时候再来看一下
1 入门:算法初级
• 排序算法列表 https://zh.wikipedia.org/wiki/%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95#排序算法列表
• 冒泡排序 http://bubkoo.com/2014/01/12/sort-algorithm/bubble-sort/
• 插入排序 http://bubkoo.com/2014/01/14/sort-algorithm/insertion-sort/
• 桶排序 http://bubkoo.com/2014/01/15/sort-algorithm/bucket-sort/
• 其他排序:http://bubkoo.com/tags/algorithm/
2 伪代码与流程图
3 结构化编程
https://zh.wikipedia.org/zh-hans/%E7%BB%93%E6%9E%84%E5%8C%96%E7%BC%96%E7%A8%8B
- 一行一行执行
- 有条件控制语句 if…else…
- 有循环控制语句 while(exp) do…
什么是数据结构
就是数据的结构。
一般来说是这样的: - 我们要解决一个跟数据相关的问题
- 分析这个问题,想出对应的数据结构
- 分析数据结构,想出算法
数据结构和算法是互相依存、不可分开的
你学习完排序算法,就能了解常见的数据结构
大分类
• 分治法:把一个问题分区成互相独立的多个部分分别求解的思路。这种求解思路带来的好处之一是便于进行并行计算。
• 动态规划法:当问题的整体最优解就是由局部最优解组成的时候,经常采用的一种方法。
• 贪婪算法:常见的近似求解思路。当问题的整体最优解不是(或无法证明是)由局部最优解组成,且对解的最优性没有要求的时候,可以采用的一种方法。
• 线性规划法:见词条。
• 简并法:把一个问题通过逻辑或数学推理,简化成与之等价或者近似的、相对简单的模型,进而求解的方法。
我们前端主要使用分治法——分而治之。
排序算法
中国学生学不好排序算法主要是因为这些算法的名字是外国人取的 - 体育委员两两摸头法(冒泡排序)
- 体育老师一指禅法(选择排序)
- 起扑克牌法(插入排序)
- 强迫症收扑克牌法(基数排序)
- 快排(可选择随机排序加快速度)
- 归并排序
- 堆排序
排序可视化:https://visualgo.net/bn/sorting
2 数据结构
- 哈希(Hash)
• 计数排序中的桶(复杂度 O(n+max),比快排还快
• 桶排序 (http://bubkoo.com/2014/01/15/sort-algorithm/bucket-sort/)与计数排序的区别
• 基数排序(http://bubkoo.com/2014/01/15/sort-algorithm/radix-sort/) 与计数排序的区别 - 队列(Queue)
• 先进先出
• 可以用数组实现
• 举例:排队 - 栈(Stack)
• 先进后出
• 可以用数组实现
• 举例:盗梦空间 - 链表(Linked List)
• 数组无法直接删除中间的一项,链表可以
• 用哈希(JS里面用对象表示哈希)实现链表
• head、node 概念 - 树(tree)
• 举例:层级结构、DOM
• 概念:层数、深度、节点个数
• 二叉树(https://zh.wikipedia.org/wiki/%E4%BA%8C%E5%8F%89%E6%A0%91)
• 满二叉树
• 完全二叉树
• 完全二叉树和满二叉树可以用数组实现
• 其他树可以用哈希(对象)实现
• 操作:增删改查
• 堆排序用到了 tree
• 其他:B 树(https://zh.wikipedia.org/wiki/B%E6%A0%91)、红黑树(https://zh.wikipedia.org/wiki/%E7%BA%A2%E9%BB%91%E6%A0%91)、AVL树(https://zh.wikipedia.org/wiki/AVL%E6%A0%91)
堆排序可视化:https://www.cs.usfca.edu/~galles/visualization/HeapSort.html
堆排序JS代码完整讲解(看到最后):http://bubkoo.com/2014/01/14/sort-algorithm/heap-sort/
上面的网址不稳定,打不开了,还是写到这篇文章里吧。
一、冒泡排序
大致分两步:
1、依次对比相邻2个数字,前者比后者大就调换位置
2、重复第一步操作,直到所有数字都按顺序排列
function bubbleSort(arr){
for(var i=1; i<arr.length; i++){
for(var j=0; j<arr.length-i; j++){
if(arr[j]>arr[j+1]){
var temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
return arr;
}
二、快速排序
大致分三步:
1、找基准(一般是以中间项为基准)
2、遍历数组,小于基准的放在left,大于基准的放在right
3、递归
function quickSort(arr){
//如果数组<=1,则直接返回
if(arr.length<=1){return arr;}
var pivotIndex=Math.floor(arr.length/2);
//找基准,并把基准从原数组删除
var pivot=arr.splice(pivotIndex,1)[0];
//定义左右数组
var left=[], right=[];
//比基准小的放在left,比基准大的放在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));
}
三、插入排序(对于少量元素比较有效)
原理:像排序一手扑克牌,开始时,我们的左手为空并且桌子上的牌面向下。然后,我们每次从桌子上拿走一张牌并将它插入左手中正确的
位置。为了找到一张牌的正确位置,我们从右到左将它与已在手中的每张牌进行比较,如图2-1所示。拿在左手上的牌总是排序好的,原来这些牌是桌子上牌堆中顶部的牌。
手上的牌是有序数列,桌子上的牌是无序数列。
function insertSort(arr){
//从第二个数开始,依次插入
for(var i=1; i<arr.length; i++){
//判断目标元素是否小于前一个元素
if(arr[i]<arr[i-1]){
var current=arr[i];
var j=i-1;
//从有序数列从后往前对比,如果目标元素小于与之对比的当前元素,当前元素位置往后挪一位
while(j>=0 && current<arr[j]) {
arr[j+1]=arr[j];
j--;
}
//插入
arr[j+1]=current;
}
}
return arr;
}
插入排序另一种写法(个人感觉还是这种效率快)
function insertSort(arr) {
for(let i=1; i<arr.length; i++) {
if(arr[i] < arr[0]) {
arr.unshift(arr.splice(i,1)[0]);
}else {
for(let j=i-1; j>=0; j--) {
if(arr[i] > arr[j]) {
let current = arr.splice(i,1)[0];
arr.splice(j+1,0,current);
break;
}
}
}
}
return arr;
}