资讯专栏INFORMATION COLUMN

[ JavaScript ] 数据结构与算法 —— 链表

wfc_666 / 1235人阅读

摘要:每个元素由一个存储元素本身的节点和一个指向下一个元素的引用也称指针或链接组成。相对于传统的数组,链表的一个好处在于,添加或移除元素的时候不需要移动其他元素。然而,链表需要使用指针,因此实现链表时需要额外注意。

本篇主要有三部分

什么是链表

链表的实现

链表的变种

源码地址:https://github.com/yhtx1997/S...

另外,今天2019年2月18日上午发现 2048-vue 版,代码版本不对,且最新版本遗失,无奈只得重新修复了下
2048-vue地址: https://github.com/yhtx1997/S...

什么是链表

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

注:其中 00 06 10 12 18 为假定在内存中的地址

我将已经做好的链表存入数据,然后在控制台打印出来是这样的:

它看起来就像是这样的,一层套一层

其实应该是下面这样,类似于栓狗的铁链

链表的实现 链表功能

添加元素

获取指定位置元素

在指定位置插入元素

移除指定位置的元素

返回指定元素的位置

移除指定元素

是否为空

长度

获取表头

清空链表

转换为字符串输出

// 链表元素
class Node {
    constructor(element) {
        this.element = element; // 元素
        this.next = undefined; // 指向下一个元素
    }
}
class LinkedList {
    // 构造函数声明一些全局变量
    constructor(){
        this.count = 0; // 长度
        this.head = undefined; // 第一个元素
    }
    // 添加元素
    push(element) {
        
    }
    // 获取指定位置元素
    getElementAt(index) {
        
    }
    // 在指定位置插入元素
    insert(element, index) {
        
    }
    // 移除指定位置的元素
    removeAt(index) {
    
    }
    // 返回指定元素的位置
    indexOf(element) {
        
    }
    // 移除指定元素
    remove(element) {
        
    }
    // 是否为空
    isEmpty() {
        
    }
    // 长度
    size() {
        
    }
    // 获取表头
    getHead() {
       
    }
    // 清空链表
    clear() {
        
    }
    // 转换为字符串输出
    toString() {
        
    }
}
代码实现
class LinkedList {
    // 构造函数声明一些全局变量
    constructor(){
        this.count = 0; // 长度
        this.head = undefined; // 第一个元素
    }
    // 添加元素
    push(element) {
        const node = new Node(element);
        if (this.head === undefined) {
            this.head = node;
        } else {
            let current = this.head;
            while (current.next !== undefined) {
                current = current.next;
            }
            current.next = node;
        }
        this.count++;
    }
    // 获取指定位置元素
    getElementAt(index) {
        // 判断不是空链表
        if (this.isEmpty() || index > this.count || index < 0) { 
            // 非空才能继续处理
            // 判断不大于最大长度,不小于最小长度(0)
            return undefined;
        }
        // 循环找到元素
        let current = this.head;
        for (let i = 0; i < index; i++){
            current = current.next;
        }
        return current;// 返回找到的元素
    }
    // 在指定位置插入元素
    insert(element, index) {
        // 创建一个元素
        let current = new Node(element);
        // 首先确定是不是在首位置插入
        if (index === 0){
            current.next = this.head;
            this.head = current;
        } else {
            // 找到指定位置前一个元素
            let previous = this.getElementAt(index - 1);
            // 将前一个元素的 next 赋值给插入元素的 next
            current.next = previous.next;
            // 将插入元素的 node 赋值给前一个元素的 next
            previous.next = current;
        }
        this.count++;
    }
    // 移除指定位置的元素
    removeAt(index) {
        let current = this.head;
        if (index === 0){
            this.head = current.next;
        } else {
            // 找到这个元素和这个元素之前的元素
            let previous = this.getElementAt(index - 1);
            current = previous.next;
            // 将这个元素的 next 赋值给这个元素之前元素的 next
            previous.next = current.next;
        }
        this.count--;
        // 返回要移除的元素
        return current.element;
    }
    // 返回指定元素的位置
    indexOf(element) {
        // 从头开始找
        let current = this.head;
        // 不超过最大长度
        for (let i = 0; i < this.size() && current != null; i++){
            if (current.element === element){ // 找到相等的就返回下标
                return i;
            }
            current = current.next;
        }
        return -1;
    }
    // 移除指定元素
    remove(element) {
        // 获取指定元素位置
        let index = this.indexOf(element);
        // 移除指定位置元素
        return this.removeAt(index);
    }
    // 是否为空
    isEmpty() {
        return this.size() === 0;
    }
    // 长度
    size() {
        return this.count;
    }
    // 获取表头
    getHead() {
        return this.head;
    }
    // 清空链表
    clear() {
        this.head = undefined;
        this.count = 0;
    }
    // 转换为字符串输出
    toString() {
        if (this.head == null) {
            return "";
        }
        let objString = `${this.head.element}`;
        let current = this.head.next;
        for (let i = 1; i < this.size() && current != null; i++) {
            objString = `${objString},${current.element}`;
            current = current.next;
        }
        return objString;
    }
}
let a = new LinkedList();
a.push("a");
a.push("b");
a.push("c");
a.push("d");
a.push("e");
a.push("f");
a.push("h");
a.push("i");
a.push("j");
a.push("k");
a.push("l");
a.push("m");
a.push("n");
a.push("o");
a.push("p");
a.push("q");
a.remove("a");
a.insert("a",1);
console.log(a);

