数据结构(三)链表JS实现
特点
链表和数组一样是一种线性结构,每个节点都有指向下一个节点的指针,例如,生活中的火车,铁链,一节节地连接
- 优点:随意扩充没有存储位置固定的限制,插入,删除的效率很高
- 缺点:查询效率低,遍历时只能从头部开始一个个往下查询
- 存储一个head节点指向头指针
链表中的常见操作:
- append(element):向链表尾部添加一个新的项;
- insert(position,element):向链表的特定位置插入一个新的项;
- get(position):获取对应位置的元素;
- indexOf(element):返回元素在链表中的索引。如果链表中没有该元素就返回-1;
- update(position,element):修改某个位置的元素;
- removeAt(position):从链表的特定位置移除一项;
- remove(element):从链表中移除一项;
- isEmpty():如果链表中不包含任何元素,返回true,如果链表长度大于0则返回false;
- size():返回链表包含的元素个数,与数组的length属性类似;
- toString():由于链表项使用了Node类,就需要重写继承自JavaScript对象默认的toString方法,让其只输出元素的值;
单向链表代码
class LinkedList {
constructor() {
this.head = null
this.length = 0
}
add(data) {
let cache = new this.node(data)
if (this.length == 0) {
this.head = cache
} else {
let current = this.head
while (current.next) {
current = current.next
}
current.next = cache
}
this.length += 1
}
insert(position, data) {
let cache = new this.node(data)
if (position <= this.length && position >= 0) {
let index = 0
let current = this.head
while (index++ < position - 1) {
current = current.next
}
//插入分成两种情况,1.插入到头节点,2.插入其他节点
if (position == 0) {
cache.next = current
this.head = cache
} else {
cache.next = current.next
current.next = cache
}
this.length += 1
}
}
get(position) {
let current = this.head
let index = 0
if (!(position < 0) && !(position >= this.length)) {
while (index++ < position) {
current = current.next
}
return current.data
} else {
return -1
}
}
indexOf(data) {
let current = this.head
let index = 0
while (index < this.length) {
if (current.data == data) {
return index
}
current = current.next
index++
}
return -1
}
removeAt(position) {
let current = this.head
let index = 0
if (!(position < 0) && !(position >= this.length)) {
while (index++ < position - 1) {
current = current.next
}
if (position !== 0) {
current.next = current.next.next
console.log(this.toString())
return true
} else {
this.head = current.next
return current.data
}
} else {
return -1
}
}
remove(data) {
return this.removeAt(this.indexOf(data))
}
toString() {
let str = ''
let current = this.head
while (current) {
str = str + ' ' + current.data
current = current.next
}
return str
}
}
LinkedList.prototype.node = function (data) {
this.data = data
this.next = null
}
双向链表
- 每个节点包含向上节点,向下节点查询
- 包含头尾两个指向节点,head,rear,可以两面遍历
代码
class doublyLinkedList {
constructor() {
this.head = null
this.tail = null
this.length = 0
}
append(data) {
let node = new this.node(data)
if (this.length == 0) {
this.head = node
this.tail = node
} else {
node.prev = this.tail
this.tail.next = node
this.tail = node
}
this.length += 1
}
insert(position, data) {
let node = new this.node(data)
let current = this.head
let prev = null
if (position == 0) {
this.head = node
current.prev = node
node.next = current
this.length += 1
return true
}
if (position > 0 && position <= this.length) {
for (let i = 0; i < position; i++) {
prev = current
current = current.next
}
if (position == this.length) {
console.log(prev.data)
prev.next = node
node.prev = prev
this.tail = node
} else {
console.log(position)
console.log(current)
prev.next = node
node.prev = prev
node.next = current
current.prev = node
}
this.length += 1
return true
}
return false
}
get(position) {
if (position >= 0 && position < this.length) {
let midNum = this.length / 2
if (position <= midNum) {
let current = this.head
for (let i = 0; i < position; i++) {
current = current.next
}
return current.data
} else {
let current = this.tail
for (let i = this.length - 1; i > position; i--) {
console.log('prev')
current = current.prev
}
return current.data
}
}
return false
}
toString() {
let str = ''
let current = this.head
while (current !== null) {
str = str + ' ' + current.data
current = current.next
}
return str
}
}
doublyLinkedList.prototype.node = function (data) {
this.prev = null
this.next = null
this.data = data
}