數(shù)據(jù)結(jié)構(gòu)javascript

我的電腦配置
CPU:AMD X4 640
內(nèi)存: 宏想 DDR3 1600MHz 8g
主板:華擎 980DE3/U3S3 R2.0

時間測試函數(shù)

        function testRunTime(fn) {
            let start = new Date();
            let end = null;
            fn();
            end = new Date();
            console.log(`運行時間: ${(end - start) / 1000}秒`);
        }


數(shù)據(jù)結(jié)構(gòu)

線性結(jié)構(gòu)
1.數(shù)組
2.鏈表
3.隊列
4.棧
5.最大堆
6.映射
7.二叉樹
8.圖
9.哈希表
**

數(shù)組

// 數(shù)組
class MyArray {
    constructor(capacity=10) {
        this._data = new Array(capacity);
        this._size = 0;
    }
    get length() {
        return this._size;
    }
    get capacity() {
        return this._data.length;
    }

    // 插入指定位置
    insert(index, e) { 
        if (index < 0 || index >= this._data.length) {
            throw new RangeError("index is invalid");
        }
        for (let i=this._size-1; i>=index; i--) {
            this._data[i+1] = this._data[i];
        }
        this._data[index] = e;
        this._size++;
    }
    // 添加到最后
    insertLast(e) { 
        this.insert(this._size, e);
    }
    // 添加到開頭
    insertFirst(e) { 
        this.insert(0, e);
    }

    // 獲取位置為index的元素
    get(index) { 
        if (index < 0 || index >= this._data.length) {
            throw new RangeError("index is invalid");
        } 
        return this._data[index];
    }

    // 刪除位置為index的元素
    remove(index) { 
        if (index < 0 || index >= this._data.length) {
            throw new RangeError("index is invalid");
        } 
        let ret = this._data[index];
        for (let i=index,len=this._size-1; i<=len; i++) {
            this._data[i] = this._data[i+1];
        }
        this._size--;
        return ret;
    }

    // 更新元素
    set(index, e) { 
        if (index < 0 || index >= this._data.length) {
            throw new RangeError("index is invalid");
        } 
        if (this._data[index]) {
            this._data[index] = e;
        } else { // 不存在就添加
            this.insertLast(e);
        }
    }

    // 是否包含元素
    includes(e) {
        for (let i=0,len=this._size; i<len; i++) {
            if (Object.is(this._data[i], e)) {
                return true;
            }
        }
        return false;
    }

    // 查找元素, 返回索引
    find(e) {
        for (let i=0,len=this._size; i<len; i++) {
            if (Object.is(this._data[i], e)) {
                return i;
            }
        }
        return -1;
    }

    toString() {
        let str = "[";
        for (let i=0,len=this._size; i<len; i++) {
            str += this._data[i];
            if (i != len-1) {
                str += ",";
            }
        }
        str += "]";
        return str;
    }
}

export default MyArray;






鏈表

單向鏈表

// 鏈表
class LinkedListNode {
    constructor(e, next=null) {
        this.e = e;
        this.next = next;
    }
}
class LinkedList {
    constructor() {
        this._dummyhead = new LinkedListNode(null);
        this._tail = null; // 尾指針
        this._size = 0;
    }
    get length() {
        return this._size;
    }
    get isEmpty() {
        return this._size == 0;
    }

    // 插入元素
    insert(index, e) {
        if (index < 0 || index>this._size) {
            throw new RangeError("index is invalid");
        }
        let cur = this._dummyhead;
        for (let i=0; i<index; i++) {
            cur = cur.next;
        }
        cur.next = new LinkedListNode(e, cur.next);
        if (this._size === index) {
            this._tail = cur.next;
        }
        this._size++;
    }
    // 插入表頭
    insertFirst(e) {
        this._dummyhead.next = new LinkedListNode(e, this._dummyhead.next);
        if (this._size == 0) {
            this._tail = this._dummyhead.next;
        }
        this._size++;
    }
    // 插入表尾
    insertLast(e) {
        if (this._size == 0) {
            this._dummyhead.next = new LinkedListNode(e);
            this._tail = this._dummyhead.next;
        } else {
            this._tail.next = new LinkedListNode(e);
            this._tail = this._tail.next;
        }
        this._size++;
    }
    
