资讯专栏INFORMATION COLUMN

javascript数据结构学习笔记

mingde / 770人阅读

摘要:数据结构数组方法一数组添加元素开头插入尾部删除头部删除数组合并迭代器方法会迭代数组中每个元素,直到返回。这个数据结构使用了与有限集合相同的数学概念,但应用在计算机科学的数据结构中。散列算法的作用是尽可能快的在数据结构中找到一个值。

数据结构 数组 方法
//一、数组
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           
               
                                           
                       
                 

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/102335.html

相关文章

  • 重学前端学习笔记(七)--JavaScript对象:面向对象还是基于对象?

    摘要:对象有状态对象具有状态,同一对象可能处于不同状态之下。中对象独有的特色对象具有高度的动态性,这是因为赋予了使用者在运行时为对象添改状态和行为的能力。小结由于的对象设计跟目前主流基于类的面向对象差异非常大,导致有不是面向对象这样的说法。 笔记说明 重学前端是程劭非(winter)【前手机淘宝前端负责人】在极客时间开的一个专栏,每天10分钟,重构你的前端知识体系,笔者主要整理学习过程的一些...

    mayaohua 评论0 收藏0
  • 重学前端学习笔记(七)--JavaScript对象:面向对象还是基于对象?

    摘要:对象有状态对象具有状态,同一对象可能处于不同状态之下。中对象独有的特色对象具有高度的动态性,这是因为赋予了使用者在运行时为对象添改状态和行为的能力。小结由于的对象设计跟目前主流基于类的面向对象差异非常大,导致有不是面向对象这样的说法。 笔记说明 重学前端是程劭非(winter)【前手机淘宝前端负责人】在极客时间开的一个专栏,每天10分钟,重构你的前端知识体系,笔者主要整理学习过程的一些...

    yy736044583 评论0 收藏0
  • 重学前端学习笔记(七)--JavaScript对象:面向对象还是基于对象?

    摘要:对象有状态对象具有状态,同一对象可能处于不同状态之下。中对象独有的特色对象具有高度的动态性,这是因为赋予了使用者在运行时为对象添改状态和行为的能力。小结由于的对象设计跟目前主流基于类的面向对象差异非常大,导致有不是面向对象这样的说法。 笔记说明 重学前端是程劭非(winter)【前手机淘宝前端负责人】在极客时间开的一个专栏,每天10分钟,重构你的前端知识体系,笔者主要整理学习过程的一些...

    xingpingz 评论0 收藏0
  • 26天学通前端开发(配资料)

    摘要:网上有很多前端的学习路径文章,大多是知识点罗列为主或是资料的汇总,数据量让新人望而却步。天了解一个前端框架。也可以关注微信公众号晓舟报告,发送获取资料,就能收到下载密码,网盘地址在最下方,获取教程和案例的资料。 前言 好的学习方法可以事半功倍,好的学习路径可以指明前进方向。这篇文章不仅要写学习路径,还要写学习方法,还要发资料,干货满满,准备接招。 网上有很多前端的学习路径文章,大多是知...

    blair 评论0 收藏0
  • javascript高程3 学习笔记(一)

    摘要:元素,当浏览器不支持脚本数据结构有如下中基本数据结构操作符,用来检测给定变量的数据类型结果都是,声明没初始化,使用生命变量但未对其进行初始化的,默认没有进行声明,传递给函数会导致一个错误,对于未声明变量这么操作没什么意义比如,也是返回。 javascript简史 微软IE和网景在浏览器上的竞争 ECMAScript,由ECMA-262定义,提供核心语言功能 `ECMA 欧洲计算机制...

    you_De 评论0 收藏0

发表评论

0条评论

mingde

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<