單向鏈表的特點
單向鏈表的缺點
雙向鏈表
雙向鏈表的缺點
雙向鏈表的特點
雙向鏈表基本屬性的封裝
在單向鏈表中head存儲的是第一個節點的引用,在雙向鏈表中tail存儲的是最後一個節點的引用
// 雙向鏈表的封裝
function DoubleLinkedList(){
// 屬性
this.head = null
// 在雙向鏈表裏面this.tail一定是指向最後一個節點
this.tail = null
this.length = 0
// 內部的類進行節點的創建(3個屬性)
function Node(data){
this.data = data
this.prev = null
this.next = null
}
// 封裝常見的操作
}
雙向鏈表的常見操作
(1)實現append方法
DoubleLinkedList.prototype.append=function(data){
// 根據傳入的數據創建節點
var newNode = new Node(data)
// 如果當前鏈表沒有元素
if(this.length == 0){
this.head = newNode
this.tail = newNode
}else{
newNode.prev = this.tail
this.tail.next = newNode
this.tail = newNode
}
this.length += 1
}
(2)實現toString ,forwardString ,backwardString 方法
// 將鏈表轉爲字符串的形式
DoubleLinkedList.prototype.toString = function(){
return this.backwardString()
}
// forwardString:向前遍歷
DoubleLinkedList.prototype.forwardString = function(){
var current = this.tail
var resultString = ''
// 依次向前遍歷獲取每一個節點
while(current){
resultString += current.data + ' '
current = current.prev
}
return resultString
}
// backwardString:向後串聯爲字符串
DoubleLinkedList.prototype.backwardString = function(){
var current = this.head
var resultString = ''
// 依次向後遍歷獲取每一個節點
while(current){
resultString += current.data + ' '
current = current.next
}
return resultString
}
(3)實現insert方法
(當position是0的情況的圖示)
DoubleLinkedList.prototype.insert=function(position,data){
// 當存入position的時候,先進行越界判斷
var newNode = new Node(data)
if(position<0 || position>this.length) return false
// 當前兩邊是否有元素
if(this.length === 0){
// 將head的指針指向newNode
this.head = newNode
this.tail = newNode
}else{
// 判斷position是否是0
if(position === 0){
// this.head指向的是原本的那個元素
this.head.prev = newNode
newNode.next = this.head
this.head = newNode
}else if(position == this.length){
// this.tail指向最後一個節點
newNode.prev = this.tail
this.tail.next = newNode
this.tail = newNode
}else{
var current = this.head,
index = 0
previous = null;
while(index++<position){
previous = current
current = current.next
}
newNode.next = current
previous.next = newNode
current.prev = newNode
newNode.prev = previous
}
}
length += 1
return true
}
(4)實現get方法
DoubleLinkedList.prototype.get=(position)=>{
// 越界判斷
if(position<0 || position>= this.length) return null
var current = this.head
var index = 0
while(index++ < position){
current = current.next
}
return current.data
}
但是通過這樣實現的get方法,當鏈表的元素過多的時候, 其實是效率不高的,因爲這個方法是從前依次王后進行尋找,如果找的是鏈表末尾的元素,在單向鏈表中必須是從前往後尋找,但是在雙向鏈表中,可以通過從後往前的方式,在尋找末尾元素的時候會更加快捷,方便。
DoubleLinkedList.prototype.get=(position)=>{
// 越界判斷
if(position<0 || position>= this.length) return null
var current = this.head
// 噹噹前尋找的位置處於前半段的時候
var len = this.length
var index = 0
if(len / 2 > position ){
while(index++ < position){
current = current.next
}
return current.data
}else{
// 當前尋找的元素處於後半段
current = this.tail
index = this.length -1
while(index-- > position) {
current = current.prev
}
console.log('我是後半段')
return current.data
}
}
(4)實現indexOf方法
DoubleLinkedList.prototype.indexOf=(data)=>{
var current = this.head
var index =0
// 查找與data相同的節點
while(current){
if(current.data === data){
return index
}
current = current.next
index += 1
}
return -1
}
(5)實現update方法(也可以像get方法一樣,進行一個優化)
DoubleLinkedList.prototype.update=(position,newDate)=>{
// 越界判斷
if(position<0 || position>=this.length) return false
var current = this.head
var index = 0
while(index++ < position){
current = current.next
}
// 找到的時候修改值
current.data = newDate
return true
}
(6)實現removeAt方法(當一個節點,沒有其他節點的引用指向它的話,那麼這個節點就會被回收)
DoubleLinkedList.prototype.removeAt=(position)=>{
// 越界判斷
if(position<0 || position >= this.length) return null
// 判斷是否只有一個節點
var 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{
var index = 0
while(index++ < position){
current = current.next
}
// 找到以後需要改變2個指針
current.prev.next =current.next
current.next.prev = current.prev
}
}
// 最後修改length屬性
this.length -=1
return current.data
}
(7)實現remove方法
DoubleLinkedList.prototype.remove=(data)=>{
// 獲取索引
var index = this.indexOf(data)
return this.removeAt(index)
}
(8)其餘方法的實現(isEmpty,size)
DoubleLinkedList.prototype.isEmpty=(data)=>{
return this.length == 0
}
DoubleLinkedList.prototype.size=(data)=>{
return this.length
}
(9)雙向鏈表獲取第一個節點元素
DoubleLinkedList.prototype.getFirst=(data)=>{
return this.head.data
}
(10)雙向鏈表獲取最後一個節點元素
DoubleLinkedList.prototype.getLast=(data)=>{
// 獲取索引
return this.tail.data
}