    // 刪除元素
    removeElement(e) {
        if (this.isEmpty) {
            return new Error("Element is empty");
        }
        let prev = this._dummyhead;
        while (prev != null) {
            if (Object.is(prev.next.e,e)) {
                break;
            }
            prev = prev.next;
        }
        if (prev != null) {
            let ret = prev.next;
            prev.next = ret.next;
            ret.next = null;
            if (Object.is(ret.e, this._tail.e)) {
                this._tail = prev;
            }
            this._size--;
            return ret;
        }
        return null;
    }
    // 根據(jù)位置刪除元素
    removeIndex(index) {
        if (index < 0 || index>this._size) {
            throw new RangeError("index is invalid");
        }
        if (this.isEmpty) {
            return new Error("Element is empty");
        }
        let prev = this._dummyhead;
        let ret;
        for (let i=0; i<index; i++) {
            prev = prev.next;
        }
        ret = prev.next;
        prev.next = ret.next;
        ret.next = null;
        if (Object.is(ret.e, this._tail.e)) {
            this._tail = prev;
        }
        this._size--;
        return ret;
    }

    // 查找元素
    find(e) {
        let cur = this._dummyhead.next;
        let index = 0;

        while (cur !== null) {
            if (Object.is(cur.e, e)) {
                break;
            }
            index++;
            cur = cur.next;
        }
        if (cur == null) {
            return -1;
        } else {
            return index;
        }
    }
    contains(e) {
        let result = this.find(e);
        return result != -1 ? true : false;
    }
    // 訪問元素
    get(index) {
        if (index < 0 || index>this._size) {
            throw new RangeError("index is invalid");
        }
        let cur = this._dummyhead.next;
        for (let i=0; i<index; i++) {
            cur = cur.next;
        }
        return cur;
    }
    toString() {
        let res = "";
        let cur = this._dummyhead.next;

        for (let i=0,len=this._size; i<len; i++) {
            res += cur.e;
            if (i != len-1) {
                res += " > ";
            }
            cur = cur.next;
        }
        return res;
    }
}

export default LinkedList;

雙向鏈表

