JavaScript实现单向链表

JavaScript 本身提供了十分好用的数据类型,以满足大家的日常使用。单靠 Array  和 Object 也的确足够应付日常的绝大部分需求,这也导致了很多前端er对数据结构这一块不是十分的了解。

数据结构是 CS 的必修科目,前端这个圈子非科班的童鞋比例较高,相信很多人对数据结构的了解并不多。虽然本人大学读的也是 CS,但那时候上课基本都在睡觉,数据结构也是学得一塌糊涂,现在也基本上全忘了。

那下面我们来了解一下,如何用 JavaScript 来实现一个 单向链表

维基百科中,对链表的描述如下:

链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer)。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而顺序表相应的时间复杂度分别是O(logn)和O(1)。

由此可以知道,链表和数据相比,会具有一下优点:

  1. 不需要预先分配内存(在静态语言中,数组是需要预先分配内存空间的,空间分配后不能再改变??)
  2. 插入和删除元素不需要移动其余元素,效率更高

JavaScript 作为一门动态语言,其中的数组也是动态数组,不需要预先分配内存的。在使用过程中还可以动态增减数组长度,这直接让 Array 类型的适用范围扩大了不少。

数组在进行插入和删除元素时,是十分麻烦的事情,而这方面却是链表的优势。在查找元素的效率方面,链表就比不上数组那么方便快捷了。

单向链表,是链表中最简单的一种,其特点是链表的链接方向是单向的,对链表的访问要通过顺序读取从头部开始。

下面我们看看 单向链表 的图示:

可以看到,链表中每一个 item(元素) 都有两个部分组成:data 和 next。其中 data 用于存储数据,是真正的存储区。而 next 用于存放地址,用于指向下一个 item。

下面我们看看怎么设计一个单向列表。

一般的单向列表,都具有以下的属性和方法:

  • first:指向第一个 item
  • last:指向最后一个 item
  • length:链表的 item 数量
  • get():获取指定位置的 item
  • set():修改指定位置的 item
  • add():插入一个新的 item 到指定位置
  • remove():移除指定位置的 item
  • clear():清空所有 item

为了方便实用,还提供了部分语法糖:

  • addFirst():插入一个新的 item 到链表头部
  • addLast():插入一个新的 item 到链表尾部
  • removeFirst():移除第一个 item
  • removeLast():移除最后一个 item
  • toString():列表以 "10 -> a -> [1,2] -> 3.14" 方式输出

下面是 SinglyLinkedList 的类:

