一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第17天,点击查看活动详情。
前言
上期我们实现介绍了何为链表,并创建了一个链表类。本篇文章我们就继续完善我们的链表类。首先先来回顾一下,链表中所包含的方法。
链表中的方法
- push(data) 向链表尾部添加一个新元素
- pushAnyWhere(data,index) 向链表的特定位置添加一个新元素
- getData(index) 返回链表特定位置的元素。不存在返回undefined
- remove(data) 从链表中移除一个元素
- indexOf(data) 返回数据在链表中的索引,不存在返回-1
- removeAnyWhere(index) 从链表特定位置移除一个元素
- isNull() 链表是否为空
- size() 链表中的元素个数
编码实现
push
push(data){
// 创建节点
const node = new Node(data)
if(this.head === null){
this.head = node
}else{
// 定义一个指针,来帮助我们指向最后一个节点
let current = this.head
while(current.next){
current = current.next
}
// 尾部添加
current.next = node
}
// 数量+1
this.count++
}
pushAnyWhere
pushAnyWhere(data,index){
// 两种情况,头节点插入,身体或尾部插入
if(index >= 0 && index <= this.count){
// 不能过界。
const node = new Node(data)
if(index === 0){
// 第一种情况——头插入
const current = this.head
node.next = current
this.head = node
}else{
// 第二种情况
// 获取前一个节点
const prev = this.getData(index - 1)
// 获取当前index位置的节点
const current = prev.next
node.next = current
prev.next = node
}
this.count++
}else{
console.log(`index输入不合法,请输入0-${this.count}之间的值`)
}
}
getData()
getData(index){
if(index >= 0 && index <= this.count){
let current = this.head
for(let i = 0;i < index && current !== null;i++){
current = current.next
}
return current
}
return undefined
}
remove()
remove(data){
return this.removeAnyWhere(this.indexOf(data))
}
removeAnyWhere()
removeAnyWhere(index){
// 两种情况,第一项,非第一项
if(index >= 0 && index < this.count){
let current = this.head
if(index === 0){
this.head = current.next
}else{
const prev = this.getData(index - 1)
current = prev.next
prev.next = current.next
}
this.count--
return current.data
}
return undefined
}
indexOf()
indexOf(data){
let current = this.head
for(let i = 0;i < this.count && current !== null;i++){
if(this.isEqual(data,current.data)){
return i
}
current = current.next
}
return -1
}
isNull()
isNull(){
return this.count === 0
}
size()
size(){
return this.count
}
为了方便观察链表,我们重写一下toString方法
toString()
toString(){
if(this.head === null) {
return ''
}
let resultData = `${this.head.data}`
let current = this.head.next
for(let i = 1;i < this.count && current !== null;i++){
resultData = `${resultData},${current.data}`
current = current.next
}
return resultData
}
完整代码如下:
class Node {
constructor(data){
this.data = data
this.next = null
}
}
class LinkedList {
constructor(){
// 链表大小
this.count = 0
// 头节点
this.head = null
// 比较函数
this.isEqual = function(a,b){
return a === b
}
}
push(data){
// 创建节点
const node = new Node(data)
if(this.head === null){
this.head = node
}else{
// 定义一个指针,来帮助我们指向最后一个节点
let current = this.head
while(current.next){
current = current.next
}
// 尾部添加
current.next = node
}
// 数量+1
this.count++
}
pushAnyWhere(data,index){
// 两种情况,头节点插入,身体或尾部插入
if(index >= 0 && index <= this.count){
// 不能过界。
const node = new Node(data)
if(index === 0){
// 第一种情况——头插入
const current = this.head
node.next = current
this.head = node
}else{
// 第二种情况
// 获取前一个节点
const prev = this.getData(index - 1)
// 获取当前index位置的节点
const current = prev.next
node.next = current
prev.next = node
}
this.count++
}else{
console.log(`index输入不合法,请输入0-${this.count}之间的值`)
}
}
getData(index){
if(index >= 0 && index <= this.count){
let current = this.head
for(let i = 0;i < index && current !== null;i++){
current = current.next
}
return current
}
return undefined
}
remove(data){
return this.removeAnyWhere(this.indexOf(data))
}
removeAnyWhere(index){
// 两种情况,第一项,非第一项
if(index >= 0 && index < this.count){
let current = this.head
if(index === 0){
this.head = current.next
}else{
const prev = this.getData(index - 1)
current = prev.next
prev.next = current.next
}
this.count--
return current.data
}
return undefined
}
indexOf(data){
let current = this.head
for(let i = 0;i < this.count && current !== null;i++){
if(this.isEqual(data,current.data)){
return i
}
current = current.next
}
return -1
}
isNull(){
return this.count === 0
}
size(){
return this.count
}
toString(){
if(this.head === null) {
return ''
}
let resultData = `${this.head.data}`
let current = this.head.next
for(let i = 1;i < this.count && current !== null;i++){
resultData = `${resultData},${current.data}`
current = current.next
}
return resultData
}
}
const linkedList = new LinkedList()
console.log(linkedList.isNull());// true
linkedList.push(0)
linkedList.push(1)
linkedList.push(2)
linkedList.pushAnyWhere(3,3)
linkedList.pushAnyWhere(6,0)
linkedList.pushAnyWhere(4,4)
linkedList.pushAnyWhere(5,2)
console.log(linkedList.toString());// 6,0,5,1,2,4,3
console.log(linkedList.getData(3));// Node节点
linkedList.remove(5)
linkedList.removeAnyWhere(4)
console.log(linkedList.toString());// 6,0,1,2,3
console.log(linkedList.isNull());// false
console.log(linkedList.size());// 5
console.log(linkedList.indexOf(3));// 4
console.log(linkedList.indexOf(5));// -1
总结
本次我们实现了链表类上面的常用方法。但是这只是一个基本的链表结构,还有双向链表,循环链表,有序链表等特殊链表,万变不离其宗,只要基础链表学会了,特殊链表只是在此基础上做了一些属于自己的修改,下次我们实现双向链表。