class LinkedListNode {
    constructor(item, next = null, prev = null) {
        this.item = item;
        this.next = next;
        this.prev = prev;
    }
}
// 雙向鏈表
class LinkedList {
    constructor() {
        this._dummyhead = new LinkedListNode(null);
        this._tail = null; // 尾指針
        this._size = 0;
    }
    get size() {
        return this._size;
    }
    get isEmpty() {
        return this._size === 0;
    }
    // 插入元素
    insert(index, e) {
        if (index < 0 || index > this._size) {
            throw new RangeError("index is invalid");
        }
        let cur = this._dummyhead;
        for (let i = 0; i < index; i++) {
            cur = cur.next;
        }
        cur.next = new LinkedListNode(e, cur.next, cur);
        if (cur.next.next) {
            cur.next.next.prev = cur.next;
        }
        if (this._size === index) {
            this._tail = cur.next;
        }
        this._size++;
    }
    // 插入表頭
    unshift(e) {
        this._dummyhead.next = new LinkedListNode(e, this._dummyhead.next);
        if (this._size == 0) {
            this._tail = this._dummyhead.next;
        }
        this._size++;
    }
    // 插入表尾
    push(e) {
        if (this._size == 0) {
            this._dummyhead.next = new LinkedListNode(e, null, this._dummyhead);
            this._tail = this._dummyhead.next;
        } else {
            this._tail.next = new LinkedListNode(e, null, this._tail);
            this._tail = this._tail.next;
        }
        this._size++;
    }
    // 刪除元素
    removeElement(e) {
        if (this.isEmpty) {
            return new Error("Element is empty");
        }
        let prev = this._dummyhead;
        while (prev != null) {
            if (prev.next !== null && Object.is(prev.next.item, e)) {
                break;
            }
            prev = prev.next;
        }
        if (prev != null) {
            let ret = prev.next;
            prev.next = ret.next;
            if (ret.next) {
                ret.next.prev = prev; // 調(diào)整上一個元素指向
            }
            ret.next = null;
            if (Object.is(ret.item, this._tail.item)) {
                this._tail = prev;
            }
            this._size--;
            return ret;
        }
        return null;
    }
    // 根據(jù)位置刪除元素
    removeIndex(index) {
        if (index < 0 || index > this._size) {
            throw new RangeError("index is invalid");
        }
        if (this.isEmpty) {
            return new Error("Element is empty");
        }
        let prev = this._dummyhead;
        let ret;
        for (let i = 0; i < index; i++) {
            prev = prev.next;
        }
        ret = prev.next;
        prev.next = ret.next;
        if (ret.next) {
            ret.next.prev = prev; // 調(diào)整上一個元素指向
        }
        ret.next = null;
        if (Object.is(ret.item, this._tail.item)) {
            this._tail = prev;
        }
        this._size--;
        return ret;
    }
    pop() {
        return this.removeIndex(this.size - 1);
    }
    shift() {
        return this.removeIndex(0);
    }
    // 查找元素
    find(e) {
        let cur = this._dummyhead.next;
        let index = 0;

        while (cur !== null) {
            if (Object.is(cur.item, e)) {
                break;
            }
            index++;
            cur = cur.next;
        }
        if (cur == null) {
            return -1;
        } else {
            return index;
        }
    }
    contains(e) {
        let result = this.find(e);
        return result != -1 ? true : false;
    }
    // 訪問元素
    get(index) {
        if (index < 0 || index > this._size) {
            throw new RangeError("index is invalid");
        }
        let cur = this._dummyhead.next;
        for (let i = 0; i < index; i++) {
            cur = cur.next;
        }
        return cur;
    }
    toString() {
        let res = "";
        let cur = this._dummyhead.next;

        for (let i = 0, len = this._size; i < len; i++) {
            res += cur.item;
            if (i != len - 1) {
                res += " > ";
            }
            cur = cur.next;
        }
        return res;
    }
    iterator() { // 迭代器
        return {
            _item: this._dummyhead,
            next() {
                if (this.hasNext()) {
                    let ret = this._item.next;
                    this._item = this._item.next;
                    return ret;
                }
                return null;
            },
            hasNext() {
                return this._item.next !== null; 
            }
        }
    }
}






  1. 數(shù)組實現(xiàn)
class Stack {
    constructor() {
        this._data = [];
    }
    push(e) {
        this._data.push(e);
    }
    pop() {
        return this._data.pop();
    }
    peek() {
        return this._data[0];
    }
    isEmpty() {
        return this._data.length == 0;
    }
    get length() {
        return this._data.length;
    }
}
export default Stack;
  1. 鏈表實現(xiàn)
import LinkedList from "./LinkedList.js";
// 先引入鏈表

class Stack {
   constructor() {
       this._data = new LinkedList();
   }
   push(e) {
       this._data.insertFirst(e);
   }
   pop() {
       return this._data.removeIndex(0);
   }
   peek() {
       return this._data.get(0);
   }
   get isEmpty() {
       return this._data.isEmpty;
   }
   get lenght() {
       return this._data.length;
   }
}

export default Stack;






隊列

  1. 數(shù)組實現(xiàn)
class Queue {
   constructor() {
       this._data = [];
   }
   enqueue(e) {
       this._data.push(e);
   }
   dequeue() {
       return this._data.shift();
   }
   front() {
       return this._data[0];
   }
   get isEmpty() {
       return this._data.length == 0;
   }
   get length() {
       return this._data.length;
   }
   toString() {
       return "Front ["+this._data.toString+"]";
   }
}

export default Queue;
  1. 鏈表實現(xiàn)
import LinkedList from "./LinkedList.js";

class Queue {
    constructor() {
        this._data = new LinkedList();
    }

    // 進隊
    enqueue(e) {
        this._data.insertLast(e);
    }

    // 出隊
    dequeue() {
        return this._data.removeIndex(0);
    }

    // 隊首元素
    front() {
        return this._data.get(0);
    }
    get isEmpty() {
        return this._data.length == 0;
    }
    get length() {
        return this._data.length;
    }
    toString() {
        return "Front "+this._data.toString();
    }
}

