1.链表和数组一样,用于存储一系列元素,但是链表和数组的实现机制完全不同
2.数组:要存储多个元素,数据可能是常用的数据结构,但数组有很多缺点,数组的创建通常需要申请一段连续的内存空间(一整块的内存),并且大小是固定的,所以当前数组不能满足容量需求时,需要扩容。
数组在开头或中间插入数据的成本很高,需要进行大量的元素的位移。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>单向链表</title>
</head>
<body>
<script>
function LinkedList() {
function Node(data, next = null) {
this.data = data
this.next = next
}
this.head = null
this.len = 0
// 节点新增
LinkedList.prototype.append = function (data) {
let newNode = new Node(data) // 创建新节点
if (this.len === 0) { // 第一个节点直接加入
this.head = newNode
} else {
let current = this.head
while (current.next) { // 寻找最后一个节点
current = current.next
}
current.next = newNode
}
this.len += 1
}
LinkedList.prototype.toString = function () {
let current = this.head
let listString = ''
while (current) {
listString += current.data + ' '
current = current.next
}
return listString.trim();
}
// 任意位置插入数据
LinkedList.prototype.insert = function (position, data) {
// 负数越界,长度越界判断
if (position < 0 || position > this.len) return false
let newNode = new Node(data)
if (position === 0) {
newNode.next = this.head
this.head = newNode
} else {
let index = 0
let current = this.head
let previous = null
while (index++ < position) {
previous = current
current = current.next
}
newNode.next = current
previous.next = newNode
}
this.len += 1
return true
}
LinkedList.prototype.get = function (position, data) {
// 越界判断
if (position < 0 || position >= this.len) return null
let current = this.head
let index = 0
while (index++ < current) {
current = current.next
}
return current.data
}
LinkedList.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
}
LinkedList.prototype.update = function (position, newData) {
if (position < 0 || position > this.len) return false
let current = this.head
let index = 0
while (index++ < position) {
current = current.next
}
current.data = newData
return true
}
LinkedList.prototype.removeAt = function (position) {
if (position < 0 || position > this.len) return false
let current = this.head
let index = 0
if (position === 0) {
this.head = this.head.next
} else {
let index = 0
let previous = null
while (index++ < position) {
previous = current
current = current.next
}
previous.next = current.next
}
this.len -= 1
return current.data
}
LinkedList.prototype.remove = function (data) {
let position = this.indexOf(data)
return this.removeAt(position)
}
LinkedList.prototype.isEmpty = function () {
return this.len === 0
}
LinkedList.prototype.size = function () {
return this.len
}
}
let linkedList = new LinkedList();
// Test case 1: append
linkedList.append('A');
linkedList.append('B');
linkedList.append('C');
console.log('After appending: ', linkedList.toString()); // Output: 'A B C'
// Test case 2: insert
linkedList.insert(1, 'D');
console.log('After inserting at position 1: ', linkedList.toString()); // Output: 'A D B C'
// Test case 3: get
console.log('Element at position 2: ', linkedList.get(2)); // Output: 'B'
// Test case 4: indexOf
console.log('Index of element "D": ', linkedList.indexOf('D')); // Output: 1
// Test case 5: update
linkedList.update(2, 'E');
console.log('After updating element at position 2: ', linkedList.toString()); // Output: 'A D E C'
// Test case 6: removeAt
linkedList.removeAt(1);
console.log('After removing at position 1: ', linkedList.toString()); // Output: 'A E C'
// Test case 7: remove
linkedList.remove('A');
console.log('After removing element "A": ', linkedList.toString()); // Output: 'E C'
// Test case 8: isEmpty
console.log('Is the linked list empty? ', linkedList.isEmpty()); // Output: false
// Test case 9: size
console.log('Size of the linked list: ', linkedList.size()); // Output: 2
</script>
</body>
</html>