javascript数据结构学习笔记

数据结构

数组

方法

//一、数组
var arr = [];
// 添加元素
arr.push(1, 2); // [1,2]
// 开头插入
arr.unshift(0); // [0, 1, 3]
// 尾部删除
arr.pop(); // [0, 1] 
// 头部删除
arr.shift(); // [1]
// 数组合并
[1].concat([2]) // [1,2]

迭代器

  • every every方法会迭代数组中每个元素,直到返回false。
  • some some和every类似,不过some方法会迭代数组的每个元素,直到函数返回true
  • forEach 和for循环的结果相同
  • map 返回新的数组 [1,2].map(o => o * 2) // [2,4]
  • filter 返回新的数组 [1,2].filter(o => o > 1) // [2]
  • reduce [1,2].reduce((result, current) => result + current) // 3
  • for of for (let n of numbers) { console.log((n % 2 === 0) ? 'even' : 'odd')};
  • entries

    const numbers = [1,2,3];
    let aEntries = numbers.entries(); // 得到键值对的迭代器
    console.log(aEntries.next().value); // [0, 1] 位置0的值为1
    console.log(aEntries.next().value); // [1, 2] 位置1的值为2
    console.log(aEntries.next().value); // [2, 3] 位置2的值为3
  • keys

    const numbers = [1,2,3];
    console.log(Object.keys(numbers)); // ['0','1','2'];
  • values

    const numbers = [1,2,3];
    console.log(Object.values(numbers)); // [1,2,3]
  • Array.from
  • Array.of
  • fill
  • copyWithin
  • sort
  • find
  • findIndex
  • includes

栈是一种遵从 后进先出原则的有序集合

实现

function Stack() {
    let items = [];
    // 向栈添加元素
    this.push = function(element) {
        items.push(element);
    }
    // 从栈移除元素
    this.pop = function() {
        return items.pop();
    };
    // 查看栈顶元素
    this.peek = function() {
        return items[item.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());
    };
}

用栈解决问题

存储访问过的任务或路径、撤销的操作等。

队列

队列是遵循FIFO(First In First Out, 先进先出,也称为先来先服务)

实现

function Queue() {
    let items = [];
    // 向队列添加元素
    this.enqueue = function(element) {
        items.push(element);
    };
    // 从队列移除元素
    this.dequeue = function() {
        return 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());
    };
}

链表

链表村粗有序的元素集合,但不同于数组,链表中的元素在内存中并不是连续放置的。每个元素由一个存储元素本身的节点和一个指向下一个元素的引用(也称指针或链接)组成。
相对于传统的数组,链表的一个好处在于,添加或移除元素的时候不需要移动其他元素。然而,链表需要使用指针,因此实现链表时需要额外注意。数组的另一个细节是可以直接访问任何位置的任何元素,而要想访问链表中间的一个元素,需要从起点(表头)开始迭代列表直到找到所需的元素。

实现

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;
            }
            // 找到最后一项,将其next赋为node,建立链接
            current.next = node;
        }
        length++; // 更新列表的长度
    }
    // 从链表中移除元素
    this.removeAt = function() {
        // 检查越界值
        if (position > -1 && position < length) {
            let current = head,
            previous,
            index = 0;

            // 移除第一项
            if (position === 0) {
                head = current.next;
            } else {
                while (index++ < position) {
                    previous = current;
                    current = current.next;
                }
                // 将previous 与 current的下一项链接起来: 跳过current,从而移除它
                previous.next = current.next;
            }
            length--;
            return current.element;
        } else {
            return null;
        }
    }
    // 在任意位置插入元素
    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;
        }
    }
    // toString方法
    this.toString = function() {
        let current = head,
        string = '';

        while (current) {
            string += current.element + (current.next ? 'n' : '');
            current = current.next;
        }
        
        return string;
    }
    // indexOf 方法
    this.indexOf = function(elment) {
        let current = head,
        index = 0;
        
        while(current) {
            if (element === current.element) {
                return index;
            }
            index++;
            current = current.next;
        }

        return -1;
    }
    // remove 方法
    this.remove = function(elment) {
        let index = this.indexOf(element);
        return this.removeAt(index);
    }
    // isEmpty 方法
    this.isEmpty = function() {
        return length == 0;
    }
    // size 方法
    this.size = function() {
        return length;
    }
    // getHead 方法
    this.getHead = function() {
        return head;
    }
}

