前端数据结构----单链表

大家好,今天给大家分享一下单链表;单链表,顾名思义,一个一个的表由一根链条连接在一起;说到单链表,我们肯定会想到数组,同时脑海中还会浮现一个问题---两个不都能实现增删改查嘛,好好的数组不用却非要用链表。就这一问题呢,我来说一下两者的区别吧,这个问题也是面试的高频问点,所以大家一定要记牢:

数组存在的缺点:

1.数组的创建需要申请一片连续的空间,也就是一整块内存,并且大小是固定的。所以当数组的容量不能满足需求时需要进行扩容处理

2.在数组的开口或中间位置插入数据时成本很高,需要进行大量元素的移动

链表的优点:

1.链表中的内存不必是连续的空间,可以充分利用计算机的内存实现灵活的内存动态管理

2.链表不必在创建时就确定大小,并且大小可以无限的延伸下去

3.链表在插入和删除数据时时间复杂度可以达到O(1),效率很高

链表的缺点:

1.链表访问任何一个位置的元素时,都需要从头开始访问

2.无法通过下标值直接访问元素,需要从头开始一个个访问

3.虽然可以轻松地到达下一个节点,但是回到前一个节点是很难的

对于初学者来说 ,不理解上面的总结很正常,可以先略过,让我先带你解释一下链表的原理并去实现它的功能之后你再回头看上面的总结,相信你一定会恍然大悟的,哈哈哈哈!!!!

前面说到链表,其实生活中也有许多链表的影子,比如火车,火车的整体由一个车头和许多车厢组成,和链表的结构特别像

 下面来看一看链表的结构:

 

有没有觉得链表的结构和火车很像呢,有了这样的图,那我们就一步一步的来实现链表吧 

首先,创建一个单链表的构造函数:

        // 构造一个单链表函数
        function LinkedList() {
            this.head = null // 单链表的头结点
            this.length = 0 // 单链表的长度
            // 封装一个节点类来存放数据项和下一个数据位置的项
            function Node(data) {
                this.data = data
                this.next = null
            }
        }

这样,一个简单的链表就封装好了;接下来就来一个一个实现链表的功能吧

1. insert插入数据

            // 单链表的插入操作
            LinkedList.prototype.insert = function (position, data) {
                var newNode = new Node(data)
                // 越界判断
                if (position < 0 || position > this.length) return false
                // 特殊情况:当插入到第0个位置时
                if (position === 0) {
                    newNode.next = this.head
                    this.head = newNode
                } else {
                    var index = 0
                    var pre = this.head
                    while (++index < position) {
                        pre = pre.next
                    }
                    newNode.next = pre.next
                    pre.next = newNode
                }
                this.length += 1
                return true
            }

流程图解:

 

2. append追加操作

            // 单链表的追加操作
            LinkedList.prototype.append = function (data) {
                var newNode = new Node(data)
                if (this.length === 0) {
                    this.head = newNode
                } else {
                    var current = this.head
                    while (current.next) {
                        current = current.next
                    }
                    current.next = newNode
                }
                this.length += 1
            }

流程图解:

3. get根据索引获取单链表中的某个元素

            // 根据索引获取单链表中的某个元素
            LinkedList.prototype.get = function (position) {
                // 越界判断
                if (position < 0 || position >= this.length) return null
                var index = 0
                var current = this.head
                while (current) {
                    if (index === position) {
                        return current.data
                    }
                    current = current.next
                    index++
                }
            }

4. indexOf获取单链表中某个元素的索引

            // 获取单链表中某个元素的索引
            LinkedList.prototype.indexOf = function (data) {
                var current = this.head
                var index = 0
                while (current) {
                    if (current.data === data) {
                        return index
                    }
                    index++
                    current = current.next
                }
                return -1
            }

5. update修改单链表中某个元素的值

            // 修改单链表中某个元素的值
            LinkedList.prototype.update = function (position, element) {
                if (position < 0 || position >= this.length) return false
                var index = 0
                var current = this.head
                while (index++ < position) {
                    current = current.next
                }
                current.data = element
                return true
            }

6. removeAt根据索引删除单链表中某个元素

            LinkedList.prototype.removeAt = function (position) {
                // 越界判断
                if (position < 0 || position >= this.length) return false
                if (position === 0) {
                    this.head = this.head.next
                } else {
                    var index = 0
                    var pre = this.head
                    while (++index < position) {
                        pre = pre.next
                    }
                    pre.next = pre.next.next
                }
                this.length -= 1
                return true
            }

7. remove删除单链表中某个元素

            // 删除单链表中某个元素
            LinkedList.prototype.remove = function (data) {
                var index = this.indexOf(data) // 调用indexOf方法获取data对应的索引
                return this.removeAt(index) //删除索引对应的元素

            }

8. isEmpty判断单链表是否为空

            // 判断单链表是否为空
            LinkedList.prototype.isEmpty = function () {
                return this.length === 0
            }

9. toString 遍历单链表

            // 遍历单链表
            LinkedList.prototype.toString = function () {
                var strResult = ''
                var current = this.head
                while (current) {
                    strResult += current.data + ' '
                    current = current.next
                }
                return strResult
            }

测试代码:

        let link = new LinkedList() // 创建链表实例
        link.append('Mike')
        link.append('Kobe')
        link.append('John')
        link.append('Abo')
        link.append('Lisa')
        link.insert(0, 'kangkang')
        console.log(link.toString()); //kangkang Mike Kobe John Abo Lisa 
        console.log(link.removeAt(5)); //true
        console.log(link.remove('Abo')); //true
        console.log(link.toString()); //kangkang Mike Kobe John 
        console.log(link.isEmpty()); //false
        console.log(link.get(0)); //kangkang
        console.log(link.indexOf('Kobe')); //2

以上就是单链表的创建及各功能的实现过程。看完的小伙伴再回到顶部看一下数组和链表的区别吧,此时是不是已经恍然大悟了呢?

“了解真相,你才能获得真正的自由”,只有我们自己搞懂了原理我们才能自如地实现我们想要的功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是个程序员吧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值