插入元素图解:

现在有狗链两节,我要在中间加一节

先把两节分开,

然后把前边的尾部与要加的头部相连,然后把要加的尾部与后边的头部相连

0 连 xx , xx 连 1

链表的变种 双向链表

我们已经知道链表的每个元素由一个存储元素本身的节点和一个指向下一个元素的引用(也称指针或链接)组成,双向链表除了这个基本特性,每个元素还包含一个指向前一个元素的引用,如图所示:

循环链表

循环链表就是链表的最后一个指向下一个元素的引用指向了第一个元素,使其成为循环链表

双向循环链表

双向循环链表就是双向链表的第一个元素指向前一个的引用指向了最后一个元素,而最后一个元素指向下一个元素的引用指向了第一个元素,如图所示:

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

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

相关文章

  • 学习JavaScript数据结构算法(二):链表

    摘要:实现移除给定的元素要移除的元素返回值表示移除成功方法说明移除单向链表中某个位置的元素。的前端乐园原文链接寒假前端学习学习数据结构与算法二链表 本系列的第一篇文章: 学习JavaScript数据结构与算法(一),栈与队列第二篇文章:学习JavaScript数据结构与算法(二):链表第三篇文章:学习JavaScript数据结构与算法(三):集合第四篇文章:学习JavaScript数据结构与...

    lolomaco 评论0 收藏0
  • JavaScript数据结构算法(四) —— 双向链表

    摘要:链表链表存储有序的元素集合,但不同于数组,链表中的元素在内存中并不是连续放置的。链表又包括单向链表和双向链表双向链表双向链表与单向链表很是相像。但在双向链表中,还有指向上一个节点的链接,是双向的。 链表 链表存储有序的元素集合,但不同于数组,链表中的元素在内存中并不是连续放置的。每个元素由一个存储元素本事的节点和一个指向下一个元素的引用组成。相对于传统的数组,链表的一个好处在于,添加或...

    Youngdze 评论0 收藏0
  • JavaScript数据结构算法——链表

    摘要:链表数据结构链表存储有序的元素集合,但不同于数组,链表中的元素咋内存中并不是连续放置的每个元素有一个存储元素本身的节点和一个指向下一个元素的引用组成。 1.链表数据结构 链表存储有序的元素集合,但不同于数组,链表中的元素咋内存中并不是连续放置的每个元素有一个存储元素本身的节点和一个指向下一个元素的引用组成。下图展示了一个链表的结构:showImg(https://segmentfaul...

    chunquedong 评论0 收藏0
  • Javascript数据结构算法》笔记-「链表

    摘要:链表数据结构与算法第五章链表数据结构链表不同与数组数组要插入或者移入一个元素的成本很高,因为所有元素都需要移动位置。 JavaScript-链表 《Javascript数据结构与算法》第五章 5.1 链表数据结构 链表不同与数组 数组要插入或者移入一个元素的成本很高,因为所有元素都需要移动位置。 链表插入或者移动一个元素时很高效,因为并不需要移动其他的元素位置。 链表存储元素的方式...

    gclove 评论0 收藏0
  • Javascript数据结构算法(二)循环链表有序链表

    摘要:循环链表可以像单向链表引用,也可以像双向链表有双向引用。以下就以如何创建栈数据结构为例。 循环链表可以像单向链表引用,也可以像双向链表有双向引用。性能上也跟双向链表差不多,如果position大于length/2,那就可以从尾部开始迭代,可以减少迭代的元素。唯一的区别在于最后一个元素指向下一个元素的指针(tail.next)不是undefine,而是第一个元素(head)。接下来来看一...

    YacaToy 评论0 收藏0
  • JavaScript数据结构算法(三) —— 单向链表

    摘要:链表链表存储有序的元素集合,但不同于数组,链表中的元素在内存中并不是连续放置的。相对于传统的数组,链表的一个好处在于,添加或者删除元素的时候不需要移动其他元素。 链表 链表存储有序的元素集合,但不同于数组,链表中的元素在内存中并不是连续放置的。每个元素由一个存储元素本事的节点和一个指向下一个元素的引用组成。相对于传统的数组,链表的一个好处在于,添加或者删除元素的时候不需要移动其他元素。...

    李涛 评论0 收藏0

发表评论

0条评论

wfc_666

|高级讲师

TA的文章

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