zoukankan      html  css  js  c++  java
  • JavaScript数据结构 --- 链表

    JavaScript数据结构 --- 链表

    数组不总是组织数据的最佳数据结构,因为在很多编程语言中,数组的长度是固定的,所以当数组被数据填满时,在要加入数据会很困难。在数组中添加和删除元素也很麻烦,需要移动其它元素。
    JavaScript中的数组是对象,与其它语言(Java,C++)相比,效率很低。我们可以考虑用链表来替代它。

    链表是一组节点组成的集合。每个节点都使用一个对象的引用指向它的后继。指向另一个节点的引用叫

    链表元素靠相互之间的关系进行引用,许多链表的实现都在链表最前面有一个特殊的节点,叫头结点,链表的尾元素可以指向一个 null 节点。
    link

    链表中插入节点效率很高。插入节点时,需要修改它前面的节点(前驱),使其指向新加入的节点,而新加入的节点则指向原来前驱指向的节点。
    link2

    从链表中删除一个元素也很简单。将待删除元素的前驱节点指向待删除元素的后继节点。
    link3

    1. 设计一个基于对象的链表


    1.1 Node类

    Node 类包含两个属性:element 用来保存节点上的数据,next 用来保存指向下一个节点的链接。

    function Node(element) {
    	this.element = element;
    	this.next = null;
    }
    

    1.2 LinkedList类

    LList 类提供了对链表进行操作的方法。

    function LList() {
    	this.head = new Node("head"); // 头节点
    	this.find = find;
    	this.insert = insert;
    	this.remove = remove;
    	this.display = display;
    }
    

    1.3 插入新节点
    find() 方法遍历链表,查找给定数据,如果找到数据,该方法就返回保存该数据的节点。

    function find(item) {
    	var currNode = this.head;
    	while (currNode.element != item) {
    		currNode = currNode.next;
    	}
    	return currNode;
    }
    

    在一个已知节点后面插入节点时,用 find() 找到这个节点后,就可以将新节点插入链表了。首先,将新节点的 next 属性设置为这个节点的 next 属性对应的值,然后设置这个节点的 next 属性指向新节点。

    function insert(newElement, item) {
    	var newNode = new Node(newElement);
    	var current = this.find(item);
    	newNode.next = current.next;
    	current.next = newNode;
    }
    

    定义display()方法用来显示链表中的元素。

    function display() {
    	var currNode = this.head;
    	while (!(currNode.next == null)) {
    		cosole.log(currNode.next.element);
    		currNode = currNode.next;
    	}
    }
    

    1.4 从链表中删除一个节点

    从链表中删除节点时,需要先找到待删除节点前面的节点。找到这个节点后,修改它的 next 属性,使其不再指向待删除节点,而是指向待删除节点的下一个节点。
    可以先定义一个方法 findPrevious() 来遍历链表中的元素,检查每一个节点的下一个节点中是否存储着待删除数据。如果找到,返回该节点(待删除节点的”前一个“节点),这样就可以修改它的 next 属性了。

    function findPrevious(item) {
    	var currNode = this.head;
    	while (!(currNode.next == null) && (currNode.next.element != item)) {
    		currNode = currNode.next;
    	}
    	return currNode;
    }
    

    再来写 remove() 方法。

    function remove(item) {
    	var prevNode = this.findPrevious(item);
    	if (!(prevNode.next == null)) {
    		prevNode.next = prevNode.next.next;
    	}
    }
    

    这个地址包含了完整的代码

    LinkedList


    双向链表
    从链表的头节点遍历到尾节点很容易,但从后往前遍历比较难。可以通过给 Node 对象增加一个属性,该属性存储指向前驱节点的链接。
    2link

    先为 Node 类增加一个 previous 属性。

    function Node(element) {
    	this.element = element;
    	this.next = null;
    	this.previous;
    }
    

    双向链表的 insert() 方法需要设置新节点的 previous 属性,使其指向该节点的前驱。

    function insert(newElement, item) {
    	var newNode = new Node(newElement);
    	var current = this.find(item);
    	newNode.next = current.next;
    	newNode.previous = current;
    	current.next = newNode;
    }
    

    双向链表的 remove() 方法比单向链表的效率更高,不需要查找前驱节点。首先需要在链表中找出存储待删除数据的节点,然后设置该节点前驱的 next 属性,使其指向待删除节点的后继;设置该节点后继的 previous 属性,使其指向待删除节点的前驱。
    2link2
    remove() 方法的定义。

    function remove(item) {
    	var currNode = this.find(item);
    	if (!(currNode == null)) {
    		currNode.previous.next = currNode.next;
    		currNode.next.previous = currNode.previous;
    		currNode.next = null;
    		currNode.previous = null;
    	}
    }
    

    给双向链表增加一个 findLast() 工具方法,用来查找最后的节点.

    function findLast() {
    	var currNode = this.head;
    	while (!(currNode.next == null)) {
    		currNode = currNode.next;
    	}
    	return currNode;
    }
    

    在 findLast() 的基础上写一个反向显示双向链表中的元素的方法 dispReverse() 。

    function dispReverse() {
    	var currNode = this.head;
    	currNode = this.findLast();
    	while (!(currNode.previous == null)) {
    		console.log(currNode.element);
    		currNode = currNode.previous;
    	}
    }
    

    双向链表 LList 完整代码。

    LList


    参考资料:
    JavaScript高级程序设计
    JavaScript MDN
    Data Structures and Algorithms with JavaScript

  • 相关阅读:
    前端面试集锦
    nodeJs上传附件
    逻辑于 逻辑或
    webpack 学习笔记 (一)
    yum 安装mongodb mysql
    闭包面试提 (2)
    主动的重要性
    1.1一天一题:逆转字符串
    编程提高:一天一道编程题
    iconv将文件编码从gb2312 转换为utf-8
  • 原文地址:https://www.cnblogs.com/zhoufulin/p/5006044.html
Copyright © 2011-2022 走看看