├── LICENSE ├── README.md ├── bfsPath.js ├── bfsSearch.js ├── binarySearch.js ├── bubbleSort.js ├── calculation.js ├── dfsCC.js ├── dfsDirectedCycle.js ├── dfsPath.js ├── dfsPrePostSearch.js ├── dfsSearch.js ├── genArr.js ├── heapSort.js ├── insertionSort.js ├── mergeSort.js ├── quickSort.js ├── selectionSort.js └── shellSort.js /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 woniuppp 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # js-algorithm 2 | 学习算法的js实现 ,系统学习一下算法,代码用js实现 3 | 4 | * 排序 5 | - [冒泡](bubbleSort.js) 6 | - [堆排序](heapSort.js) 7 | - [插入排序](insertionSort.js) 8 | - [归并排序](mergeSort.js) 9 | - [选择排序](selectionSrot.js) 10 | - [希尔排序](shellSort.js) 11 | * 查找 12 | - [二分查找](binarySearch.js) 13 | - 查找树 14 | - 红黑树 15 | - 哈希 16 | * 图 17 | - [深度优先遍历所有结点](dfsSearch.js) 18 | - [深度优先查找路径](dfsPath.js) 19 | - [深度优先连通分量](dfsCC.js) 20 | - [广度优先遍历所有结点](bfsSearch.js) 21 | - [广度优先查找路径](bfsPath.js) 22 | - [深度优先寻找有向环](dfsDirectedCycle.js) 23 | - [深度优先前后逆后遍历有向图](dfsPrePostSearch.js) 24 | -------------------------------------------------------------------------------- /bfsPath.js: -------------------------------------------------------------------------------- 1 | // 模拟无向图的arr 深度遍历搜索所有点 2 | var arr = [ 3 | [2,1,5], 4 | [0,2], 5 | [0,1,3,4], 6 | [5,4,2], 7 | [3,2], 8 | [3,0] 9 | 10 | ] 11 | var marked = new Array(arr.length) 12 | var tmp = '' 13 | var edgeTo = new Array(arr.length) 14 | function bfs(n){ 15 | queue = [] 16 | tmp += '\nbfs'+n+'go\n' 17 | marked[n] = true 18 | queue.push(n) 19 | while(queue.length){ 20 | num = queue.shift() 21 | for (var i = 0; i < arr[num].length; i++) { 22 | var tmp_num = arr[num][i] 23 | if (!marked[tmp_num]) { 24 | edgeTo[tmp_num] = num 25 | marked[tmp_num] = true 26 | queue.push(tmp_num) 27 | tmp+=arr[num][i]+'\n' 28 | }else{ 29 | tmp+=arr[num][i]+'marked\n' 30 | } 31 | } 32 | 33 | } 34 | } 35 | 36 | function pathTo(start,end){ 37 | var path = [] 38 | for(var x=end;x!=start;x=edgeTo[x]){ 39 | path.unshift(x) 40 | } 41 | path.unshift(start) 42 | return path 43 | } 44 | 45 | 46 | 47 | 48 | bfs(0) 49 | 50 | console.log(pathTo(0,1).join('->')) 51 | console.log(pathTo(0,2).join('->')) 52 | console.log(pathTo(0,3).join('->')) 53 | console.log(pathTo(0,4).join('->')) 54 | console.log(pathTo(0,5).join('->')) 55 | 56 | 57 | console.log(edgeTo) -------------------------------------------------------------------------------- /bfsSearch.js: -------------------------------------------------------------------------------- 1 | // 模拟无向图的arr 深度遍历搜索所有点 2 | var arr = [ 3 | [2,1,5], 4 | [0,2], 5 | [0,1,3,4], 6 | [5,4,2], 7 | [3,2], 8 | [3,0] 9 | 10 | ] 11 | var marked = new Array(arr.length) 12 | var tmp = '' 13 | function bfs(n){ 14 | queue = [] 15 | tmp += '\nbfs'+n+'go\n' 16 | marked[n] = true 17 | queue.push(n) 18 | while(queue.length){ 19 | num = queue.shift() 20 | for (var i = 0; i < arr[num].length; i++) { 21 | if (!marked[arr[num][i]]) { 22 | marked[arr[num][i]] = true 23 | queue.push(arr[num][i]) 24 | tmp+=arr[num][i]+'\n' 25 | }else{ 26 | tmp+=arr[num][i]+'marked\n' 27 | } 28 | } 29 | 30 | } 31 | // for (var i = 0; i < arr[n].length; i++) { 32 | 33 | // // tmp +='>' 34 | // // if(!marked[arr[n][i]]){ 35 | 36 | // // bfs(arr[n][i]) 37 | // // }else{ 38 | // // tmp+= arr[n][i]+ ':marked' 39 | // // } 40 | // }; 41 | } 42 | 43 | bfs(0) 44 | console.log(marked) 45 | console.log(tmp) -------------------------------------------------------------------------------- /binarySearch.js: -------------------------------------------------------------------------------- 1 | // 二分查找 2 | arr = [1,3,5,7,11,24,35,100] 3 | 4 | function binarySearch(arr,n){ 5 | var end = arr.length,start = 0,res 6 | while(end>start){ 7 | var mid = (end+start)>>1 8 | if (arr[mid]>n) { 9 | end = mid-1 10 | }; 11 | if (arr[mid]arr[j+1]) { 7 | 8 | var tmp = arr[j] 9 | arr[j] = arr[j+1] 10 | arr[j+1] = tmp 11 | 12 | }; 13 | }; 14 | }; 15 | return arr 16 | 17 | } 18 | 19 | arr = [366, 240, 866, 115, 447, 887, 308, 883, 871, 174, 17, 792, 721, 79, 613, 135, 108, 110, 666, 450, 36, 466, 934, 562, 841, 311, 847, 665, 830, 385, 110, 888, 731, 312, 862, 768, 568, 633, 88, 403, 944, 115, 45, 292, 95, 403, 686, 204, 334, 779, 973, 112, 674, 246, 212, 229, 309, 255, 645, 242, 527, 681, 565, 316, 320, 407, 493, 46, 992, 898, 886, 128, 88, 559, 302, 2, 369, 470, 328, 795, 264, 209, 17, 620, 290, 555, 942, 85, 118, 158, 927, 429, 986, 408, 917, 89, 86, 312, 355, 779, 700, 280, 583, 138, 786, 590, 933, 964, 321, 548, 758, 851, 746, 887, 815, 623, 969, 496, 823, 79, 65, 224, 257, 965, 112, 66, 231, 334, 28, 407, 248, 20, 395, 398, 498, 189, 217, 831, 354, 377, 836, 325, 248, 112, 885, 919, 172, 735, 569, 468, 300, 730, 853, 427, 766, 200, 267, 116, 634, 989, 624, 343, 316, 315, 540, 835, 563, 495, 798, 86, 9, 760, 553, 354, 232, 374, 450, 426, 944, 393, 602, 777, 146, 829, 674, 167, 808, 509, 730, 94, 152, 658, 656, 579, 720, 301, 269, 670, 75, 788, 589, 906, 531, 264, 358, 155, 247, 209, 503, 207, 951, 580, 282, 518, 119, 643, 429, 657, 446, 684, 950, 426, 324, 490, 46, 289, 138, 763, 57, 620, 465, 973, 466, 165, 897, 888, 181, 385, 554, 711, 346, 365, 437, 405, 241, 972, 607, 382, 465, 762, 678, 758, 426, 453, 321, 387, 590, 331, 363, 234, 374, 75, 840, 62, 66, 997, 521, 169, 23, 417, 377, 6, 393, 657, 889, 56, 156, 729, 448, 278, 515, 372, 936, 129, 81, 676, 466, 555, 790, 538, 750, 101, 878, 196, 477, 222, 384, 557, 475, 258, 456, 894, 127, 101, 887, 289, 257, 310, 271, 344, 226, 563, 778, 144, 871, 313, 486, 809, 692, 992, 877, 945, 862, 551, 540, 142, 941, 836, 646, 423, 311, 28, 516, 608, 784, 975, 100, 490, 51, 100, 608, 667, 289, 984, 825, 395, 113, 184, 896, 86, 594, 540, 597, 364, 153, 426, 83, 6, 686, 372, 415, 726, 168, 176, 336, 412, 67, 564, 404, 911, 741, 372, 508, 927, 728, 982, 209, 101, 207, 657, 577, 733, 926, 187, 561, 11, 370, 143] 20 | res = bubble(arr) 21 | console.log(res) 22 | // console.log(arr) -------------------------------------------------------------------------------- /calculation.js: -------------------------------------------------------------------------------- 1 | // 解析算数表达式 求结果1123 2 | 3 | function cal(str){ 4 | var numArr = [],opArr = [] 5 | for(var s in str){ 6 | var tmp = str[s] 7 | // console.log(tmp) 8 | if (tmp=='+'||tmp=='-'||tmp=='*'||tmp=='/') { 9 | opArr.push(tmp) 10 | }else if(tmp=='('){ 11 | 12 | } 13 | else if(tmp==')'){ 14 | var num = Number(numArr.pop()); 15 | var op = opArr.pop(); 16 | // console.log(num,op) 17 | 18 | if (op=='+') num = Number(numArr.pop())+num 19 | if (op=='-') num = numArr.pop()-num 20 | if (op=='*') num = numArr.pop()*num 21 | if (op=='/') num = numArr.pop()/num 22 | numArr.push(num) 23 | }else{ 24 | numArr.push(tmp) 25 | } 26 | } 27 | console.log(opArr) 28 | return numArr 29 | } 30 | 31 | console.log(cal('((1+(2*3)*(4+5)))')) -------------------------------------------------------------------------------- /dfsCC.js: -------------------------------------------------------------------------------- 1 | 2 | var arr = [ 3 | [6,2,1,5], 4 | [0], 5 | [0], 6 | [5,4], 7 | [5,6,3], 8 | [3,4,0], 9 | [0,4], 10 | [8], 11 | [7], 12 | [11,10,12], 13 | [9], 14 | [9,12], 15 | [11,9] 16 | ] 17 | var marked = new Array(arr.length) 18 | var ids = new Array(arr.length) 19 | var count = 0 20 | function CC(arr){ 21 | for (var i = 0; i < ids.length; i++) { 22 | // ids[i] 23 | // console.log(i) 24 | if (!marked[i]) { 25 | dfs(arr,i) 26 | count++ 27 | }; 28 | }; 29 | } 30 | function dfs(arr, v){ 31 | console.log('check '+v) 32 | marked[v] = true 33 | ids[v] = count 34 | var idv 35 | for (var i = 0; i < arr[v].length; i++) { 36 | idv = arr[v][i] 37 | if (!marked[idv]) { 38 | // console.log('search '+idv) 39 | dfs(arr,idv) 40 | }else{ 41 | // console.log(' '+idv+' checked') 42 | } 43 | 44 | }; 45 | } 46 | 47 | // console.log('search 0')console.log(marked) 48 | 49 | CC(arr) 50 | 51 | console.log(ids) 52 | console.log(marked) 53 | 54 | -------------------------------------------------------------------------------- /dfsDirectedCycle.js: -------------------------------------------------------------------------------- 1 | var arr = [ 2 | [5, 1], 3 | [], 4 | [0, 3], 5 | [5, 2], 6 | [3, 2], 7 | [4], 8 | [9, 4, 0], 9 | [6, 8], 10 | [7, 9], 11 | [11, 10], 12 | [12], 13 | [4, 12], 14 | [9] 15 | 16 | ] 17 | 18 | var marked = new Array(arr.length) 19 | var edgeTo = new Array(arr.length) 20 | var onStack = new Array(arr.length) 21 | var hasCycle = false 22 | var circle = [] 23 | function directedCycye(arr) { 24 | for (var i = 0; i < arr.length; i++) { 25 | if (!marked[i]) { 26 | dfs(arr, i) 27 | }; 28 | }; 29 | } 30 | 31 | function dfs(arr, num) { 32 | marked[num] = true 33 | onStack[num] = true 34 | for (var i = 0; i < arr[num].length; i++) { 35 | 36 | end = arr[num][i] 37 | if (circle.length>0) { 38 | return; 39 | }; 40 | 41 | if (!marked[end]) { 42 | edgeTo[end] = num 43 | dfs(arr,end) 44 | }else{ 45 | // var cir = [] 46 | for (var x=num; x!=end; x=edgeTo[x]) { 47 | circle.push(x) 48 | }; 49 | circle.push(end) 50 | circle.push(num) 51 | 52 | } 53 | 54 | }; 55 | // console.log(cir) 56 | onStack[num] = false 57 | 58 | 59 | } 60 | directedCycye(arr) 61 | console.log(marked) 62 | console.log(edgeTo) 63 | console.log(circle) 64 | -------------------------------------------------------------------------------- /dfsPath.js: -------------------------------------------------------------------------------- 1 | // 模拟无向图的arr 深度遍历搜索所有点 2 | var arr = [ 3 | [2,1,5], 4 | [0,2], 5 | [0,1,3,4], 6 | [5,4,2], 7 | [3,2], 8 | [3,0] 9 | 10 | ] 11 | var marked = new Array(arr.length) 12 | var edgeTo = new Array(arr.length) 13 | 14 | function dfs(n){ 15 | marked[n] = true 16 | for (var i = 0; i < arr[n].length; i++) { 17 | if(!marked[arr[n][i]]){ 18 | edgeTo[arr[n][i]] = n 19 | dfs(arr[n][i]) 20 | } 21 | }; 22 | } 23 | 24 | dfs(0) 25 | 26 | function hasPath(v){ 27 | return marked[v] 28 | } 29 | function pathTo(start,end){ 30 | var path = [] 31 | for(var x=end;x!=start;x=edgeTo[x]){ 32 | path.unshift(x) 33 | } 34 | path.unshift(start) 35 | return path 36 | } 37 | 38 | console.log(pathTo(0,1).join('->')) 39 | console.log(pathTo(0,2).join('->')) 40 | console.log(pathTo(0,3).join('->')) 41 | console.log(pathTo(0,4).join('->')) 42 | console.log(pathTo(0,5).join('->')) 43 | 44 | 45 | console.log(hasPath(2)) 46 | 47 | 48 | -------------------------------------------------------------------------------- /dfsPrePostSearch.js: -------------------------------------------------------------------------------- 1 | var arr = [ 2 | [5, 1], 3 | [], 4 | [0, 3], 5 | [5], 6 | [], 7 | [4], 8 | [4,9], 9 | [6], 10 | [7], 11 | [10,11,12], 12 | [], 13 | [12], 14 | [] 15 | 16 | ] 17 | 18 | var marked = new Array(arr.length) 19 | 20 | var pre = [] 21 | var post = [] 22 | var reversePost = [] 23 | 24 | function prePostReversepost(arr) { 25 | for (var i = 0; i < arr.length; i++) { 26 | if (!marked[i]) { 27 | dfs(arr, i) 28 | }; 29 | }; 30 | } 31 | 32 | function dfs(arr,num){ 33 | var end 34 | marked[num] = true 35 | pre.push(num) 36 | for (var i = 0; i < arr[num].length; i++) { 37 | end = arr[num][i] 38 | if (!marked[end]) { 39 | dfs(arr,end) 40 | }; 41 | }; 42 | post.push(num) 43 | reversePost.unshift(num) 44 | } 45 | prePostReversepost(arr) 46 | console.log(pre) 47 | console.log(post) 48 | console.log(reversePost) 49 | -------------------------------------------------------------------------------- /dfsSearch.js: -------------------------------------------------------------------------------- 1 | // 模拟无向图的arr 深度遍历搜索所有点 2 | var arr = [ 3 | [2,1,5], 4 | [0,2], 5 | [0,1,2,3,4], 6 | [5,4,2], 7 | [3,2], 8 | [3,0] 9 | 10 | ] 11 | var marked = new Array(arr.length) 12 | var tmp = '' 13 | function dfs(n){ 14 | tmp += '\ndfs'+n 15 | marked[n] = true 16 | for (var i = 0; i < arr[n].length; i++) { 17 | tmp +='>' 18 | if(!marked[arr[n][i]]){ 19 | 20 | dfs(arr[n][i]) 21 | }else{ 22 | tmp+= arr[n][i]+ ':marked' 23 | } 24 | }; 25 | } 26 | 27 | dfs(0) 28 | console.log(marked) 29 | console.log(tmp)earch -------------------------------------------------------------------------------- /genArr.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shengxinjing/js-algorithm/e56751e89482d2afa799f98bcfe82238a811daa7/genArr.js -------------------------------------------------------------------------------- /heapSort.js: -------------------------------------------------------------------------------- 1 | function heapSort(arr){ 2 | 3 | var len = arr.length 4 | // heap(arr,0,arr.length) 5 | buildMaxHeap(arr) 6 | console.log(arr) 7 | for (var i = arr.length - 1; i > 0; i--) { 8 | // swap(arr,0,i) 9 | swap(arr,0,i) 10 | // console.log(i,arr) 11 | len-- 12 | heap(arr,0,i) 13 | // break 14 | }; 15 | return arr 16 | } 17 | function buildMaxHeap(arr){ 18 | for(var i=Math.floor(arr.length/2);i>=0;i--){ 19 | heap(arr,i,arr.length) 20 | } 21 | return arr 22 | } 23 | // 调整子数为最大堆 24 | // 合并两个有序数组 25 | 26 | 27 | function heap(arr,start,end){ 28 | var left = 2*start + 1 29 | var right = 2*start +2 30 | var largest = start 31 | if (leftarr[start]) { 32 | largest = left 33 | }; 34 | if (rightarr[largest]) { 35 | largest = right 36 | }; 37 | if (largest!==start) { 38 | swap(arr,start,largest) 39 | heap(arr,largest,end) 40 | }; 41 | } 42 | function swap(items, firstIndex, secondIndex){ 43 | var temp = items[firstIndex]; 44 | items[firstIndex] = items[secondIndex]; 45 | items[secondIndex] = temp; 46 | } 47 | arr = [366, 240, 866, 115, 9, 760, 553, 354, 232, 374, 450, 426, 944, 2,393, 143] 48 | heapSort(arr) 49 | console.log(arr) 50 | 51 | 52 | 53 | console.log('--------------') 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /insertionSort.js: -------------------------------------------------------------------------------- 1 | function insertion(arr){ 2 | var len = arr.length 3 | for (var i = 0; i < len; i++) { 4 | // var min = i 5 | for (var j = i+1; j env){ 17 | end-- 18 | } 19 | while(arr[start]=1){ 10 | for (var i = 0; i < len; i=i+h) { 11 | 12 | // // var min = i 13 | for (var j = i+h; j