伪代码和流程图
逻辑
三段论逻辑
三段论逻辑就是从前两种结论为真的命题中推论出第三个命题,这个过程就叫做三段论逻辑。
譬如:
命题一:JS有7种数据类型:string、number、bool、symbol、underfined、null、object。
命题二:JS的函数不属于前六种类型。
推 论:JS函数属于object类型。
命题一:JS中的所欲函数都是由Function构造的。
命题二:Function、Object、Array是函数。
推 论:Function、Object、Array是由Function构造的。
如何用代码表示逻辑
例子:
输出两个数中较大的数
- 如果第1个数字大于第二个数字,就输出第一个数字
- 否则就输出第二个数字
代码:
这段用伪代码,方便理解,同时伪代码不用兼顾语法的使用细节,更突出如何去想。
a=[1,100]
if(a.get(0)>a.get(1)){
print a.get(0)
}else{
print a.get(1)
}
如果要输出N个数字中最大的数
- 首先找到第1和第2个数字中较大的那个数组,存入Max
- 再将Max与第三个数字的大小做对比,将较大的那个数字存入Max
- 一直到N-1与N作比较,将较大的数字存入Max
- Max就是得到最大的数
a=[1,3,5,6,8,22,67,111]
Max=a[0]
for(i from 1 to a.length()-1){
if a.get(i)>Max then Max=a.get(i)
print Max
}
顺序执行语句
由语句一向语句二按顺序执行
条件判断语句
通过判断条件,如果返回为真,则执行语句一,如果判断为假,则执行语句二
循环语句
进入一个循环语句,设置及一个初始的 i 值与判断条件,判断条件是否满足,如果返回为真,则执行语句一,然后 i=i+1 ,当不满足判断条件是,则执行语句二,跳出循环
流程图和伪代码的好处:1.锻炼你的大脑 2.整理你的思路
流程图的运用
选出两个数较大的数
选出多个数中最大的数
数据结构
数据与数据之间的关系与结构
如何表示两个数据
如果顺序有意义,则
[x,y]表示第一个是x,第二个是y
[y,x]表示第一个是y,第二个是x
比如坐标就是这样的数据
需要提供first和last操作
如果顺序无意义,则
(x,y)和(y,x)一样
比如血压值(120,80)和(80,120)没区别
不需要提供first和last操作
如何表示N个数据
如果顺序有意义,则
数组表示[a1,a2...aN]
要提供索引操作get(i)
要提供add/indexOf/delete操作
如果顺序无意义,则
集合表示{a1,a2...aN}
要提供add/delete/has操作
如何表示N对N数据
比如学号
用哈希表表示
hash{10001="小红",10002=>"小兰"}
哈希表与JavaScript中的对象并不相同,只是形式相似,JavaScript中对象的key只能是字符串,而哈希表中的key可以是字符串,数字,甚至是对象。且对象具有原型,哈希表没有
min的实现
找出两个数字中较小的那个一个(minOf2)
let minOf2 = (numebrs) => {
if (numbers[0] < number[1]) {
return numbers[0];
} else {
return numbers[1];
}
};
//优化代码
let minOf2 = (numbers) => (numebrs[0] < numbers[1] ? numbers[0] : numbers[1]);
//再优化代码
let minOf2 = ([a, b]) => (a < b ? a : b-- - 析构赋值);
JavaScript内置了Math.min
- Math.min(1,2) // 1
- Math.min.call(null,1,2)
- Math,min.apply(null,[1,2])
关于Math:Math看起来像object一样是构造函数,实际上Math只是一个普通函数。
找出多个数字中较小的那个一个(minOf2)
三个数字中找到最小的那一个
let minOf3 = ([a, b, c]) => {
return minOf2(a, minOf2([b, c]));
};
以此类推,如果在四个数字中找到最小的那个则可以写成:
let minOf4 = ([a, b, c, d]) => {
return minOf2(a, minOf3([b, c, d]));
};
N个数字中找到最小的那一个
let min = (numbers) => {
if (numbers.lenght > 2) {
return min([numbers[0], min(numbers.slice(1))]);
} else {
return Math.min.apply(null, numbers);
}
};
递归
特点:函数不停的调用自己,每次调用的参数略有不同
排序算法
长度为2的数组排序
let sort2 = ([a, b]) => {
if (a < b) {
return [a, b];
} else {
return [b, a];
}
};
//优化代码
let sort2 = ([a, b]) => (a < b ? [a, b] : [b, a]);
长度为3的数组排序
let minIndex = (numbers) => {
numbers.indexOf(min(numbers));
};
let sort3 = (numbers) => {
let index = minIndex(numbers);
let min = numbers[index];
numbers.splice(index, 1);
return [min].concat(sort2(numbers));
};
以此类推,如果四个数字排序则可以写成:
let sort4 = (numbers) => {
let index = minIndex(numbers);
let min = numbers[index];
numbers.splice(index, 1);
return [min].concat(sort3(numbers));
};
任意长度的数组排序
let sort = (numbers) => {
if (numbers.length > 2) {
let index = minIndex(numbers);
let min = numbers[index];
numbers.splice(index, 1);
return [min].concat(sort(numbers));
} else {
return numbers[0] < numbers[1] ? numbers : numbers.reverse();
}
};
minIndex重写
let minIndex = (numbers) => {
let index = 0;
for (let i = 1; i < numbers.length; i++) {
if (numbers[i] < numbers[index]) {
index = i;
}
}
return index;
};
用循环的思路重写sort
let swap =(array,i,j)=>{
let temp = array[i]
array[i] = array [j]
array[j] = temp
}
let minIndex=(numbers)=>{
let index = 0
for(let i=1;i<numbers.length;i++){
if(numbers[i]<numbers[index]){
index=i
}
}
return index
}
let sort =(numbers)=>{
for(let i = 0 ;i<numbers.length-1;i++){
let index =minIndex(numbers.slice(i))+i
if(index!=i){swap(numbers,index,i)}
}
return numbers
}
快速排序
let quickSort = (arr) => {
if (arr.length <= 1) {
return arr;
}
let pivotIndex = Math.floor(arr.length / 2);
let pivot = arr.splice(pivotIndex, 1)[0];
let left = [];
let right = [];
for (let 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));
};
归并排序
let mergeSort = (arr) => {
if (arr.length === 1) {
return arr;
}
let left = arr.slice(0, Math.floor(arr.length / 2));
let right = arr.slice(Math.floor(arr.length / 2));
return merge(mergeSort(left), mergeSort(right));
};
let merge = (a, b) => {
if (a.length === 0) {
return b;
}
if (b.length === 0) {
return a;
}
return a[0] < b[0]?
a[0].concat(merge(a.slice(1), b)): b[0].concat(merge(a, b.slice(1)));
};
计数排序
let countSort = (arr) => {
let hashTable = {},
max = 0,
result = [];
for (let i = 0; i < arr.length; i++) {
if (!(arr[i] in hashTable)) {
hashTable[arr[i]] = 1;
} else {
hashTable[arr[i]] += 1;
}
}
if (arr[i] > max) {
max = arr[i];
}
for (let j = 0; j <= max; j++) {
if (j in hashTable) {
for (let i = 0; i < hashTable[j]; i++) {
result.push(j);
}
}
}
return result;
};
数据结构
队列 Queue
先进先出的数组
实现一个餐厅叫号的网页
- 点击【取号】生成一个号码
- 点击按钮【叫号】显示请xxx号就餐
栈 Stack
后进先出的数组
- JavaScript函数的调用栈call Stack就是一个栈
- 假设f1调用了f2,f2又调用了f3
- 那么f3结束后应该回到f2,f2结束后应该回到f1
- 压栈 push 弹栈pop
链表
let array = [1,2,3]
array.proto === Array.prototype
Array.prototype.proto === Object.prototype
从这个角度看对象就是链表
const createList = (value) => {
return createNode(value);
};
const appendList = (list, value) => {
const node = createNode(value);
let x = list;
while (x.next) {
x = x.next;
}
x.next = node;
return node;
};
const createNode = (value) => {
return {
data: value,
next: null,
};
};
const removeFromList = (list, node) => {
let x = list;
let p = node;
while (x !== p && x !== null) {
p = x;
x = x.next;
}
if (x === null) {
return false;
} else if (x === p) {
p = x.next;
return p;
} else {
x.next = p.next;
return list;
}
};
const travelList = (list, fn) => {
let x = list;
while (x !== null) {
fn(x);
x = x.next;
}
};
哈希表 kay-value pairs
场景
假设哈希表hash里有一万对key-value
比如 name:'Zhoujia _ 22',age:18....
如何使得读取hash['xxx']速度最快
解决办法
不做任何优化,hash['xxx']需要遍历所有key,O(n)
对key排序,使用二分法查找,O(log2 n)
用字符串对应的ASCⅡ数字做索引O(1)
对索引做除法取余数O(1)
冲突了怎么办,冲突了就顺延
树
实际使用
中国的省市区,可以看成一棵树
公司的层级结构,可以看成一棵树
网页中的节点,可以看成一棵树
const createTree = (value) => {
return {
data: value,
children: null,
parent: null,
};
};
const addChild = (node, value) => {
const newNode = {
data: value,
children: null,
parent: node,
};
node.children = node.children || [];
node.children.push(newNode);
return newNode;
};
const travel = (tree, fn) => {
fn(tree);
if (!tree.children) {
return tree;
}
for (let i = 0; i < tree.children.length; i++) {
travel(tree.children[i], fn);
}
};
const find = (tree, node) => {
if (tree === node) {
return tree;
} else if (tree.children) {
for (let i = 0; i < tree.children.length; i++) {
const result = find(tree.children[i], node);
if (result) {
return result;
}
}
return undefined;
} else {
return undefined;
}
};
const removeNode = (tree, node) => {
const siblings = node.parent.children;
let index = 0;
for (let i = 0; i < siblings.length; i++) {
if ((siblings[i] = node)) {
index = i;
}
}
siblings.splice(index, 1);
};