export default Queue;






二分搜索樹

import Queue from "./LinkedListQueue.js";

class Node {
    constructor(e=null) {
        this.e = e;
        this.left = null;
        this.right = null;
    }
}
class BST {
    constructor() {
        this._root = null;
        this._size = 0;
    }
    get size() {
        return this._size;
    }
    get isEmpty() {
        return this._size == 0;
    }

    // 插入
    insert(e) {
        let _this = this;

        if (this._root == null) {
            this._root = new Node(e);
            this._size++;
        } else {
            this._root = _insert(this._root);
        }

        function _insert(node) {
            if (node == null) {
                _this._size++;
                return new Node(e);
            }

            if (e < node.e) {
                node.left = _insert(node.left);
            } else if (e > node.e) {
                node.right = _insert(node.right);
            }
            return node;
        }
    }

    // 最大值
    maximum() {
        if (this.isEmpty) {
            throw new Error("data is empty");
        }
        return this._maximum(this._root);
    }
    _maximum(node) {
        if (node.right == null) {
            return node;
        }
        return this._maximum(node.right); 
    }

    // 最小值
    minimum() {
        if (this.isEmpty) {
            throw new Error("data is empty");
        }
        return this._minimum(this._root);
    }
    _minimum(node) {
        if (node.left == null) {
            return node;
        }
        return this._minimum(node.left);  
    }

    // 刪除最小值
    removeMin() {
        if (this.isEmpty) {
            throw new Error("data is empty");
        }
        let minimum = this.minimum();
        this._root = this._removeMin(this._root);
        return minimum;
    }
    _removeMin(node) {
        if (node.left == null) {
            let rightNode = node.right;
            node.right = null;
            this._size--;
            return rightNode;
        }
        node.left = this._removeMin(node.left);
        return node; 
    }

    // 刪除最大值
    removeMax() {
        if (this.isEmpty) {
            throw new Error("data is empty");
        }
        let maximum = this.maximum();
        this._root = this._removeMax(this._root);
        return maximum;
    }
    _removeMax(node) {
        if (node.right == null) {
            let leftNode = node.left;
            node.left = null;
            this._size--;
            return leftNode;
        }
        node.right = this._removeMax(node.right);
        return node;
    }

    // 刪除
    remove(e) {
        if (this.isEmpty) {
            throw new Error("data is empty");
        }
        let _this = this;
        this._root = _remove(this._root);
        function _remove(node) {
            if (node == null) {
                return null;
            }
            if (e < node.e) {
                node.left = _remove(node.left);
                return node;
            } else if (e > node.e) {
                node.right = _remove(node.right);
                return node;
            } else { // 匹配成功
                if (node.left == null) {
                    let rightNode = node.right;
                    node.right = null;
                    _this._size--;
                    return rightNode;
                } else if (node.right == null) {
                    let leftNode = node.left;
                    node.left = null;
                    _this._size--;
                    return leftNode;
                } 
                // 兩邊都有結(jié)點
                let successor = _this._minimum(node.right);
                successor.right = _this._removeMin(node.right);
                successor.left = node.left;
                return successor;
            }
        }
    }

    // 查找
    find(e) {
        if (this.isEmpty) {
            throw new Error("data is empty");
        }
        return _find(this._root);
        function _find(node) {
            if (node == null) {
                return null;
            }
            if (e < node.e) {
                node.left = _find(node.left);
                return node.left;
            } else if (e > node.e) {
                node.right = _find(node.right);
                return node.right;
            } else {
                return node;
            }
        }
    }

    // 前序遍歷
    preOrder() {
        _preOrder(this._root);
        function _preOrder(node) {
            if (node == null) {
                return;
            }
            console.log(node.e);
            _preOrder(node.left);
            _preOrder(node.right);
        }
    }
    // 中序遍歷
    inOrder() {
        _inOrder(this._root);
        function _inOrder(node) {
            if (node == null) {
                return;
            }
            _inOrder(node.left);
            console.log(node.e);
            _inOrder(node.right);
        }
    }
    // 后序序遍歷
    postOrder() {
        _postOrder(this._root);
        function _postOrder(node) {
            if (node == null) {
                return;
            }
            _postOrder(node.left);
            _postOrder(node.right);
            console.log(node.e);
        }
    }

