雙向鏈表也叫雙鏈表。雙向鏈表中不僅有指向後一個節點的指針,還有指向前一個節點的指針。這樣可以從任何一個節點訪問前一個節點,當然也可以訪問後一個節點,以至整個鏈表。
一般是在需要大批量的另外儲存數據在鏈表中的位置的時候用。雙向鏈表也可以
package com.atguigu.datastruc.linked_list
/**
* Author lzc
* Date 2019-11-27 11:11
*/
object DoublyLinkedListDemo {
def main(args: Array[String]): Unit = {
val list = new DoublyLinkedList[Int]()
list.add(10)
list.add(20)
list.add(30)
list.printInfo()
list.delete(30)
list.delete(20)
list.delete(10)
list.printInfo()
}
}
class DoublyLinkedList[T] {
var head: Node = _
var tail: Node = _
/**
* 刪除節點
* 雙向節點刪除比較方便: 支持自刪除
*
* @param ele
*/
def delete(ele: T): Boolean = {
// 找到要刪除的節點
val targetNode: Node = find(ele)
if (targetNode == null) { // 如果要刪除的節點不存在
false
}
else { // 刪除的節點存在
// 上一個節點
val preNode: Node = targetNode.pre
val nextNode: Node = targetNode.next // 下一個節點
if (targetNode == head) { // 如果是頭節點
if (nextNode != null) nextNode.pre = null // 下一個節點的 pre 指向 null
head = nextNode // 更新頭節點
} else if (targetNode == tail) { // 如果是尾節點
preNode.next = null // 上一個節點的 next 指向 null
tail = preNode // 更新尾節點
} else {
preNode.next = nextNode
nextNode.pre = preNode
}
true
}
}
/**
* 找到要刪除的元素所在的節點
*
* @param ele
*/
protected def find(ele: T): Node = {
var tmp: Node = head // 從頭節點開始查找
while (tmp != null) {
if (tmp.value == ele) return tmp
tmp = tmp.next
}
null
}
/**
* 新增節點
*
* @param ele
*/
def add(ele: T): Boolean = {
val newNode: Node = Node(ele, null, null)
if (head == null) { // 第一次添加
head = newNode // 因爲第一個元素, 上一個和下一個節點都應該是 null
} else { // 不是第一次添加, tail 的next節點指向新節點, 新節點的pre節點指向 tail
tail.next = newNode
newNode.pre = tail
}
// 更新 tail 的指向
tail = newNode
true
}
/**
* 打印鏈表的元素
*/
def printInfo(): Unit = {
if (head == null) return
var tmp: Node = head
do {
print(tmp.value + "->")
tmp = tmp.next
} while (tmp != null)
println()
}
case class Node(value: T, var pre: Node, var next: Node)
}