js版数据结构_04链表(1)

js版数据结构_04链表(1)

从本篇开始我将用三篇博文写总结js对链表的操作

在本篇博文你会了解到:

  • 什么是链表
  • 单链表的实现

1.什么是链表

在这里插入图片描述

  • 这种东西有什么优点,先说说数组。所有的高级语言都有数组这一数据结构吧,我们都清除数组是一块地址连续的储存单元。以c为例,声明数组的变量名便是储存了这片连续空间的首地址。因为它连续我们可以很方便的存取数组中的每一个元素,但是我想增删元素呢。它的缺点就是在与的一旦有增删操作就可能造成大量元素位置的变化,这并不是我们想要看到的吧
  • 所以链表这种使用结构和指针创建的强大数据结构便被开发出来,链表的存储单元并不连续。拿单链表为例,它的每一个节点均有两个域。即数据域和“指针域”,指针域有来保存下一节点的地址
  • 唯一的遗憾在与js虽然是c搞出来的,但是没有继承老爹的最大优点。拿不到内存地址。但好在js的灵活,它可以套娃娃(接下来你便可以体会的到了)
    额额,写了这么多不废话了。

创建单链表类:(可能c不太好的不理解为什么这里要创建节点类,链表的节点是由数据域和指针域构成的,没有现成的数据结构可以用来保存它们。既然是c的儿子,老爹可以用结构和指针创建,那么js就用类的成员变量来模仿呗)

	  // 创建一个节点类
        class LNode{
            constructor(e){
                this.element=e;
                this.next=null;
            }
        }
        //链表类
        class LinkList{
            constructor(){
                this.count=0;
                this.head=null;
            }
        }

这里我们不管什么头插尾插有无头节点的那一套。我们还是和前俩节相似,实现以下功能。

  • push(element) 向尾部插一个
  • insert(element, position) 向指定位置插一个
  • getElementAt(index) 获取指定位置的元素
  • remove(element) 移出元素
  • indexOf(element) 返回该元素的位置
  • removeAt(position) 移出指定位置的元素
  • isEmpty() 判空
  • size() 链表长度

2. 实现

还是先来体验套娃娃吧。先实现push,毕竟没有真正的指针,相信大家对实现指针域的方法还是有一丝丝好奇的吧

 push(e) {
                const node = new LNode(e);
                let current = this.head;
                // 先看链表是不是空的
                if (current == null) {
                    this.head = node;
                } else {
                    // 想一下最后一个节点的特点,最后一个节点的next为null
                    while (current.next) {
                        current = current.next;
                    }
                    current.next = node;
                }
            }
//测试代码
        let linkList = new LinkList();
        linkList.push(1)
        linkList.push(2)
        linkList.push(3)
        linkList.push(4)
        console.log(linkList);

看图:
在这里插入图片描述
哈哈,好玩不。我大js虽然没有指针,但是做不了你兄弟我做你亲爸爸,我把你整个节点作为我next属性的一个属性值,对象嵌套

其他功能的实现:
removeAt方法

            removeAt(index) {
                // 先判读这个index是否越界
                if (index >= 0 && index < this.count) {
                    let current = this.head;
                    // 看index是不是head位置
                    if (index === 0) {
                        this.head = current.next;
                    } else {
                        let previous;
                        // 找位置
                        for (let i = 0; i < index; i++) {
                            previous = current;
                            current = current.next;
                        }
                        previous.next = current.next;
                    }
                    this.count--;
                    return current.element;

                } else {
                    return undefined;
                }
            }

如果有些迷的话,回忆一下c
在这里插入图片描述
想起来了吧,没错c中这里的关键代码是p->next=q->next;然后再把q指针所指的节点delete掉。

js这里也是一样的(丑图理解)单链表的特点就是节点得顺着头节点往下找啊
在这里插入图片描述
获取指定位置的节点

            getElementAt(index) {
                    // 判断是否越界
                    if (index >= 0 && index < this.count) {
                        let node = this.head;
                        for (let i = 0; i < index && node != null; i++) {
                            node = node.next;
                        }
                        return node;
                    } else {
                        return undefined;
                    }
                }

在任意位置插入

扫描二维码关注公众号,回复: 11278779 查看本文章
               // 在任意位置插入
            insert(e, index) {
                    // 还是先判断是否越界
                    if (index >= 0 && index < this.count) {
                        let node = new LNode(e);

                        // 0号位置判断
                        if (index == 0) {
                            let current = this.head;
                            node.next = current;
                            this.head = node;
                        } else {
                            // 先找到索引的前一号位置,一截两瓣
                            let pre = this.getElementAt(index - 1);
                            let current = pre.next;
                            pre.next = node;
                            node.next = current;

                        }
                        this.count++;
                        return true;
                    } else {
                        return undefined;
                    }
                }

返回指定元素的位置

               // 返回一个元素的位置
            indexOf(e) {
                    // 到循环遍历链表就ok
                    let current = this.head;
                    for (let i = 0; i < this.count && current != null; i++) {
                        if (current.element == e) {
                            return i;
                        } else {
                            current = current.next;
                        }
                    }
                    // 循环完链表仍然没有找到
                    return -1;
                }

删除一个指定元素(仅匹配第一个),返长度,判空

               // 删除指定元素
            remove(e) {
                // 我们前面实现一个根据位置删除
                // 还实现了一个根据指定元素返回位置
                let index = this.indexOf(e);
                return this.removeAt(index);
            }
            size() {
                return this.count;
            }
            isEmpty() {
                return this.count == 0;
            }
        }

猜你喜欢

转载自blog.csdn.net/qq_41086511/article/details/105319607