    // 層序遍歷
    levelOrder() {
        let queue = new Queue();
        let node;
        queue.enqueue(this._root);

        while (!queue.isEmpty) {
            node = queue.dequeue();
            console.log(node.e.e);
            if (node.e.left != null) {
                queue.enqueue(node.e.left);
            }
            if (node.e.right != null) {
                queue.enqueue(node.e.right);
            }
        }
    }

    // 是否包含某個元素
    contains(e) {
        return _contains(this._root);
        function _contains(node) {
            if (node == null) {
                return false;
            }
            if (e < node.e) {
                node.left = _contains(node.left);
                return node.left;
            } else if (e > node.e) {
                node.right = _contains(node.right);
                return node.right;
            } else {
                return true;
            }
        }
    }
}

export default BST;






集合

  1. 數(shù)組實現(xiàn)
class Set {
   constructor() {
       this._data = [];
   }
   contains(e) {
       return this._data.includes(e);
   }
   add(e) {
       if (!this.contains(e)) {
           this._data.push(e);
       }
   }
   remove(e) {
       let index = this._data.indexOf(e);
       this._data.splice(index,1);
       return this._data[index];
   }
   get length() {
       return this._data.length;
   }
   get isEmpty() {
       return this.length == 0;
   }
}

export default Set;
  1. 鏈表實現(xiàn)
import LinkedList from "./LinkedList.js";

class Set {
    constructor() {
        this._data = new LinkedList();
    }
    contains(e) {
        return this._data.contains(e);
    }
    add(e) {
        if (!this.contains(e)) {
            this._data.insertFirst(e);
        }
    }
    remove(e) {
        return this._data.removeElement(e);
    }
    get length() {
        return this._data.length;
    }
    get isEmpty() {
        return this.length == 0;
    }
}

export default Set;






映射

雙向鏈表實現(xiàn)
查找和設(shè)置復(fù)雜度都是O(n)

數(shù)據(jù)量 雙向鏈表映射 js自帶的對象
3萬 9.965秒 0.018秒
10萬 33.22秒 0.043秒
class Node {
    constructor(key,value,prev=null,next=null) {
        this.key = key;
        this.value = value;
        this.next = next;
        this.prev = prev;
    }
}
class LinkedListMap {
    constructor() {
        this._root = null;
        this._tail = null;
        this._size = 0;
    }
    get size() {return this._size}
    get isEmpty() {return this._size === 0}
    contains(key) {
        if (typeof key !== "string") {throw("key need string type")}
        for(let cur=this._root; cur!=null; cur=cur.next) {
            if (cur.key === key) {
                return cur;   
            }
        }
        return null;
    }
    get(key) {
        if (typeof key !== "string") {throw("key need string type")}
        let ret = this.contains(key);
        return ret ? ret.value : null;
    }
    put(key, value) {
        if (typeof key !== "string") {throw("key need string type")}
        let ret = this.contains(key);
        if (ret !== null) { // 有則更新
            ret.value = value;
        } else { // 沒有就創(chuàng)建
            let node = new Node(key,value);
            if (this.size === 0) {
                this._root = node;
                this._tail = node;
            } else {
                node.prev = this._tail;
                this._tail.next = node;  
                this._tail = node;
            }
            this._size++;
        }
    }
    delete(key) {
        if (typeof key !== "string") {throw("key need string type")}
        let node = this.contains(key);
        if (node !== null) {
            if (key === this._root.key) {
                let next = this._root.next;
                this._root.next = null;
                this._root = next;
                if (next != null) { 
                    next.prev = null;
                } else { // 只有一個節(jié)點
                    this._tail = null
                }
            } else {
                node.prev.next = node.next;
                if (key === this._tail.key) {
                    this._tail = node.prev;
                } else {
                    node.next = null;
                    node.next.prev = null;
                }
            }
            this._size--;
        }
    }

}






最大堆