双向链表(留给大家自己思考)

集合

集合是由一组无序且唯一(即不能重复)的项组合的。这个数据结构使用了与有限集合相同的数学概念,但应用在计算机科学的数据结构中。
function Set() {
    let items = {};
    // has 方法
    this.has = function(value) {
        return items.hasOwnProperty(value);
    };
    // add 方法
    this.add = function(value) {
        if (!this.has(value)) {
            items[value] = value;
            return true;
        }
        return false;
    }
    // remove 方法
    this.remove = function(value) {
        if (this.has(value)) {
            delete items[value];
            return true;
        }
        return false;
    }
    // clear 方法
    this.clear = function() {
        items = {};
    }
    // size 方法
    this.size = function() {
        return Object.keys(items).length;
    }
    // values 方法
    this.values = function() {
        let values = [];
        for (let i = 0, keys = Object.keys(items); i< keys.length; i++) {
            values.push(items[keys[i]]);
        }
        return values;
    }
    // 并集
    this.union = function(otherSet) {
        let unionSet = new Set();

        let values = this.values();
        for (let i = 0; i < values.length; i++) {
            unionSet.add(values[i]);
        }

        values = otherSet.values();
        for (let i = 0; i < values.length; i++) {
            unionSet.add(values[i]);
        }

        return unionSet;
    }
    // 交集
    this.intersection = function(otherSet) {
        let intersectionSet = new Set();

        let values = this.values();
        for (let i = 0;i otherSet.size()) {
            return false;
        } else {
            let values = this.values();
            for (let i = 0;i< values.length;i++) {
                if (!otherSet.has(values[i])) {
                    return false;
                }
            }
            return true;
        }
    }
}

字典和散列表

实现

function Dictionary() {
    var items = {};
    // has 和 set 方法
    this.has = function(key) {
        return items.hasOwnProperty(key);
    }
    this.set = function(key, value) {
        item[key] = value;
    }
    // delete 方法
    this.delete = function(key) {
        if (this.has(key)) {
            delete items[key];
            return true;
        }
        return false;
    }
    // get 和 values 方法
    this.get = function(key) {
        return this.has(key) ? items[key] : undefined;
    }
    this.values = function() {
        var values = [];
        for(var k in items) {
            if (this.has(k)) {
                values.push(items[k]);
            }
        }

        return values;
    }
    // clear 方法
    this.clear = function() {
        items = {};
    }
    // size 方法
    this.size = function() {
        return Object.keys(items).length;
    }
    // keys 方法
    this.keys = function() {
        return Object.keys(items);
    }
    // getItems 方法
    this.getItems = function() {
        return items;
    }

}

散列表

HashTable类 也叫 HashMap类,它是Dictionary类的一种散列表是实现方式。
散列算法的作用是尽可能快的在数据结构中找到一个值。
function HashTable() {
    var table = [];
    var loseloseHashCode = function(key) {
        var hash = 0;
        for (var i = 0; i< key.length; i++) {
            hash += key.charCodeAt(i);
        }
        return hash % 37;
    }
    this.put = function(key, value) {
        var position = loseloseHashCode(key);
        console.log(position + ' - ' + key);
        table[position] = value;
    }
    this.get = function(key) {
        return table[loseloseHashCode(key)];
    }
    this.remove = function(key) {
        table[loseloseHashCode(key)] = undefined;
    }
}

Map类

es6 新增了Map类
var map = new Map();

map.set('a', 'b');

console.log(map.has('a')); // true
console.log(map.size()); // 输出1
console.log(map.keys()); // ['a']
console.log(map.values()); // ['b'];

// 和Dictionary类不同,es6的Map类的values方法和keys方法都返回Iterator,而不是值或键构成的数组。

es6 --- WeakMap类 和 WeakSet类

  • WeakMap 和 WeakSet类没有entries keys values等方法
  • 只能用对象作为键
var map = new WeakMap();
var obj = {name: 'a'};
map.set(obj, 'b');