var SinglyLinkedList = function () {

    function SinglyLinkedList() {
        this.length = 0;
        this.first = null;
        this.last = null;
    }

    /**
     * 根据索引获取 item
     * @param   {Number}    index   链表索引
     * @returns {*}
     */
    SinglyLinkedList.prototype.get = function (index) {
        if (typeof index !== ‘number‘ || index < 0 || index >= this.length) {
            return undefined;
        }

        var item = this.first;
        for (var i = 0; i < index; i++) {
            item = item.next;
        }
        return item;
    };

    /**
     * 根据索引设置 item 的内容
     * @param   {Number}    index   链表索引
     * @param   {*}         value   需要设置的值
     * @returns {*}
     */
    SinglyLinkedList.prototype.set = function (index, value) {
        if (typeof index !== ‘number‘ || index < 0 || index >= this.length) {
            return false;
        }

        var item = this.get(index);
        item.data = value;
        return item;
    };

    /**
     * 根据索引位置插入新的 item
     * @param   {Number}    index   链表索引
     * @param   {*}         value   需要设置的值
     * @returns {*}
     */
    SinglyLinkedList.prototype.add = function (index, value) {
        if (typeof index !== ‘number‘ || index < 0 || index > this.length || index === undefined) {
            return false;
        }

        var item = {
            data: value,
            next: null
        };

        if (this.length > 0) {
            if (index === 0) {
                item.next = this.first;
                this.first = item;
            } else if (index === this.length) {
                this.last.next = item;
                this.last = item;
            } else {
                var prevItem = this.get(index - 1),
                    nextItem = this.get(index);
                item.next = nextItem;
                prevItem.next = item;
            }
        } else {
            this.first = item;
            this.last = item;
        }

        this.length++;
        return item;
    };

    /**
     * 根据索引删除 item
     * @param   {Number}    index   链表索引
     * @returns {boolean}
     */
    SinglyLinkedList.prototype.remove = function (index) {
        if (typeof index !== ‘number‘ || index < 0 || index >= this.length) {
            return false;
        }

        var item = this.get(index);

        if (this.length > 1) {
            if (index === 0) {
                this.first = item.next;
            } else if (index === this.length - 1) {
                this.last = this.get(this.length - 2);
                this.last.next = null;
            } else {
                this.get(index - 1).next = item.next;
            }
        } else {
            this.first = null;
            this.last = null;
        }

        item = null;
        this.length--;
        return true;
    };

    /**
     * 清空整个单链表
     * @returns {boolean}
     */
    SinglyLinkedList.prototype.clear = function () {
        this.first = null;
        this.last = null;
        this.length = 0;
        return true;
    };

    SinglyLinkedList.prototype.addFirst = function (value) {
        return this.add(0, value);
    };

    SinglyLinkedList.prototype.addLast = function (value) {
        return this.add(this.length, value);
    };

    SinglyLinkedList.prototype.removeFirst = function () {
        return this.remove(0);
    };

    SinglyLinkedList.prototype.removeLast = function () {
        return this.remove(this.length - 1);
    };

    SinglyLinkedList.prototype.toString = function () {
        var arr = [],
            item = {};

        if (this.length) {
            do {
                item = item.next || this.get(0);
                arr.push(typeof item.data === ‘object‘ ? JSON.stringify(item.data).replace(/\"/g, ‘‘) : item.data);
            } while (item.next);
        }

        return arr.join(‘ -> ‘);
    };

    return SinglyLinkedList;
}();

使用方法很简单:

var sList = new SinglyLinkedList();
sList.addLast(‘a‘);
sList.addFirst(10);
sList.addLast(3.14);
sList.add(2, [1, 2]);
sList.addLast({a: 1, b: 2});
console.log(sList.toString());  // "10 -> a -> [1,2] -> 3.14 -> {a:1,b:2}"
console.log(sList.length);   // 5
sList.removeFirst();
sList.removeLast();
console.log(sList.toString());  // "a -> [1,2] -> 3.14"
console.log(sList.length);   // 3

参考资料:

http://zh.wikipedia.org/wiki/%E9%93%BE%E8%A1%A8

http://www.cnblogs.com/skywang12345/p/3561803.html#a33

本文作者:Maple Jan

本文链接:http://www.cnblogs.com/maplejan/p/3903749.html

JavaScript实现单向链表

时间: 2024-10-21 02:38:34

JavaScript实现单向链表的相关文章

【转】单向链表(单链表)的Java实现

最近被问到链表,是一个朋友和我讨论Java的时候说的.说实话,我学习编程的近一年时间里,学到的东西还是挺少的.语言是学了Java和C#,关 于Web的学了一点Html+css+javascript.因为比较偏好,学习WinForm时比较认真,数据库操作也自己有所研究.但链表这个东西我 还真没有学习和研究过,加上最近自己在看WPF,而课程也到了JSP了,比较紧. 但是我还是抽了一个晚上加半天的时间看了一下单向链表.并且使用Java试着写了一个实例出来.没有接触过链表的朋友可以作为参考,希望大家多提

数据结构与算法学习-单向链表的实现

链表(Chain本文所说链表均为单向链表,以下均简称单向链表)实际上是由节点(Node)组成的,一个链表拥有不定数量的节点.而向外暴露的只有一个头节点(Head),我们对链表的所有操作,都是直接或者间接地通过其头节点来进行的. 节点(Node)是由一个需要储存的对象及对下一个节点的引用组成的.也就是说,节点拥有两个成员:储存的对象.对下一个节点的引用. 这样说可能大家不是很明白,我贴一张图大家可能更容易理解. package LinkedList; /** * <p><strong>

算法总结之 反转部分单向链表

给定单链表的表头节点head, 以及两个整数from 和 to, 在单向链表上把fro个节点到第to个节点这一部分进行反转 思路: 本题 有可能存在换头的问题,所以函数应该返回调整后的新的头节点 1 判断是否满足 1<=from<=to<=N 如果不满足,直接返回原来的头节点 2 找到第from-1个节点pre和第to+1个节点tPos,fPre即要反转部分的前一个节点,tPos是反转部分的后一个节点,把反转部分先反转,然后正确的链接fPre和tPos package TT; impor

C语言之字符单向链表

/* * @Author: suifengtec * @Date:   2017-09-02 16:06:33 * @Last Modified by:   suifengtec * @Last Modified time: 2017-09-02 20:47:13 **/ /* 字符单向链表 gcc -o a.exe main.c && a  */ #include <stdio.h> #include <stdlib.h> #include <stdbool

C++__单向链表(练习)

单向链表 link.h #ifndef LINK_H_ #define LINK_H_ #define HEADER 0 #define TAIL -1 typedef int data_type; enum LINK_OP { LINK_ERR = -1, LINK_OK }; class LINK { private: data_type data; LINK *next; public: LINK(); LINK(data_type data); virtual ~LINK(); data

单向链表模板

写个单向链表模板练练手: #include <bits/stdc++.h> using namespace std; //create // delete // modify // search class Node{ public: int data; Node* ptr; Node(int elem= 0, Node* node= NULL){ this->data= elem; this->ptr= NULL; } }; class MyList{ private: Node

C#学习单向链表和接口 IList&lt;T&gt;

作者:乌龙哈里 时间:2015-11-04 平台:Window7 64bit,Visual Studio Community 2015 参考: MSDN 索引器(C# 编程指南) <数据结构(C#语言版)>下载 When to use IEnumerable, ICollection, IList and List 章节: 单向链表元素 定义单向链表操作接口 逐步实现单向链表 正文: 前面学习了 IEnumerable<T>.IComparable<T>.ICollec

循环单向链表(约瑟夫环)

#include <stdio.h> #include <stdlib.h> typedef struct List { int data; struct List *next; }List; //创建循环单向链表n为长度 List *list_create(int n) { List *head, *p; int i; head = (List *)malloc(sizeof(List)); p = head; p->data = 1; //创建第一个结点 for (i =

给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点

#include <iostream> #include <string.h> #include <stdlib.h> #include <stack> using namespace std; struct Node { int data; struct Node* next; }; struct Node* create_list(int len) { if (len <= 0) return NULL; struct Node* head; st