class MaxHeap {
    constructor(arr=[]) {
        this._data = arr;
        for (let i=this._parent(arr.length-1); i>=0; i--) {
            this._shiftDown(i);
        }
    }
    get length() {
        return this._data.length;
    }
    get isEmpty() {
        return this._data.length == 0;
    }
    add(e) {
        this._data.push(e);
        this._shiftUp(this._data.length-1);
    }
    get() {
        return this._data[0];
    }
    remove(e) {
        let ret = this._data.shift();
        this._shiftDown(0);
        return ret;
    }
    // 父節(jié)點的索引
    _parent(index) {
        if (index == 0) {
            throw new RangeError("index-0 doesn't parent");
        }
        return Math.floor((index-1) / 2);
    }
    // 左結(jié)點的索引
    _leftChild(index) {
        return index*2+1;
    }
    // 右結(jié)點的索引
    _rightChild(index) {
        return index*2+2;
    }

    // 大的往上走
    _shiftUp(k) {
        let data = this._data;
        while (k>0 && data[this._parent(k)] < data[k]) {
            let parent = data[this._parent(k)];
            data[this._parent(k)] = data[k];
            data[k] = parent;

            k=this._parent(k);
        }
    }
    // 小的往下走
    _shiftDown(k) {
        let size = this._data.length;

        while (this._leftChild(k) < size) {
            let j = this._leftChild(k);
            let data = this._data;
            if (j+1 < size && data[j+1] > data[j]) {
                j = this._rightChild(k);
            }
            if (data[k] > data[j]) {
                break;
            }
            let agent = data[k];
            data[k] = data[j];
            data[j] = agent;
            k=j;
        }
    }
}

export default MaxHeap;






優(yōu)先隊列

import MaxHeap from "./MaxHeap.js";

class PriorityQueue {
    constructor() {
        this._data = new MaxHeap();
    }
    get length() {
        return this._data.length;
    }
    get isEmpty() {
        return this._data.isEmpty;
    }
    enqueue(e) {
        this._data.add(e);
    }
    dequeue() {
        return this._data.remove();
    }
    front() {
        return this._data.get();
    }
}

export default PriorityQueue;






前綴樹

class Node {
    constructor(isWord=false) {
        this.isWord = isWord;
        this.next = {};
    }
}
class Trie {
    constructor() {
        this._root = new Node();
        this._size = 0;
    }
    get size() {
        return this._size;
    }
    add(word) {
        let cur = this._root;
        for (let i=0; i<word.length; i++) {
            let key = word.charAt(i);
            if (cur.next[key] == undefined) {
                cur.next[key] = new Node();
            }
            cur = cur.next[key];
        }
        if (!cur.isWord) {
            cur.isWord = true;
            this._size++;
        }
    }
    contains(word) {
        let cur = this._root;
        for(let i=0; i<word.length; i++) {
            let key = word.charAt(i);
            if (cur.next[key] == undefined) {
                return false;
            }
            cur = cur.next[key];
        }
        return cur.isWord;
    }
    isPrefix(prefix) {
        let cur = this._root;
        for(let i=0; i<prefix.length; i++) {
            let key = prefix.charAt(i);
            if (cur.next[key] == undefined) {
                return false;
            }
            cur = cur.next[key];
        }
        return true;
    }
}

export default Trie;






并查集

class UnionFind {
    constructor(size) { // size 集合數(shù)量
        if (!size) {
            throw new TypeError("size is empty");
        }
        this._parent = new Array(size);
        this._rank = new Array(size); // 優(yōu)先級

        for (let i=0; i<this._parent.length; i++) {
            this._parent[i] = i; 
            this._rank[i] = 1;
        }
    }
    get size() {
        return this._parent.length;
    }
    _find(p) { // 查找所屬集合
        if (p<0 && p>=parent.length) {
            throw new RangeError(`${p} is invalid`);
        }
        while (p != this._parent[p]) {
            this._parent[p] = this._parent[this._parent[p]];
            p = this._parent[p];
        }
        return p;
    }
    isConnected(p, q) {
        return this._find(p) == this._find(q);
    }
    unionElement(p, q) {
        let pRoot = this._find(p);
        let qRoot = this._find(q);

        if (pRoot == qRoot) {
            return;
        }
        if (this._rank[pRoot] < this._rank[qRoot]) { // 小的合并到大的集合
            this._parent[pRoot] = qRoot;
        } else if (this._rank[pRoot] > this._rank[qRoot]) {
            this._parent[qRoot] = pRoot;
        } else {
            this._parent[qRoot] = pRoot;
            this._rank[pRoot] += 1;
        }
    }

}

