链表操作及封装
操作分类
append(item)
:向链表尾部添加一个新的节点,item
为节点数据insert(position, item)
:向链表的某个位置插入一个新的节点,position
为插入位置,item
为节点数据get(position)
:获取链表中某个位置的节点,position
为位置indexOf(item)
:返回节点在链表中的位置索引,若在链表中没有该元素,则返回-1,其中item
为要查询的节点数据update(position,item)
:修改某个节点的元素,position
为某个节点的位置,item
为要修改的数据remove(item)
:从链表中移除数据item
对应的某个节点remove(position)
:从链表中移除位置position
对应的某个节点isEmpty()
:判断链表是否为空,如果链表中不包含任何的节点,则返回true
,反之则返回false
size()
:返回链表所包含的节点个数toString()
:将链表转换为字符串形式
append方法
首先还是和之前的封装方式一样,我们先封装一下。
LinkList.prototype.append = function (data) { var newNode = new Node(data) this.length++ } 复制代码
而在封装append要考虑两种情况,即当链表本身为空的时候,新添加的节点是唯一的,这个时候只需要将头节点的指向改为新节点即可
if (this.head == null) { this.head = newNode } 复制代码
另外一种则是当链表不为空的时候,需要在其他节点后面添加节点,通过while从头节点开始直到current.next
也就是节点的指向为空的时候将其指向改为新增节点
else { var current = this.head while(current.next) { current = current.next } current.next = newNode } 复制代码
toString方法
toString方法需要我们从第一个节点开始,拿到对应的item来不断拼接字符串
LinkList.prototype.toString = function () { var current = this.head var result = "" while (current) { result += current.data current = current.next } return result } 复制代码
insert方法
insert方法可以将节点插入任意位置上
LinkList.prototype.insert = function (position,data) { var newNode = new Node(data) this.length++ } 复制代码
我们首先需要对position
进行越界判断,判断其传参是否在链表的范围内还有是否合法
if (position < 0 || position > this.length) return false 复制代码
进一步我们可以进行插入的操作,即我们将插入位置的前一个节点的指向转向新节点,将新节点的指向转向位置后的节点,但是需要考虑两种情况,即插入位置是否是第一个。
当插入位置为第一个的时候新节点的指向需要改为当前头节点的指向,之后再将头节点指向新节点
if (position == 0) { newNode.next = this.head this.head = newNode } 复制代码
当插入位置不是第一个的时候,我们需要通过头节点向后寻找对应位置的前节点,首先需要将新节点的指向转向插入位置后的节点,再将插入位置前的节点指向改为我们的新节点,如果顺序反过来,那么我们就会找不到插入位置后的节点,造成了丢失的情况。
else { var index = 0 var current = this.head var previous while (index++ < position) { previous = current current = current.next } newNode.next = current previous.next = newNode } 复制代码
get方法
get方法是根据传来的position位置来获取其对应的节点数据
LinkList.prototype.get = function (position) {} 复制代码
当然同样的,传参出现position的时候我们首先需要的就是先判断它是否越界,与之前不同的是将>改为>=
if (position < 0 || position >= this.length) return false 复制代码
get方法还是简单的只需要从头节点向后找对应的position的数据
var current = this.head var index = 0 while (index < position) { current = current.next index++ } return current.data 复制代码
indexOf方法
indexOf方法通过传入的数据来寻找并返回其数据在链表中的索引也就是下标
LinkList.prototype.indexOf = function (data) { var index = 0 var current = this.head while (current) { if(current.data == data) { return index } current = current.next index++ } return -1 } 复制代码
update方法
update通过传进来的位置参数来寻找并使用数据参数修改其值,同样的因为参数中有position,所有我们必须先进行越界判断再进行操作,最后通过直接修改current
的data完成修改
LinkList.prototype.update = function (position,data) { if (position < 0 || position >= this.length) return false var index = 0 var current = this.head while (index++ < position) { current = current.next } current.data = data retrun true } 复制代码
removePo&remove方法
移除方法有两种形式,一种是根据位置去移除,一种是根据数据去移除,我们首先来介绍一下通过位置进行移除的封装,其实移除和插入的逻辑相似,同样也分两种情况,一种是移除第一个,另一种是移除其他位置
当移除位置为第一个的时候则将头节点的指向直接改为头节点的下一个节点
LinkList.prototype.removePo = function (position) { if (position < 0 || position >= this.length) return false if (position == 0) { this.head = this.head.next } this.length-1 } 复制代码
当position为其他位置的时候则将位置前节点的指向改为位置后的节点,使用两个变量记录位置current
的变化,当其满足条件的时候即到达指定位置的时候操作即可
else { var index = 0 var current = this.head var previous while (index++ < position) { previous = current current = current.next } previous.next = cuurent.next } 复制代码
大家可能疑问那么我删除的节点哪去了?其实大家不用担心移除的节点会占内存,因为浏览器的回收机制会将它及时回收的。
remove方法则是根据传入的数据来进行移除,有了之前的封装我们直接调用indexOf和removePo直接获取,简单粗暴
LinkList.prototype.remove = function (data) { var position = this.indexOf(data) return this.removePo(position) }