console.log(map.has(obj)); // 输出true
console.log(map.get(obj)); // 输入'b'
map.delete(obj);

一个树结构包含一系列存在父子关系的节点。每个节点都有一个父节点(除了顶部的第一个节点)以及零个或多个子节点;

二叉树和二叉搜索树

function BinarySearchTree() {
    var Node = function(key) {
        this.key = key;
        this.left = null;
        this.right = null;
    }

    var root = null;

    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.insert = function(key) {
        var newNode = new Node(key);

        if (root = null) {
            root = newNode;
        } else {
            insertNode(root, newNode);
        }
    }

    var inOrderTraverseNode = function(node, callback) {
        if (node !== null) {
            inOrderTraverseNode(node.left, callback);
            callback(node.key);
            inOrderTraverseNode(node.right, callback);
        }
    }

    // 中序遍历
    this.inOrderTraverse = function(callback) {
        inOrderTraverseNode(root, callback);
    }

    var preOrderTraverseNode = function(node, callback) {
        if (node !== null) {
            callback(node.key);
            preOrderTraverseNode(node.left, callback);
            preOrderTraverseNode(node.right, callback);
        }
    }

    // 先序遍历
    this.preOrderTraverse = function(callback) {
        preOrderTraverseNode(root, callback);
    }

    var postOrderTraverseNode = function(node, callback) {
        if (node !== null) {
            postOrderTraverseNode(node.left, callback);
            postOrderTraverseNode(node.right, callback);
            callback(node.key);
        }
    }

    // 后序遍历
    this.postOrderTraverse = function(callback) {
        postOrderTraverseNode(root, 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 if (key > node.key) {
            node.right = removeNode(node.right,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.rihgt, aux.key);
            return node;
        }

        var findMinNode = function(node) {
            while (node && node.left !== null) {
                node = node.left;
            }
            return node;
        }
    }
}

自平衡树(AVL)

当树很深的时候,添加移除和搜索某个节点时引起一些性能问题。
var heightNode = function(node) {
    if (node === null) {
        return -1;
    } else {
        return Math.max(heightNode(node.left), heightNode(node.right)) + 1;
    }
}

var rotationRR = function(node) {
    var tmp = node.right;
    node.right = tmp.left;
    tmp.left = node;
    return tmp;
}
var rotationLL = function(node) {
    var tmp = node.left;
    node.left = tmp.right;
    tmp.right = node;
    return tmp;
}

var rotationLR = function(node) {
    node.left = rotationRR(node.left);
    return rotationLL(node);
}

var rotationRL = function(node) {
    node.right = rotationLL(node.right);
    return rotationRR(node);
}

var insertNode = function(node, element) {
    if (node === null) {
        node = new Node(element);
    } else if (element < node.key) {
        node.left = insertNode(node.left, element);

        if (node.left !== null) {
            // 确认是否需要平衡
            if ((heightNode(node.left) - heightNode(node.right) > 1)) {
                if (element < node.left.key) {
                    node = rotationLL(node);
                } else {
                    node = rotationLR(node);
                }
            }
        }
    } else if (element > node.key) {
        node.right = insertNode(node.right, element);

        if (node.right !== null) {
            // 确认是否需要平衡
            if ((heightNode(node.right) - heightNode(node.left) > 1)) {
                if (element > node.right.key) {
                    node = rotationRR(node);
                } else {
                    node = rotationRL(node);
                }
            }
        }
    }
    return node;
}

图是网络结构的抽象模型,图是一组由边连接的节点(或顶点)。学习图是重要的,因为任何关系都可以用图来表示
function Graph() {
    var vertices = [];
    var adjList = new Dictionary();

    this.addVertex = function(v) {
        vartices.push(v);
        adjList.set(v, []);
    }

    this.addEdge = function(v, w) {
        addList.get(v).push(w);
        addList.get(w).push(v);
    }

    this.toString = function() {
        var s = '';
        for (var i = 0; i< vertices.length;i++) {
            s += vertices[i] + ' -> ';
            var neighbors = adjList.get(vertices[i]);
            for (var j = 0;j

你可能感兴趣的:(javascript)