写在前面
改变原始数组
- 斐波那契
function Fibonacci(n) {
if (n==1 || n == 2){
return 1
}
return Fibonacci(n-1)+Fibonacci(n-2)
}
console.log(Fibonacci(30))
//非递归方法
function Fibonacci(num){
var n1 = 1, n2 = 1 , n= 1
for(var i = 2; i < num; i++){
n = n1 + n2
n1 = n2
n2 = n
}
return n
}
0 字符串
var str = 'hello, july'
var a
a = str.length//11
a = str[0]//h
a = str.concat('hi','cool')//hello, julyhicool
a = str[0]//h
a = str.indexOf('h')//0, 如果没有就是 -1
a = str.lastIndexOf('h')
a = str.slice(0,2)//he
a = Array.isArray(a)//true
a = str.toUpperCase()//HELLO, JULY
a = str.toLowerCase()//hello, july
//字符串变数组
a = str.split(',')//[ 'hello', ' july' ]
a = str.split('')//['h', 'e', 'l', 'l', 'o', ',', ' ', 'j', 'u', 'l', 'y']
//数组变字符串
a = a.join('')//hello, july
a = a.toString()//hello, july
1 数组
var n = [1,23,4,45,345,2,1]
n.push(11)
n.push(14,24)
n.unshift(-2)//在首位添加
n.pop()
n.shift()//从首位删除
console.log(n.splice(1,3))
var n= b.concat(a,c)
let ncopy = Array.of(...n)
let one = Array(6).fill(1)
console.log(num.reverse())
console.log(num.sort())
console.log(n.indexOf(2))
console.log(n.includes(999))
console.log(n.toString())
var b= n.join('-')
获取数组中重复的数和次数
目标参数若是字符串,可通过split()方法转换为数组
var str="qwertyuiopasdfghjklzxcvbnmqazwsxaswazaaa";
var arr=str.split(""); // 转换为数组
function moreValue() {
if (!arr) return false;
if (arr.length === 1) return 1;
let result = {}
let maxNum = 0;//元素出现的次数
let maxValue = null;//最大的对应的maxValue值
// 循环对象,取出value值最大的对应的maxValue值
for(let i = 0; i < arr.length;i++) {
let val = arr[i]
// 先循环数组,把元素作为key值,元素出现的次数为value值,塞进result对象中
//循环数组塞进对象的操作用三元表达式判断,合并为一个for循环
result[val] === undefined ? result[val] = 1 : result[val]++;
if(result[val] > maxNum) {
maxNum = result[val];
maxValue = val
}
}
return maxValue +','+ maxNum;
}
数组去重(三种方法)
function unique(arr) {
var a = []
a[0] = arr[0]
for (let i = 0; i < arr.length; i++) {
for (let k = 0; k < a.length; k++) {
if (a[k] == arr[i]) {
break
}
if (k == a.length-1) {
a.push(arr[i])
}
}
}
return a
}
数组拍平
function fn(arr) {
var arr1 = []
arr.forEach(val =>{
if ( val instanceof Array) {
arr1 = arr1.concat(fn(val))
} else {
arr1.push(val)
}
})
return arr1
}
输入二维数组和一个整数,判断二维数组中是否含有该整数
const arr = [1,5,9;3,8,12;6,9,19]; function hasNumber(array,target){}
解法 1:暴力法 遍历数组中的所有元素,找到是否存在。
时间复杂度是 O(N^2),空间复杂度是 O(1)
function Find(target, array) {
const rowNum = array.length;
if (!rowNum) {
return false;
}
const colNum = array[0].length;
for (let i = 0; i < rowNum; i++) {
for (let j = 0; j < colNum; j++) {
if (array[i][j] === target) return true;
}
}
return false;
}
解法 2:观察数组规律
按照题目要求,数组的特点是:每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。考虑以下数组:
1 2 3
4 5 6
7 8 9
在其中寻找 5 是否存在。过程如下:
从右上角开始遍历当前元素小于目标元素(3 < 5),根据数组特点,当前行中最大元素也小于目标元素,因此进入下一行当前元素大于目标元素(6 > 5),根据数组特点,行数不变,尝试向前一列查找找到 5
时间复杂度是 O(M+N),空间复杂度是 O(1)。其中 M 和 N 分别代表行数和列数。
function Find(target, array) {
const rowNum = array.length;
if (!rowNum) {
return false;
}
const colNum = array[0].length;
if (!colNum) {
return false;
}
let row = 0,
col = colNum - 1;
while (row < rowNum && col >= 0) {
if (array[row][col] === target) {
return true;
} else if (array[row][col] > target) {
--col;
} else {
++row;
}
}
return false;
}
两个数组的交集和并集
- 对 Array 进行扩展
//数组功能扩展
//数组迭代函数
Array.prototype.each = function(fn){
fn = fn || Function.K;
var a = [];
var args = Array.prototype.slice.call(arguments, 1);
for(var i = 0; i < this.length; i++){
var res = fn.apply(this,[this[i],i].concat(args));
if(res != null) a.push(res);
}
return a;
};
//数组是否包含指定元素
Array.prototype.contains = function(suArr){
for(var i = 0; i < this.length; i ++){
if(this[i] == suArr){
return true;
}
}
return false;
}
//不重复元素构成的数组
Array.prototype.uniquelize = function(){
var ra = new Array();
for(var i = 0; i < this.length; i ++){
if(!ra.contains(this[i])){
ra.push(this[i]);
}
}
return ra;
};
//两个数组的交集
Array.intersect = function(a, b){
return a.uniquelize().each(function(o){return b.contains(o) ? o : null});
};
//两个数组的差集
Array.minus = function(a, b){
return a.uniquelize().each(function(o){return b.contains(o) ? null : o});
};
//两个数组的补集
Array.complement = function(a, b){
return Array.minus(Array.union(a, b),Array.intersect(a, b));
};
//两个数组并集
Array.union = function(a, b){
return a.concat(b).uniquelize();
};
2 filter 它用于把Array的某些元素过滤掉,然后返回剩下的元素。
和map()类似,Array的filter()也接收一个函数。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是true还是false决定保留还是丢弃该元素。
回调函数
filter()接收的回调函数,其实可以有多个参数。通常我们仅使用第一个参数,表示Array的某个元素。回调函数还可以接收另外两个参数,表示元素的位置和数组本身:
var a = [1,2,3,4,5]
var b = [2,4,6,8,10]
//交集
var intersect = a.filter(function(v){ return b.indexOf(v) > -1 })
//差集
var minus = a.filter(function(v){ return b.indexOf(v) == -1 })
//补集
var complement = a.filter(function(v){ return !(b.indexOf(v) > -1) })
.concat(b.filter(function(v){ return !(a.indexOf(v) > -1)}))
//并集
var unionSet = a.concat(b.filter(function(v){ return !(a.indexOf(v) > -1)}));
console.log("a与b的交集:", intersect);
console.log("a与b的差集:", minus);
console.log("a与b的补集:", complement);
console.log("a与b的并集:", unionSet);
合并两个数组并排序
- 合并两个数组并排序
var a =[2,5,8,9];
var b=[7,9,7,9]
var c = a.concat(b).sort(function(a,b){return a-b }//升序
//回调函数里面返回值如果是:参数1-参数2;升序;
- 两个有序数组,合并后重新排序js实现
利用两个数组已经排好序这个条件,设置两个指针,分别指向两个数组
当其中一个小于另外一个就将小的数push到新数组中,后移指针
相等的话则全push到新数组中,两个指针全后移
直到一个指针指到数组结尾,将另一个数组直接加入到新数组中即可
let sortArr = (arr1, arr2) => {
let [i,j] = [0,0];
let newArr = [];
while (i < arr1.length && j < arr2.length) {
if (arr1[i] < arr2[j]) {
newArr.push(arr1[i]);
i++;
} else if (arr1[i] > arr2[j]) {
newArr.push(arr2[j]);
j++;
} else if (arr1[i] === arr2[j]) {
newArr.push(arr1[i]);
newArr.push(arr2[j]);
i++, j++;
}
}
// 将指针未移到末尾的部分取出,拼到新数组后面
if (i < arr1.length) {
return newArr.concat(arr1.splice(i));
} else if (j < arr2.length) {
return newArr.concat(arr2.splice(j));
} else {
return newArr;
}
};
let arr1 = [1, 2, 3, 4, 6, 9, 11];
let arr2 = [2, 4, 6, 8, 12, 19, 33, 45];
console.log(sortArr(arr1, arr2));
数组的反转
//反转数组
function reverse(arr) {
for (let i = 0; i < arr.length/2; i++) {
[arr[i],arr[arr.length-1-i]]=[arr[arr.length-1-i],arr[i]]
}
return arr
}
对数组的遍历有那些api、迭代器函数 filter() forEach()some() every() map()
- filter()
// 对数组中每一项运行回调函数,该函数返回结果是true的项组成的新数组
// 新数组是有老数组中的元素组成的,return为ture的项;
例:
var arr = [111,222,333,444,555];
var newArr = arr.filter(function (element, index, array) {
//只要是奇数,就组成数组;(数组中辨别元素)
if(element%2 === 0){
return true;
}else{
return false;
}
})
console.log(newArr); // [222, 444]
- forEach()
// 和for循环一样;没有返回值;
例:
var arr = [111,222,333,444,555];
var sum = 0;
var aaa = arr.forEach(function (element,index,array) {
console.log(element); // 输出数组中的每一个元素
console.log(index); // 数组元素对应的索引值
console.log(array); // 数组本身 [111, 222, 333, 444, 555]
sum += element; //数组中元素求和;
});
console.log(sum); // 数组元素加起来的和
console.log(aaa);//undefined;没有返回值 所以返回undefined
- some 与every some 会迭代数组中每个元素,直到函数返回true every 会迭代数组中每个元素,直到函数返回false
var isEven = function(x){return (x%2 == 0)}
var isEven =(x) => (console.log( x%2 == 0))
var numbers = [2,4,6,3]
numbers.some(isEven)
numbers.every(isEven)
- map()
// 对数组中每一项运行回调函数,返回该函数的结果组成的新数组
// return什么新数组中就有什么; 不return返回undefined; 对数组二次加工
例:
var arr = [111,222,333,444,555];
var newArr = arr.map(function (element, index, array) {
if(index == 2){
return element; // 这里return了 所以下面返回的值是333
}
return element*100; // 返回的元素值都乘上100后的值
})
console.log(newArr); // [11100, 22200, 333, 44400, 55500]
实现sum函数(闭包):
sum(1)(2)() 输出 3; sum(1)(2)(3)(4)() 输出10;
指的是将一个接受多个参数的函数 变为 接受一个参数返回一个函数的固定形式,这样便于再次调用,例如 实现add(1)(2)(3)(4)=10; 、 add(1)(1,2,3)(2)=9;
function sum() {
const _args = [...arguments];
function fn() {
_args.push(...arguments);
return fn;
}
fn.toString = function() {
return _args.reduce((sum, cur) => sum + cur);
}
return fn;
}
解析url参数
function GetRequest(url) {
if (typeof url == "undefined") {
var urla = decodeURI(location.search)//获取url中"?"符后的字符串
} else {
var urla = "?" + url.split("?")[1]
}
var request = new Object()
if (urla.indexOf("?") != -1){
var str = urla.substr(1)
strs = str.split("&")
for (let i = 0; i < strs.length; i++) {
request[strs[i].split("=")[0]] = decodeURI(strs[i].split("=")[1])
}
}
return request
}
var parms_2 = GetRequest('http://htmlJsTest/getrequest.html?uid=admin&rid=1&fid=2&name=小明');
console.log(parms_2); // {"uid":"admin","rid":"1","fid":"2","name":"小明"}
字符串数组中的最长公共前缀
function longestCommonPrefix(string) {
if (!string.length){
return ''
}
if (string.length === 1) {
return string[0]
}
string.sort()
let first = string[0]
let end = string[string.length -1]
let result = ''
for (let i = 0; i < first.length; i++) {
if (first[i] === end[i]) {
result += first[i]
} else {
break
}
}
return result
}
var a = ["abca","abc","abca","abc","abcc"]
console.log(longestCommonPrefix(a))
找最大值(5种方法)
var arr = [23,5,6,2,1]
// ES6
var a = Math.max(...arr)
// ES5
var a = Math.max.apply(null,arr)
//sort
a= arr.sort((num1,num2) =>{
return num1 - num2 >0
})
arr[0]
//reduce
a = arr.reduce((num1,num2 )=>{
return num1>num2 ? num1:num2
})
// for
let max= arr[0]
for (let i = 0; i < arr.length -1; i++) {
max = max > arr[i+1]?max:arr[i+1]
}
console.log(a)
2 排序和搜索算法
冒泡排序 O(n2)
function bubbleSort(array) {
for (let i = 0; i < array.length; i++) {
for (let j = 0; j < array.length -1; j++) {
if (array[j] > array[j +1]) {
[array[j],array[j+1]] = [array[j+1],array[j]]
}
}
}
return array
}
// 改进冒泡
function modifyBubbleSort(array) {
var n=array.length
for (let i = 0; i < n; i++) {
for (let j = 0; j < n-1-i; j++) {
if (array[j] > array[j+1]) {
[array[j],array[j+1]] = [array[j+1],array[j]]
}
}
}return array
}
var arr = [3,1,5,6,2]
console.log(bubbleSort(arr))
选择排序 O(n2)
function selectSort(array) {
var indexMin,temp, n=array.length
for (let i = 0; i < n-1; i++) {
indexMin = i
for (let j = i+1; j < n; j++) {
if (array[indexMin] > array[j]) {
indexMin = j
}
}
temp = array[i]
array[i]= array[indexMin]
array[indexMin]=temp
}
return array
}
插入排序O(n2)
function insertSort(array) {
var n =array.length,j,temp
for (let i = 0; i < n; i++) {
j = i
temp = array[i]
while (j > 0 && array[j -1]>temp){
array[j]=array[j-1]
j--
}
array[j] = temp
}
return array
}
归并排序O(nlogn)
function mergeSort(arr) {
const length = arr.length;
if (length === 1) { //递归算法的停止条件,即为判断数组长度是否为1
return arr;
}
const mid = Math.floor(length / 2);
const left = arr.slice(0, mid);
const right = arr.slice(mid, length);
return merge(mergeSort(left), mergeSort(right)); //要将原始数组分割直至只有一个元素时,才开始归并
}
function merge(left, right) {
const result = [];
let il = 0;
let ir = 0;
//left, right本身肯定都是从小到大排好序的
while( il < left.length && ir < right.length) {
if (left[il] < right[ir]) {
result.push(left[il]);
il++;
} else {
result.push(right[ir]);
ir++;
}
}
//不可能同时存在left和right都有剩余项的情况, 要么left要么right有剩余项, 把剩余项加进来即可
while (il < left.length) {
result.push(left[il]);
il++;
}
while(ir < right.length) {
result.push(right[ir]);
ir++;
}
return result;
}
console.log(mergeSort([2,9,1,8,3,]))
快速排序 O(nlogn)最差情况O(n2)
//1 、随机选择数组中的一个数A,以这个数为基准;
// 2、其他数字跟这个数进行比较,比这个数小的放在其左边,大的放在其右边;
// 3、经过一次循环之后,A左边为小于A的,右边为大于A的;
// 4、这时候将左边和右边的数再递归上面的过程。
function 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))
}
console.log(quickSort([1,4,5,6,2]))
顺序搜索O(n2)和二分搜索 O(logn)(提前排好序)
// 顺序搜索
function search(array,item) {
for (let i = 0; i < array.length; i++) {
if (item === array[i]){
return i
}
}
return -1
}
var arr = [3,1,5,6,2]
console.log(search(arr,2))
//二分搜索
function binarySearch(array,item) {
var low = 0,
high = array.length -1,
mid,element
while (low <= high){
mid = Math.floor((low+high)/2)
element = array[mid]
if (element <item) {
low = mid+1
} else if (element >item) {
high = mid -1
} else {
return mid
}
}
return -1
}
var arr = [1,2,3,4,5]
console.log(binarySearch(arr,2))
2 栈(后进先出)
es5
function Stack() {
let items = []
this.push = function (element) {
items.push(element)
}
this.pop = function () {
return items.pop()
}
this.peek =function () {
return items[items.length-1]
}
this.isEmpty =function () {
return items.length == 0
}
this.size = function () {
return items.length
}
this.clear = function () {
items = []
}
this.print = function () {
console.log(items.toString())
}
}
es6
class Stack {
constructor() {
this.item = []
}
push(element){
this.item.push(element)
}
pop(){
this.item.pop()
}
peek(){
return this.item[this.item.length-1]
}
isEmpty(){
return this.item.length==0
}
size(){
return this.item.length
}
}
let stack = new Stack()
console.log(stack.isEmpty())
stack.push(1)
stack.push(4)
stack.push(32)
console.log(stack.peek())
stack.push(99)
console.log(stack.size())
console.log(stack.isEmpty())
stack.pop()
stack.pop()
console.log(stack.size())
stack.print()
3 队列(先进先出)
es5
function Queue() {
let items = []
this.enqueue = function(element){
items.push(element)
}
this.dequeue = function () {
items.shift()
}
this.front = function () {
return items[0]
}
this.isEmpty =function () {
return items.length == 0
}
this.size = function () {
return items.length
}
this.print = function () {
console.log(items.toString())
}
}
es6
let Queue = (function () {
const items = new WeakMap()
class Queue2 {
constructor() {
items.set(this,[])
}
enqueue(element){
let q = items.get(this)
q.push(element)
}
dequeue(){
let q = items.get(this)
let r = q.shift()
return r
}
size(){
let q = items.get(this)
return q.length
}
isEmpty(){
let q = items.get(this)
return q.length == 0
}
front(){
let q = items.get(this)
return q[0]
}
print(){
let q = items.get(this)
console.log(items.toString())
}
}
return Queue2
})();
let queue = new Queue()
console.log( queue.isEmpty())
queue.enqueue('ll')
queue.enqueue('ss')
queue.enqueue('qq')
queue.print()
console.log(queue.size())
console.log(queue.isEmpty())
queue.dequeue()
queue.dequeue()
queue.print()
优先队列
function PriorityQueue() {
let items = []
function QueueElememt(element,priority) {
this.elements = element
this.priority = priority
}
this.enqueue = function (element,priorty) {
let queueElememt = new QueueElememt(element,priorty)
let added = false
for (let i = 0; i < items.length; i++){
if (queueElememt.priority < items[i].priority) {
items.splice(i,0,queueElememt)
added = true
break
}
}
if (!added){
items.push(queueElememt)
}
}
this.print =function () {
for (let i = 0; i < items.length; i++) {
console.log(`${items[i].elements}-${items[i].priority}`)
}
}
}
let pq = new PriorityQueue()
pq.enqueue('jack',3)
pq.enqueue('sam',2)
pq.enqueue('lucy',2)
pq.enqueue('tim',1)
pq.print()
循环队列-击鼓传花
function Queue() {
let items = []
this.enqueue = function(element){
items.push(element)
}
this.dequeue = function () {
items.shift()
}
this.size = function () {
return items.length
}
}
function f(nameList ,num) {
let queue =new Queue()
for (let i = 0; i < nameList.length; i++) {
queue.enqueue(nameList[i])
}
let eliminated = ''
while (queue.size ()>1){
for (let i = 0; i <num; i++) {
queue.enqueue(queue.dequeue())
}
eliminated = queue.dequeue()
console.log(eliminated ,'quit')
}
return queue.dequeue()
}
let names = ['a','v','d','s','q','e','t','u']
let winner = f(names,7)
console.log(winner)
4 链表
function LinkedList() {
let Node =function (element) {
this.element =element
this.next = null
}
let length = 0
let head = null
this.append = function (element) {
let node = new Node(element),
current
if (head === null){
head = node
}else {
current=head
while(current.next){
current = current.next
}
current.next = node
}
length++
}
this.insert = function (position,element) {
if (position >= 0 && position <= length) {
let node = new Node(element),
current = head,
previous,
index = 0
if (position === 0) {
node.next = current
head = node
} else {
while (index++ <position){
previous = current;
current = current.next
}
node.next = current
previous.next = node
}
length++
return true
} else {
return false
}
}
this.removeAt = function (position) {
if (position >= 0 && position <length){
let current = head,
previous, index = 0
if (position === 0) {
head = current.next
}else {
while (index++ <position){
previous = current
current = current.next
}
previous.next= current.next
}
length--
return current.element
}else {
return null
}
}
this.indexOf = function (element) {
let current = head,
index = -1
while (current){
if (element = current.element) {
return index
}
index++
current = current.next
}
return -1
}
this.remove = function (element) {
let index = this.indexOf(element)
return this.removeAt(index)
}
this.isEmpty = function () {
return length === 0
}
this.size =function () {
return length
}
this.getHead = function () {
return head
}
this.toString = function () {
let current = head,str = ''
while (current){
str +=current.element +(current.next ? 'n':'')
current = current.next
}
return str
}
this.print = function () {
console.log(Node.toString())
}
}
let list = new LinkedList();
list.append(15)
list.append(20)
console.log(list.indexOf(20))
console.log(list.insert(2,99))
console.log(list.isEmpty())
console.log(list.removeAt(3))
console.log(list.toString())
链表反转(利用递归实现)
思路 递归的基线条件:遍历到末节点(node.next === null) 递归的递归条件:node.next !== null 当遇到末节点时,返回末节点,前一节点接收末节点,并把末节点的next设置为自身,返回前一节的,继续下去 考虑特殊情况:undefined和null
function reverseList(head){
// 闭包
if (head === undefined || head === null) return null
var reverHead
var origHead = head
var re = function (head) {
if (head.next === null) {
reverHead = head
return head
} else {
var node = reverse(head.next)
node.next = head
if (origHead === head) {
head.next = null
return reverHead
} else {
return head
}
}
}
return re(head)
}
双向链表
function DoubleList() {
let Node = function (element) {
this.element = element
this.prev = null
this.next = null
}
let length = 0
let head = null
let tail = null
this.insert = function (position, element) {
if (position >= 0 && position <= length) {
let node = new Node(element),
current = head,
previous,
index = 0
if (position === 0) {
if (!head) {
head = node
tail = node
} else {
node.next = current
current.prev = node
head = node
}
} else if (position === length) {
current = tail
current.next = node
node.prev = current
tail = node
} else {
while (index++ < position) {
previous = current
current = current.next
}
node.next = current
previous.next = node
current.prev = node
node.prev = previous
}
length++
return true
} else {
return false
}
}
this.removeAt = function (position) {
if (position >= 0 && position < length) {
let current = head,
previous,
index = 0
if (length === 1) {
tail = null
} else {
head.prev = null
}
} else if (position === length - 1) {
current = tail
tail = current.prev
tail.next = null
} else {
while (index++ < position) {
previous = current
current = current.next
}
previous.next = current.next
current.next.prev = previous
}
length--
return current.element
}
}
5 集合 Set ES6
const obj = new Set()
//增加
obj.add(1)
obj.add(2)
obj.add(['aa','bbb'])
obj.add(2)
obj.add(5)
console.log(obj)
//判断有无
console.log(obj.has(5))
obj.has(6)
//删除
obj.delete(5)
console.log( obj.delete(6))
console.log(obj)
//遍历
obj.forEach(n => console.log(n))
//总数
console.log(obj.size)
//清除所有元素
console.log(obj.clear())
let set = new Set()
set.add(1)
set.add(3)
set.add(5)
set.add(7)
console.log(set)
console.log(set.values())
console.log(set.size)
console.log(set.has(1))
set.delete(1)
let setA = new Set()
setA.add(1)
setA.add(2)
setA.add(3)
let setB = new Set()
setB.add(4)
setB.add(5)
setB.add(6)
// 并集
let unionAb = new Set()
for (let x of setA) unionAb.add(x)
for (let x of setB) unionAb.add(x)
console.log(unionAb)
//交集
let intersection = function (setA,setB) {
let intersectionSet = new Set()
for (let x of setA) {
if (setB.has(x)) {
intersectionSet.add(x)
}
}
return intersectionSet
}
let interAB = intersection(setA,setB)
//差集
let diff = function (setA, setB) {
let diffSet = new Set()
for (let x of setA) {
if (!setB.has(x)){
diffSet.add(x)
}
}
return diffSet
}
let diffAb = diff(setA,setB)
5.5 Map ES6
const obj2 = new Map()
//增加
obj2.set('one','abc')
console.log(obj2)//Map(1) { 'one' => 'abc' }
obj2.set('two',221)
console.log(obj2)//Map(2) { 'two' => '221', 'abc' => 221 }
//取值
console.log(obj2.get('one'))//abc
console.log(obj2.get('two'))//221
console.log(obj2.get('three'))//undefined
//删除
console.log(obj2.delete('one'))//true
//数量
console.log(obj2.size)//1
//清除所有元素
console.log(obj2.clear())//undefined
console.log(map.has('lida'))
console.log(map.keys())
console.log(map.values())
var weekmap = new WeakMap()
var ob1 = {name:'gad'}
var ob2 = {name: 'san'}
var ob3 = {name:'ll'}
weekmap.set(ob1,'gad@qq.com')
weekmap.set(ob2,'sam@qq.com')
weekmap.set(ob3,'ll@qq.com')
console.log(weekmap.has(ob1))
console.log(weekmap.get(ob3))
weekmap.delete(ob2)
6 字典 和散列表
字典
function Dictionary() {
var items = {}
this.has = function (key) {
return key in items
}
this.set = function (key,value) {
items[key] = value
}
this.delete = function (key) {
if (this.has(key)){
delete items[key]
return true
}
return false
}
this.get = function (key) {
return this.has(key) ? items[key]:undefined
}
this.values = function () {
var values = []
for (let k in items) {
if (this.has(k)) {
values.push(items[k])
}
}
return values
}
this.keys = function () {
return Object.keys(items)
}
this.getItems = function () {
return items
}
}
var dict = new Dictionary()
dict.set('tony','tony@qq.com')
dict.set('som','som@qq.com')
dict.set('jack','jack@qq.com')
dict.set('lily','lily@qq.com')
console.log(dict.has('som'))
console.log(dict.keys())
console.log(dict.values())
console.log(dict.get('lily'))
dict.delete('som')
HashMap(HashTable 散列表)
function HashTable() {
var table = []
//hash 函数 ,是私有方法
var loseCode = function (key) {
var hash = 0
for (let i = 0; i < key.length; i++) {
hash += key.charCodeAt(i)
}
return hash%37
}
this.put = function (key,value) {
var position = loseCode(key)
console.log(position,'-',key)
table[position] =value
}
this.get = function (key) {
return table[loseCode(key)]
}
this.remove = function (key) {
table[loseCode(key)] = undefined
}
}
var hash = new HashTable()
hash.put('lida','lida@qq.com')
hash.put('yould','yould@qq.com')
hash.put('miky','miky@qq.com')
console.log(hash.get('lida'))
console.log(hash.get('llll'))
hash.remove('yould')
//社区中推崇的hash 函数
var djb2HashCode = function (key) {
var hash = 5381
for (let i = 0; i < key.length; i++) {
hash = hash *33 + key.charCodeAt(i)
}
return hash % 1013
}
7 树
BST
//声明结构
function BinarySeacheTree() {
var Node = function (key) {
this.key = key
this.left = null
this.right = null
}
var root = null
this.inset = function (key) {
var newNode = new Node(key)
if (root === null) {
root = newNode
} else {
insertNode(root, newNode)
}
}
var insertNode = function (node,newNode) {
if (newNode.key <node.key) {
if (node.left === null) {
node.left = newNode
} else {
insertNode(node.left,newNode)
}
} else {
if (node.right === null) {
node.right = newNode
} else {
insertNode(node.right,newNode)
}
}
}
//中序遍历
this.inOrderTraverse = function (callback) {
var inOrderNode =function (node,callback) {
if (node !== null){
inOrderNode(node.left,callback)
callback(node.key)
inOrderNode(node.right,callback)
}
}
}
//找最小节点
this.min = function () {
return minNode(root)
}
var minNode = function (node) {
if (node){
while (node && node.left !== null){
node = node.left
}
return node.key
}
return null
}
//找最小节点
this.max = function () {
return maxNode(root)
}
var maxNode = function (node) {
if (node){
while (node && node.right !== null){
node = node.right
}
return node.key
}
return null
}
//搜索特定的值
this.search = function (key) {
return searchNode(root,key)
}
var searchNode = function (node,key) {
if(node === null){
return false
}
if (key < node.key) {
return searchNode(node.left,key)
}else if (key > node.key) {
return searchNode(node.right,key)
} else {
return true
}
}
//移出一个节点
this.remove = function (key) {
root = removeNode(root,key)
}
var removeNode = function (node,key) {
if (node === null) {
return null
}
if (key < node.key) {
node.left = removeNode(node.left,key)
return node
} else {//键=node.key
// 情况一:一个叶节点
if (node.left === null&& node.right === null) {
node = null
return node
}
// 情况二:只有一个子节点的节点
if (node.left === null) {
node = node.right
return node
} else if(node.right === null){
node = node.left
return node
}
// 情况三:有两个子节点的节点
var aux = findMinNode(node.right)
node.key = aux.key
node.right = removeNode(node.right,aux.key)
return node
var findMinNode = function (node) {
while (node && node.left !== null){
node = node.left
}
return node
}
}
}
//前序遍历
this.preOrderTraverse = function (callback) {
var preOrderNode =function (node,callback) {
if (node !== null){
callback(node.key)
preOrderNode(node.left,callback)
preOrderNode(node.right,callback)
}
}
}
//后序遍历
this.postOrderTraverse = function (callback) {
var postOrderNode =function (node,callback) {
if (node !== null){
postOrderNode(node.left,callback)
postOrderNode(node.right,callback)
callback(node.key)
}
}
}
}
var tree = new BinarySeacheTree()
tree.inset(11)
tree.inset(15)
tree.inset(5)
tree.inset(1)
tree.inset(2)
tree.inset(13)
tree.inset(16)
tree.inset(15)
tree.inset(19)
tree.inset(10)
function printNode(value) {
console.log(value)
}
tree.inOrderTraverse(printNode)
9 深度优先算法 & 广度优先算法
const data = [
{
name: 'a',
children: [
{ name: 'b', children: [{ name: 'e' }] },
{ name: 'c', children: [{ name: 'f' }] },
{ name: 'd', children: [{ name: 'g' }] },
],
},
{
name: 'a2',
children: [
{ name: 'b2', children: [{ name: 'e2' }] },
{ name: 'c2', children: [{ name: 'f2' }] },
{ name: 'd2', children: [{ name: 'g2' }] },
],
}
]
// 深度遍历, 使用递归
function getName(data) {
const result = [];
data.forEach(item => {
const map = data => {
result.push(data.name);
data.children && data.children.forEach(child => map(child));
}
map(item);
})
return result.join(',');
}
// 广度遍历, 创建一个执行队列, 当队列为空的时候则结束
function getName2(data) {
let result = [];
let queue = data;
while (queue.length > 0) {
[...queue].forEach(child => {
queue.shift();
result.push(child.name);
child.children && (queue.push(...child.children));
});
}
return result.join(',');
}
console.log(getName(data))
console.log(getName2(data))