链表 链表和数组 数组的内存是连续分配的,在使用数组之前需要分配固定大小的空间 链表的内存是不连续的,链表通过一个指向下一个元素地址的引用将链表中的元素串起来
单链表 是一种递归的数据结构,每个节点拥有一个元素(data)和一个指向下一个节点的引用(next)
从链头指向链尾,链尾的 Next 指针设置为 NULL
实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 function Node (element ) { this .element = element; this .next = null ; } function LList () { this .head = new Node ( 'head' ); this .find = find; this .insert = insert; this .remove = remove; this .findPrev = findPrev; this .display = display; } function find ( item ) { var currNode = this .head ; while ( currNode.element != item ){ currNode = currNode.next ; } return currNode; } function insert ( newElement , item ) { var newNode = new Node ( newElement ); var currNode = this .find ( item ); newNode.next = currNode.next ; currNode.next = newNode; } function display () { var currNode = this .head ; while ( !(currNode.next == null ) ){ console .log ( currNode.next .element ); currNode = currNode.next ; } } function reverse ( ) { var revList = new LList () var currNode = this .head .next while (currNode) { this .head .next = currNode.next currNode.next = revList.head .next revList.head .next = currNode currNode = this .head .next } return revList }
双向链表 由各个内存结构通过指针 Next 和指针 Prev 链接在一起组成
Data 数据 + Next 指针 + Prev 指针,组成一个双向链表的内存结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 function Node (element ) { this .element = element; this .next = null ; this .previous = null ; } function LList () { this .head = new Node ( 'head' ); this .find = find; this .findLast = findLast; this .insert = insert; this .remove = remove; this .display = display; this .dispReverse = dispReverse; } function find ( item ) { var currNode = this .head ; while ( currNode.element != item ){ currNode = currNode.next ; } return currNode; } function insert ( newElement , item ) { var newNode = new Node ( newElement ); var currNode = this .find ( item ); newNode.next = currNode.next ; newNode.previous = currNode; currNode.next = newNode; } function remove ( item ) { var currNode = this .find ( item ); if ( !( currNode.next == null ) ){ currNode.previous .next = currNode.next ; currNode.next .previous = currNode.previous ; currNode.next = null ; currNode.previous = null ; } }
栈和队列 栈:后进先出,只能在栈顶添加或删除,遵循 先入后出 方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 function Stack () { this .dataStore = []; this .top = 0 ; this .pop = pop; this .push = push; this .peek = peek; this .length = length; this .clear = clear; } function push ( element ){ this .dataStore [this .top ++] = element; } function pop ( ){ if (this .top > 0 ) { var popItem = this .dataStore [--this .top ] this .dataStore .splice (this .top -1 ,1 ) return popItem; } else { return 'Empty' } }
栈的应用 判断一个字符串是不是回文:从左到右依次压入栈,再依次出栈
其他方法
1 return String (word).split ('' ).reverse ().join ('' ) == word ? true : false
队列:先进先出 队列只能在队尾插入元素,在队首删除元素,就像我们平时排队买票一样~
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 function Queue ( ){ this .dataStore = []; this .enqueue = enqueue; this .dequeue = dequeue; this .front = front; this .back = back; this .toString = toString; this .clear = clear; this .empty = empty; } function enqueue ( element ) { this .dataStore .push ( element ); } function dequeue () { if ( this .empty () ) return 'This queue is empty' ; else this .dataStore .shift (); }
排序 冒泡排序 比较相邻的元素。如果第一个比第二个大,就交换它们两个 对每一对相邻元素作同样的工作
1 2 3 4 5 6 7 8 9 10 function bubbleSort (arr ) { for (let i = 0 ; i < arr.length ; i++) { for (let j = 0 ; j < arr.length ; j++) { if (arr[j] > arr[j + 1 ]) { [arr[j], arr[j + 1 ]] = [arr[j + 1 ], arr[j]] } } } return arr }
改进的冒泡
1 2 3 4 5 6 7 8 9 10 11 12 13 function bubbleSort (arr ) { var i = arr.length - 1 ; while (i > 0 ) { var pos = 0 ; for (var j = 0 ; j < i; j++) if (arr[j] > arr[j + 1 ]) { pos = j; [arr[j], arr[j + 1 ]] = [arr[j + 1 ], arr[j]] } i = pos; } return arr }
选择排序 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 function selectionSort (arr) { var len = arr.length var min, temp for (let i = 0 ; i < arr.length ; i++) { min = i for (let j = i + 1 ; j < len; j++) { if (arr[j] < arr[min]) { min = j } } [arr[i], arr[min]] = [arr[min], arr[i]] } return arr }
插入排序 从第一个元素开始 取出下一个元素,在已经排序的元素序列中从后向前扫描 如果该元素(已排序)大于新元素,将该元素移到下一位置
树 二叉树 深度和高度 深度:从根节点往下数 高度:节点的高度从最低叶节点开始,到目标节点的个数 (类比:楼房的楼层,从下往上数)
二叉搜索树 BTS 一个二叉树 满足 left 节点< 中间节点 < right 节点
如果树中没有任何节点,那么就是根节点
如果插入节点的值 比树的根节点的值大,则放在右子树,否则放在左子树
递归 (2)直到找到空位插入新节点
1 2 3 4 5 function insertNode (node, newNode ) { if () { } }
堆
是一种非连续的树形存储结构 ,每个节点都有值,整棵树是经过排序的
特点是*根节点的值最小(最大)*,且根节点的两个子树也是一个堆
常用来实现优先队列,存储随意