Thinking系列,旨在利用10分鐘的時間傳達一種可落地的編程思想。
使用 typescript 生成鏈表
interface node<T> {
next: node<T> | null
element: T
}
class LinkedNode<T> implements node<T> {
element: T
next: node<T> | null = null
constructor(element: T, next: node<T> | null = null) {
this.element = element
this.next = next
}
}
class LinkedList<T> {
length: number = 0
head: node<T> | null = null
append(element: node<T>) {
let node: node<T> = element
if (this.head === null) {
this.head = node
} else {
// 不改變head指針
let current = this.head
while (current.next) {
current = current.next
}
current.next = node
}
this.length++
}
}
需求: 如,鏈表信息{"length":3,"head":{"next":{"next":{"next":null,"element":"c"},"element":"b"},"element":"a"}}
,鏈表倒序輸出c b a
var testLinkedList = new LinkedList<string>()
testLinkedList.append(new LinkedNode<string>('a'))
testLinkedList.append(new LinkedNode<string>('b'))
testLinkedList.append(new LinkedNode<string>('c'))
常規思路
循環保存,然後倒序輸出
function printLinkedListReversing (head: node<string>): void {
let result: string[] = []
while(head !== null) {
result.push(head.element)
head = head.next
}
console.log(result.reverse())
}
延伸
倒敘輸出(先進後出 FILO),典型的棧。
依靠遞歸(遞歸本質上是一個棧結構)
function printLinkedListReversing_recursion(head: node<string>): void{
if (head !== null) {
if (head.next != null) {
printLinkedListReversing_recursion(head.next)
}
console.log(head.element)
}
}
需要注意的是,當鏈表過長時,會導致函數調用的層級過深,可能導致調用棧溢出。
擴展: 數組存儲中間狀態
function printLinkedListReversing(head: node<string>, result: Array<string> = []): Array<string> {
if (head !== null) {
if (head.next != null) {
printLinkedListReversing(head.next, result)
}
console.log(head.element)
result.push(head.element)
}
return result
}
console.log(printLinkedListReversing(testLinkedList.head, [])) // [ 'c', 'b', 'a' ]
物理結構:
- 順序存儲結構:數組
- 鏈式存儲結構:鏈表
邏輯結構:
- 線性結構:順序表、棧、隊列
- 非線性結構:樹、圖
數組:讀操作多、寫操作少的場景。 非常高效的隨機訪問能力;插入和刪除元素效率不高。
鏈表:靈活地進行插入和刪除操作。
查找 | 更新 | 插入 | 刪除 | |
---|---|---|---|---|
數組 | O(1) | O(1) | O(n) | O(n) |
鏈表 | O(n) | O(1) | O(1) | O(1) |