4.链表
- 内存空间不连续,能实现灵活的内存动态管理
- 链表创建时不需确定大小,大小可随需要而扩充
- 在插入和删除数据时,时间复杂度可达到O(1)
4.1链表的火车结构
链表类似于火车,有一个火车头,火车头连接一个节点(车厢),节点(车厢)内有乘客(数据),并且此节点连接下一节点,以此类推
4.2链表的常见操作
- append(element):向列表尾部添加一个新的项
- insert(position,element):向列表的特定位置插入一个新的项
- get(position):获取对应位置的元素
- indexOf(element):返回元素在列表中的索引,如果列表中没有该元素则返回-1
- update(positon,element):修改某个位置的元素
- removeAt(position):从列表的特定位置移除一项
- remove(element):从列表中移除指定的值
- isEmpty():如果链表没有元素,返回true,否则返回False
- size():返回链表包含的元素个数
- toString():由于列表项使用了Nodeod,就需要重写继承自js对象默认的toString方法,让其只输出元素的值
4.3链表操作的实践
- 链表整体实现预览
function LinkedList () {
function Node (data, next) {
this.data = data
this.next = next
}
this.head = null
this.length = 0//记录当前数组的长度
//append
LinkedList.prototype.append = function (element) {}
LinkedList.prototype.insert = function (position,element) {}
LinkedList.prototype.get = function (position){}
LinkedList.prototype.indexOf = function (element){}
LinkedList.prototype.update = function (positon,element){}
LinkedList.prototype.removeAt = function (position){}
LinkedList.prototype.remove = function (element){}
LinkedList.prototype.isEmpty = function (){}
LinkedList.prototype.size = function (){}
LinkedList.prototype.toString = function (){}
}
- append(element)方法实现
向链表尾部追加数据有两种情况
- 链表本身为空,新添加的节点为唯一节点
- 链表不为空,在其他节点后追加节点
LinkedList.prototype.append = function (element) {
var newNode = new Node(data)
if (this.length == 0)//第一个节点
{
this.head = newNode
}
else {
var currentNode = this.head
while (currentNode.next != null) {//循环找到最后一个节点
currentNode = currentNode.next
}
currentNode.next = newNode//将新节点插入
}
this.length+=1
}
- insert(position,element)方法实现
在任意位置插入数据
- 添加到第一个位置
表示新添加的节点为头节点,此时需要将原来的头节点,作为新节点的next同时head应该指向该新节点
- 添加到其他位置
- 首先需要通过while循环,从头节点开始去遍历查找新节点需要插入的位置,并且在查找过程中保存上个节点与下个节点
- 当找到正确位置后,将新节点的next指向下一个节点,上一个节点的next指向新节点
LinkedList.prototype.insert = function (position, data) {
var currentNode = this.head
var index = 0
var newNode = new Node(data)
if (position < 0 || position > this.length)
return false
if (position == 0) {
this.head = newNode
newNode.next = currentNode
}
else {
while (currentNode != null) {
if (index++ == position - 1)
break
else {
currentNode = currentNode.next
}
}
var q = currentNode.next
currentNode.next = newNode
newNode.next = q
}
this.length += 1
return true
}
- toString()方法实现
LinkedList.prototype.toString = function () {
currentNode = this.head
let elements = ''
while (currentNode != null) {
elements += currentNode.data + ' '
currentNode = currentNode.next
}
return elements
}
- get(position)方法
LinkedList.prototype.get = function (position) {
var currentNode = this.head
var index = 0
if (position < 0 || position >= this.length)
return false
else {
while (index++ < position) {
currentNode = currentNode.next
}
return currentNode.data
}
}
- indexOf(element)方法
LinkedList.prototype.indexOf = function (element) {
var currentNode = this.head
var index = 0
while (currentNode != null) {
if (currentNode.data == element)
return index
else currentNode = currentNode.next
index += 1
}
return -1
}
- removeAt(position)方法
LinkedList.prototype.removeAt = function (position) {
var index = 0
var currentNode = this.head
if (position < 0 || position >= this.length) return false
if (position == 0)
this.head = this.head.next
else{
while (index+1 < position) {
currentNode = currentNode.next
index+=1
}
currentNode.next = currentNode.next.next
}
this.length -= 1
return true
}
- update(position,element)方法
LinkedList.prototype.update = function (position, element) {
var currentNode = this.head
var index = 0
if (position < 0 || position >= this.length) return false
while (index++ < position) {
currentNode = currentNode.next
}
currentNode.data = element
return true
}
- remove(element)方法
//方法一:
LinkedList.prototype.remove = function (element) {
var currentNode = this.head
var prev = this.head
if (this.length == 0) return false
if (this.length == 1 && element == currentNode.element) {
this.head = null
}
else {
while (currentNode != null) {
if (element == currentNode.element) {
if (currentNode === this.head) {
this.head = currentNode.next}
prev.next = currentNode.next
break }
else {
prev = currentNode
currentNode = currentNode.next
}
}
}
this.length-=1
return true
}
//方法二
LinkedList.prototype.remove = function (element) {
var position = this.indexOf(element)
this.removeAt(position)
}
- isempty()方法
LinkedList.prototype.isEmpty = function () {
if (this.length == 0) return true
else return false
}
- size()方法
LinkedList.prototype.size = function () {
return this.length
}