一、优缺点
相对于数组链表有一些优点
- 内存空间不是必须连续的.可以充分利用计算机的内存,实现灵活的内存动态管理.
- 链表不必在创建时就确定大小,并且大小可以无限的延伸下去.
- 链表在插入和删除数据时,时间复杂度可以达到0(1).相对数组效率高很多.
相对于数组,链表有一-些缺点
- 链表访问任何一个位置的元素时,都需要从头开始访问.(无法跳过第一个元素访问任何一个元素).
- 无法通过下标直接访问元素,需要从头一个个访问,直到找到对应的元素.
二、单向链表

function LinkedList() {
function Node(data) {
this.data = data
this.next = null
}
this.head = null
this.length = 0;
LinkedList.prototype.append = function(element) {
var node = new Node(element)
if (this.length === 0) {
this.head = node
}
else {
var current = this.head
while (current.next) {
current = current.next
}
current.next = node
}
this.length += 1
return element
}
LinkedList.prototype.insert = function(position, element) {
if (position < 0 || position > this.length) return false;
var newNode = new Node(element)
if (position === 0) {
newNode.next = this.head
this.head = newNode
}
else {
var current = this.head;
var previous = null
for (var i=0; i<position; i++) {
previous = current
current = current.next
}
newNode.next = current
previous.next = newNode
}
this.length += 1
return true
}
LinkedList.prototype.get = function(position) {
if (position < 0 || position >= this.length) return;
var current = this.head;
for (var i=0; i<position; i++) {
current = current.next
}
return current.data
}
LinkedList.prototype.indexOf = function(data) {
var current = this.head;
if (!current) {
return -1;
}
var index = 0;
while (current) {
if (current.data === data) {
return index
}
else {
current = current.next
index += 1
}
}
return -1;
}
LinkedList.prototype.update = function(position, data) {
if (position < 0 || position >= this.length) return false;
let current = this.head
for (let i=0; i<position; i++) {
current = current.next
}
current.data = data
return true
}
LinkedList.prototype.removeAt = function(position) {
if (position < 0 || position >= this.length) return false
let current = this.head;
if (position === 0) {
this.head = this.head.next;
}
else {
let previous = null;
for (let i=0; i<position; i++) {
previous = current
current = current.next
}
previous.next = current.next
}
this.length -= 1
return current.data
}
LinkedList.prototype.remove = function(data) {
const position = this.indexOf(data)
return this.removeAt(position)
}
LinkedList.prototype.toString = function() {
var listString = ''
var current = this.head
while (current) {
listString += current.data + ' '
current = current.next
}
return listString
}
LinkedList.prototype.isEmpty = function() {
return this.length === 0
}
LinkedList.prototype.size = function() {
return this.length
}
}
三、双向链表

function DoublyLinkedList() {
function Node(data) {
this.data = data
this.prev = null
this.next = null
}
this.head = null
this.tail = null
this.length = 0
DoublyLinkedList.prototype.append = function(data) {
const newNode = new Node(data)
if (this.length === 0) {
this.head = newNode
this.tail = newNode
}
else{
this.tail.next = newNode
newNode.prev = this.tail
this.tail = newNode
}
this.length += 1;
return true
}
DoublyLinkedList.prototype.insert = function(position, data) {
if (position < 0 || position > this.length) return false
const newNode = new Node(data)
if (this.length === 0) {
this.head = newNode
this.tail = newNode
}
else {
if (position === 0) {
newNode.next = this.head
this.head.prev = newNode
this.head = newNode
}
else if (position === this.length) {
this.tail.next = newNode
newNode.prev = this.tail
this.tail = newNode
}
else {
let current = this.head
for (let i=0; i<position; i++) {
current = current.next
}
newNode.next = current
newNode.prev = current.prev
current.prev.next = newNode
current.prev = newNode
}
}
this.length += 1
return true
}
DoublyLinkedList.prototype.get = function(position) {
if (position < 0 || position >= this.length) return false
if (position < (this.length / 2)) {
let current = this.head
for (let i=0; i<position; i++) {
console.log('111')
current = current.next
}
return current.data
}
else {
let current = this.tail
for (let i=this.length-1; i>position ; i--) {
console.log('222')
current = current.prev
}
return current.data
}
}
DoublyLinkedList.prototype.indexOf = function(data) {
let current = this.head;
let index = 0;
while (current) {
if (current.data === data) {
return index
}
current = current.next
index += 1;
}
return -1
}
DoublyLinkedList.prototype.update = function(position, data) {
if (position < 0 || position >= this.length) return false
let current = this.head
for (let i=0; i < position; i++){
current = current.next
}
current.data = data
return true
}
DoublyLinkedList.prototype.removeAt = function(position) {
if (position < 0 || position >= this.length) return null
let current = this.head
if (this.length === 1) {
this.head = null
this.tail = null
}
else {
if (position === 0) {
this.head.next.prev = null
this.head = this.head.next
}
else if (position === this.length-1) {
current = this.tail
this.tail.prev.next = null
this.tail = this.tail.prev
}
else {
for (let i=0; i<position; i++) {
current = current.next
}
current.prev.next = current.next
current.next.prev = current.prev
}
}
this.length -= 1
return current.data
}
DoublyLinkedList.prototype.remove = function(data) {
const index = this.indexOf(data)
return this.removeAt(index)
}
DoublyLinkedList.prototype.toString = function() {
return this.backwordString()
}
DoublyLinkedList.prototype.backwordString = function() {
let current = this.head
let resultString = ''
while (current) {
resultString += current.data + ' '
current = current.next
}
return resultString
}
DoublyLinkedList.prototype.forwardString = function() {
let current = this.tail
let resultString = ''
while (current) {
resultString += current.data + ' '
current = current.prev
}
return resultString
}
DoublyLinkedList.prototype.isEmpty = function() {
return this.length === 0
}
DoublyLinkedList.prototype.size = function() {
return this.length
}
DoublyLinkedList.prototype.getHead = function() {
return this.head.data
}
DoublyLinkedList.prototype.getTail = function() {
return this.tail.data
}
}