export default UnionFind;






哈希表

class HashTable {
    constructor(capacity) {
        if (!capacity) {
            throw new RangeError("capacity is empty");
        }
        this._data = new Array(capacity);
        this._size = 0;
        for (let i=0; i<capacity; i++) {
            this._data[i] = {}; // 沖突時保持到對象里
        }
    }
    hashCode(key) { // 根據(jù)不同場景設(shè)計不同的哈希函數(shù)
        let hash = 5381;
        for (let i = 0; i < key.length; i++) {
            hash = ((hash << 5) + hash) + key.charCodeAt(i);
        }
        return Math.abs(hash % this._data.length);
    }
    get size() {
        return this._size;
    }
    add(key, value) {
        let map = this._data[this.hashCode(key)];
        if (map[key]) {
            map[key] = value;
        } else {
            map[key] = value;
            this._size++;
        }
    }
    remove(key) {
        let map = this._data[this.hashCode(key)];
        let ret = map[key];
        if (map[key]) {
            delete map[key];
            this._size--;
        }
        return ret;
    }
    get(key) {
        return this._data[this.hashCode(key)][key];
    }
    set(key, value) {
        let map = this._data[this.hashCode(key)];
        if (!map[key]) {
            throw new RangeError("key is not found");
        }
        map[key] = value;
    }
    contains(key) {
        return !!(this.get(key));
    }
}

export default HashTable;






// 鄰接矩陣
class DenseGraph {
    constructor(n, directed) {
        this._n = n; // 點
        this._m = 0; // 邊
        this._directed = directed; // 是否有向圖
        this._g = [];
        for (let i = 0; i < n; i++) {
            let arr = new Array(n).fill(false);
            this._g.push(arr);
        }
    }
    get V() { return this._n }
    get E() { return this._m }
    addEdge(v, w) {
        if (this.hasEdge(v, w)) return;

        this._g[v][w] = true;
        if (!this._directed) {
            this._g[w][v] = true;
        }
        this._m++;
    }
    hasEdge(v, w) {
        if (v < 0 || v >= this._n) throw RangeError(v + " not exist");
        if (w < 0 || w >= this._n) throw RangeError(w + " not exist");
        return this._g[v][w];
    }
    DFS(v) { // 深度優(yōu)先遍歷
        if (!this._g[0].includes(v)) {throw new RangeError(v+" is not exist")}
        let visited = [];
        let _this = this;
        _dfs(v);
        function _dfs(v) {
            visited[v] = true;
            console.log(v);
            for (let i = v; i < _this._g.length; i++) {
                for (let j = 0; j < _this._g[i].length; j++) {
                    if (_this._g[i][j] && !visited[j]) {
                        _dfs(j);
                    }
                }
            }
            // 防止孤立的點沒被遍歷到
            // for (let i = 0; i < _this._g.length; i++) {
            //     for (let j = 0; j < _this._g[i].length; j++) {
            //         if (_this._g[i][j] && !visited[j]) {
            //             _dfs(j);
            //         }
            //     }
            // }

        }
    }
    BFS(v) { // 廣度優(yōu)先遍歷
        if (!this._g[0].includes(v)) {throw new RangeError(v+" is not exist")}
        let queue = [];
        let visited = [];
        let node;
        queue.push(v);
        while (queue.length) {
            visited[v] = true;
            node = queue.shift();
            console.log(node);
            for (let i=node; i<this._g.length; i++) {
                for (let j=0; j<this._g[i].length; j++) {
                    if (this._g[i][j] && !visited[j]) {
                        queue.push(j);
                        visited[j] = true;
                    }
                }
            }
        }
    }
}

