双向链表
单向链表:
1、只能从头部到尾部或者从尾部到头部
2、链表的连接是单向的
3、实现原理就是上一个链表有下一个链表的引用
4、缺点就是我们可以轻松的前往下一个节点但是回到上一个节点需要从头开始(类似于文本编辑器返回上一个光标)
双向链表:
1、可以从头遍历到尾部,也可以从尾部变量到头部
2、一个节点有上一个连接的引用,也有一个下一个连接的引用
3、缺点有实现起来更复杂,需要处理4个节点; 相比于单向链表,占用内存空间更大
实现:
tail
|
head -> pre | item | next -> pre | item | next -> null
1、有2个指针,一个指向head头部,一个指向尾部tail
2、每一个节点3个部分组成 pre(上一个节点的指针) item(保存的元素) next(下一个节点的指针)
3、双向链表的第一个节点的pre指向null
4、双向链表的最后的节点的next是null
function DoublyLinkedList() {
this.head = null
this.tail = null
this.length = 0
function Node(element) {
this.pre = null
this.next = null
this.element = element
}
DoublyLinkedList.prototype.append = (element) => {
const newNode = new Node(element)
if (this.length === 0) {
this.head = newNode
this.tail = newNode
} else {
let current = this.head
while(current.next) {
current = current.next
}
current.next = newNode
newNode.pre = current
this.tail = newNode
}
this.length += 1
}
DoublyLinkedList.prototype.toString = () => {
let current = this.head
let str = ''
while(current) {
str += current.element + ' '
current = current.next
}
return str
}
DoublyLinkedList.prototype.forwardString = () => {
let current = this.head
let str = ''
while(current) {
str += current.element + ' '
current = current.next
}
return str
}
DoublyLinkedList.prototype.backwordString = () => {
let current = this.tail
let str = ''
while(current) {
str += current.element + ' '
current = current.pre
}
return str
}
DoublyLinkedList.prototype.size = () => {
return this.length
}
DoublyLinkedList.prototype.isEmpty = () => {
if (this.length === 0) {
return true
} else {
return false
}
}
DoublyLinkedList.prototype.insert = (position, element) => {
if (position < 0 || position > this.length) {
return false
}
let newNode = new Node(element)
if (position === 0) {
newNode.pre = null
newNode.next = this.head
this.head = newNode
}
if (position === this.length) {
this.append(element)
return true
} else {
let current = this.head
let pre = null
let index = 0
while(index++ < position) {
pre = current
current = current.next
}
pre.next = newNode
newNode.pre = pre
newNode.next = current
current.pre = newNode
}
this.length += 1
return true
}
DoublyLinkedList.prototype.get = (position) => {
if (position < 0 || position >= this.length) {
return false
}
let current = this.head
let index = 0
while(index++ < position) {
current = current.next
}
return current.element
}
DoublyLinkedList.prototype.indexOf = (element) => {
let current = this.head
let index = 0
while(current) {
if (current.element === element) {
return index
} else {
current = current.next
index += 1
}
}
return -1
}
DoublyLinkedList.prototype.update = (position, element) => {
if (position < 0 || position >= this.length) {
return false
}
let current = this.head
let index = 0
while(index++ < position) {
current = current.next
}
current.element = element
return true
}
DoublyLinkedList.prototype.removeAt = (position) => {
if (position < 0 || position >= this.length) {
return false
}
if (position === 0) {
this.head = this.head.next
this.head.pre = null
}
else if (position === this.length - 1) {
this.tail.pre.next = null
this.tail = this.tail.pre
} else {
let current = this.head
let index = 0
while(index++ < position) {
current = current.next
}
current.pre.next = current.next
current.next.pre = current.pre
}
this.length -= 1
}
DoublyLinkedList.prototype.remove = (element) => {
let current = this.head
let index = 0
while(current) {
if (current.element === element) {
this.removeAt(index)
return true
} else {
current = current.next
index += 1
}
}
return false
}
}