contributed by < JeepWay
>
主要差異部分如下
可以發現兩種函式的差異在於傳入的第二個參數,分別是 l.head
和 NULL
,故可以推測第二個參數是要插入的節點的新 next
。
list_insert_before
函式如下
因為是單向鏈結串列,所以 p
是 list
的 head
。而 item
也就是插入的節點。
*p = item;
是在 assign 新的 head,也就是插入的 item
。
list_item_t **p;
這種操作是指標的指標,方便之處在於可以不用回傳的新 head 的地址,所以該函式的回傳型態才會是 void
。如果不使用指標的指標,就要向 LeetCode 的題目一樣回傳新 head 的地址。
p = AAAA;
目的是初始化 p
傳入的 head 的地址,所以 AAAA
是 &l->head
。
*p != BBBB
是在偵測是否到達要插入的位置,也就是傳入的 before
,所以 BBBB 是 before
DDDD = before
是在更新 head->next
,所以 DDDD 是 (*p)->next
或者 item->next
。
CCCC 一定式移動 p
到下一個節點,所以是 &(*p)->next
。
名稱 | 程式碼 |
---|---|
AAAA | &l->head |
BBBB | before |
CCCC | &(*p)->next |
DDDD | (*p)->next 或者 item->next |
當使用 list_insert_before(&l, l.head, &items[i]);
把節點插入到含有一個節點的鏈結串列的 head 時,各指標與節點的關係圖如下。
在插入完成後,各指標與節點的關係圖如下。
當使用 list_insert_before(&l, NULL, &items[i]);
把節點插入到含有一個節點的鏈結串列的 head 時,各指標與節點的關係圖如下。
在插入完成後,各指標與節點的關係圖如下。
main()
-> test_suite()
-> my_run_test()
巨集 -> test_list()
list_reset()
重節節點l
的 head,然後檢查插入節點數和節點順序是否符合預期。list_reset()
重節節點l
的 tail,然後檢查插入節點數和節點順序是否符合預期。list_reset()
重節節點l
的 tail,檢查檢查插入節點數是否為 N
。使用 top-down 方法實作 merge sort
0x0
(最低地址):這部分通常是未使用的(標記為 "UNUSED"),因為操作系統通常會將地址 0 保留為無效地址,以捕捉 null pointer error。0x400000
:表示虛擬記憶體空間中的某個起始點(通常 Linux 系統中可執行文件的地址從 0x400000
開始)。.text
:存放程式碼,如機器碼。.rodata
:存放唯讀數據,例如字符串(string literals)。.init
:存放程式初始化相關的數據。.data
:存放已初始化的全局變數和靜態變數。.bss
:存放未初始化的全局變數(這些變數在程式啟動時會被初始化為 0)。malloc
函數創建)。
brk
標記,這是 OS kernel 用來追踪 heap 邊界的地址。當程式需要更多空間時,會通過系統調用(如 sbrk
或 brk
)來移動這個邊界。libc
)的記憶體。
printf
函數)。stack pointer
(%rsp
) 指向 stack 的當前頂部 (往低地址)。in-order predecessor (中序前繼節點) 即目標節點的左子樹中最右邊的節點。所以 pred_ptr
就是一直往右子節點移動,直到 pred_ptr
為 leaf 為止。
名稱 | 程式碼 |
---|---|
EEEE | (*pred_ptr)->r |
FFFF | &(*pred_ptr)->r |
remove_free_tree(block_t **, block_t *)
:從二元樹中移除指定節點。
find_free_tree(root, target)
:找到目標節點 target
在二元樹中的地址,返回指向該節點的指標的指標(node_ptr
)。pred_ptr
。並使用 find_predecessor_free_tree
檢查 pred_ptr
是否為預期的中序前繼節點。remove_free_tree()
移除把中序前繼節點從二元樹中移除,再把它替換到目標節點所在的位置,然後再重新連接原本的左右子樹。NULL
。NULL
,避免非預期的 reference。