// 鄰接表
class SparseGraph {
    constructor(directed) {
        this._n = []; // 點
        this._edge = {};
        this._m = 0; // 邊
        this._directed = directed; // 是否有向圖
    }
    get V() { return this._n.length }
    get E() { return this._m }
    addEdge(v, w) {
        if (!this._edge[v]) {
            this._edge[v] = new Set();
            this._n.push(v);
        }
        if (!this._edge[v].has(w)) {
            this._edge[v].add(w);
            this._m++;
        }
        if (!this._directed) {
            if (!this._edge[w]) {
                this._edge[w] = new Set();
                this._n.push(w);
            }
            this._edge[w].add(v);
        }
    }
    DFS(v) {
        if (!this._edge[v]) {throw new RangeError(v+" is not exist")}
        let visited = {};
        let _this = this;
        _dfs(v);
        function _dfs(v) {
            visited[v] = true;
            console.log(v);
            for (let key in _this._edge) {
                _this._edge[key].forEach(item=>{
                    if (!visited[item]) {
                        _dfs(item);
                        visited[item] = true;
                    }
                })
            }
        }
    }
    BFS(v) {
        if (!this._edge[v]) {throw new RangeError(v+" is not exist")}
        let visited = {};
        let queue = [];
        let node;
        visited[v] = true;
        queue.push(v);

        while (queue.length) {
            node = queue.shift();
            console.log(node);
            this._edge[node].forEach(item=>{
                if (!visited[item]) {
                    queue.push(item);
                    visited[item] = true;
                }
            })
        }
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末宴凉,一起剝皮案震驚了整個濱河市赔蒲,隨后出現(xiàn)的幾起案子巫俺,更是在濱河造成了極大的恐慌薄啥,老刑警劉巖宛畦,帶你破解...
    沈念sama閱讀 218,640評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異赐写,居然都是意外死亡熄云,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來注祖,“玉大人猾蒂,你說我怎么就攤上這事∈浅浚” “怎么了肚菠?”我有些...
    開封第一講書人閱讀 165,011評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長罩缴。 經(jīng)常有香客問我蚊逢,道長,這世上最難降的妖魔是什么箫章? 我笑而不...
    開封第一講書人閱讀 58,755評論 1 294
  • 正文 為了忘掉前任烙荷,我火速辦了婚禮,結(jié)果婚禮上檬寂,老公的妹妹穿的比我還像新娘终抽。我一直安慰自己,他們只是感情好桶至,可當(dāng)我...
    茶點故事閱讀 67,774評論 6 392
  • 文/花漫 我一把揭開白布昼伴。 她就那樣靜靜地躺著,像睡著了一般镣屹。 火紅的嫁衣襯著肌膚如雪圃郊。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,610評論 1 305
  • 那天女蜈,我揣著相機與錄音持舆,去河邊找鬼。 笑死伪窖,一個胖子當(dāng)著我的面吹牛逸寓,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播覆山,決...
    沈念sama閱讀 40,352評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼竹伸,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了汹买?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,257評論 0 276
  • 序言:老撾萬榮一對情侶失蹤聊倔,失蹤者是張志新(化名)和其女友劉穎晦毙,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體耙蔑,經(jīng)...
    沈念sama閱讀 45,717評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡见妒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,894評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了甸陌。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片须揣。...
    茶點故事閱讀 40,021評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡盐股,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出耻卡,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 35,735評論 5 346
  • 正文 年R本政府宣布乘寒,位于F島的核電站熙掺,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏溃卡。R本人自食惡果不足惜溢豆,卻給世界環(huán)境...
    茶點故事閱讀 41,354評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望瘸羡。 院中可真熱鬧漩仙,春花似錦、人聲如沸犹赖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,936評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽冷尉。三九已至漱挎,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間雀哨,已是汗流浹背磕谅。 一陣腳步聲響...
    開封第一講書人閱讀 33,054評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留雾棺,地道東北人膊夹。 一個月前我還...
    沈念sama閱讀 48,224評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像捌浩,于是被迫代替她去往敵國和親放刨。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,974評論 2 355

推薦閱讀更多精彩內(nèi)容