horseface1110
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Versions and GitHub Sync Note Insights Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       owned this note    owned this note      
    Published Linked with GitHub
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    # 2025q1 Homework2 (quiz1+2) contributed by < horseface1110 > ## quiz1_1 完成list_insert_before 函式 ``` { list_item_t **p; for (p = &l->head; *p != before; p = &(*p)->next) ; *p = item; (*p)->next = before; } ``` #### for迴圈:尋找要插入的節點位置 - 初始化:先將p設為指向head這個指標的指標 - 尋找插入點:因為p是指標的指標,每次判斷他指向的指標是否為目標,不是的話,就指向下個節點的指標。 #### 為甚麼要用pointer to pointer: 如果只用pointer的話,遇到插在投的話需用判斷條件 ### 合併排序操作 ## quiz1_2 完成填空部分 ``` block_t **pred_ptr = &(*node_ptr)->l; while ((*pred_ptr)->r) pred_ptr = &(*pred_ptr)->r; ``` 提問:已經有function可以找中序前行節點了,為甚麼還要自己找(未解) ``` block_t *expected_pred = find_predecessor_free_tree(root, *node_ptr); assert(expected_pred == *pred_ptr); ``` 運作邏輯: 這段程式碼主要在找可以分配出去的空間,整個空間用樹狀結構表示,所以當找到可以分配出去的節點時,選擇使用中序前行節點置入被移除的節點的位置。 有幾種狀況: - 目標節點有左右子 - 先找出中序前行節點: - 是直接左子節點: ![example](https://hackmd.io/_uploads/BkG52njh1e.png) - 在左子樹的深處 ![example](https://hackmd.io/_uploads/SJogAhjnye.png) - 目標只有一個子節點 - 子節點直接取代![example](https://hackmd.io/_uploads/Sy6E16j3yl.png) - 目標沒有子節點 - 直接刪除 填空部分的目標是找到中序前行節點以取代要被刪除的節點位置,使用了pointer to pointer,指向一個指標,每次檢查他指向的指標指向的節點是否有右子,如果沒有,那現在指向的就是目標節點。 **為甚麼用pointer to pointer?** 如果使用`*pred`的話,追蹤到目標節點時,會不知道是誰指向他,沒辦法將該點自樹中移除 如果使用`**pred`的話,因為指標指向的是**指向該節點的指標本身**,可以直接修改 ## quiz1_3 ```c= static void rebuild_list_link(struct list_head *head) { if (!head) return; struct list_head *node, *prev; prev = head; node = head->next; while (node) { node->prev = prev; prev = node; node = node->next; } prev->next = head; /* GGGG */; head->prev = prev } ``` 這邊依照`list.h`的linklist來說,是雙向環狀串列,所以我認為`GGGG`毫無懸念的是將head的prev指向尾巴,但我不知道為甚麼是錯的(未解) ``` .... if (L != R) { struct list_head *pivot = L; value = list_entry(pivot,node_t,list)->value struct list_head *p = pivot->next; pivot->next = NULL; /* break the list */ ``` 這段程式碼要找出pivot的值,用來比較,所以用list.h中定義的`list_entry`取出數值之後,存在`value`。 提問:break the list時,不需要將p的prev也清掉嗎?(未解) ``` struct list_head *n = p; p = p->next; int n_value = list_entry(n,node_t,list)->value/* IIII */; if (n_value > value) { n->next = right; right = n; } else { n->next = left; left = n; } ``` 跟pivot,若節點的值 > pivot,就被分去`right`串列之中,所以`IIII`是`list_entry(n,node_t,list)->value`取出節點`n`之值 ``` begin[i] = left; begin[i + 1] = pivot /* JJJJ */; begin[i + 2] = right /* KKKK */; ``` 最後會將原linklist分為三個部分:`left`、`pivot`、`right`,所以最後填入`pivot`、`right`毫無懸念 #### 程式碼運作原理: **概述**: - `pivot`:將linklist左右畫分的節點 - `left`:數值小於等於pivot的節點的linklist - `right`:數值大於pivot的節點的linklist - `begin`:堆疊,紀錄要被排序的linklist的head 用`pivot`將linklist分成三部分,每次都先處理`right`這份,處理完後接到`pivot`後面,再處理`left`,最後再全部接起來 **圖解**: 初始linklist(為求畫面美觀,先省略`prev`指標和結尾`NULL`) ![example](https://hackmd.io/_uploads/B1Pv3InnJl.png) ![example](https://hackmd.io/_uploads/B1-OHv221g.png) 目前`pivot`是42,第一次`while`後: ![example](https://hackmd.io/_uploads/HyV87v32ye.png) ![example](https://hackmd.io/_uploads/S1P9SvnhJg.png) 第二次`while`後: ![example](https://hackmd.io/_uploads/H1NKWd23yx.png) ![example](https://hackmd.io/_uploads/S1FcXBpn1x.png) **為什麼begin大小為2 * n?:** 因為在最糟情況下(遞增或遞減),串列在每次分割時都只會集中在left/right和一個節點的pivot。依照程式碼,處理一個串列時,在beign[]上就好像該點解壓縮一樣,一個點變三個點,也就是說,每次處理時,額外增加兩個資料。理論上:共需要分割n-1次,所以會有2(n-1)個新的資料點產生 但實際上,left、right之中一定會有一個NULL,在執行過程中,right是NULL的話會被忽略,不會長期的占用空間,所以實際上不會真的用到2(n-1)+1個格子。(第三、四步驟) ![image](https://hackmd.io/_uploads/r18RJL631e.png) ## quiz2_1 ### 邏輯概述: 先取出linklist的第一個點當`pivot`,接著比較,小於`pivot`就串到`list_less`,否則串到`list_greater`,遞迴處理`list_less`、`list_greater`之後,再串在一起 ### 填空部分: ```c= pivot = list_first_entry(head, struct listitem, list); list_del(&pivot->list); ``` 這邊要先把linklist第一個元素取出來當pivot,所以填入`list_first_entry`。再來要把pivot節點從排序的list中移除,所以用`list_del`。 ```c= list_for_each_entry_safe (item, is, head, list) { if (cmpint(&item->i, &pivot->i) < 0) list_move_tail(&item->list, &list_less); else list_move_tail(&item->list, &list_greater); } ``` 這邊就是把比較完之後的節點放到各自的位置而已。 **為什麼是`list_move_tail`而不是`list_move`**: 用 `list_move_tail()` 是因為我們想要讓排序是穩定的。假設有兩個值一樣的節點 A 跟 A',原本 A 在前面,我們就希望排序後它們還是這個順序。如果用 `list_move()`把新的節點插在 list 開頭,就會讓順序顛倒。所以我們用 `move_tail()`把符合條件的節點依序加到尾巴,保持原本的順序。 ``` list_add(&pivot->list, head); list_splice(&list_less, head); list_splice_tail(&list_greater, head); ``` 這段要將排序好的串列們接在一起 `list_add`是將一個節點接到另一點後方,這邊先將pivot接到head後面。 接著要把`list_less`放在pivot前面,由於是一整個串列的移動,所以用`list_splice`將整個串列插在head後面,pivot前面。最後要將`list_greater`放到pivot後面,所以用`list_splice_tail`插在整個串列的尾端 ## quiz2_2 - 首先,我們需要知道clz2要得到什麼資訊:前導0的個數 - 邏輯概述:先檢查上半部,再換到下半部,如果上半部全零,下次檢查下半部;如果上半部不全零,下次檢查下半部,直到檢查部分是2bit。 程式碼填空 ```c= static const int mask[] = {0, 8, 12, 14}; static const int magic[] = {2, 1, 0, 0}; unsigned clz2(uint32_t x, int c) { if (!x && !c) return 32; uint32_t upper = (x >> (16 >> c)); uint32_t lower = (x & (0xFFFF >> mask[c])); if (c == 3) return upper ? magic[upper] : 2 + magic[lower]; return upper ? clz2(upper, c + 1) : (16 >> (c)) + clz2(lower, c + 1); } ``` 最一開始clz2的參數`c`由0開始。 **第9行**`:uint32_t upper = (x >> (16 >> c));`,表示這次要檢查的部分,`16>>c`意思是$\frac{16}{2^c}$,例如c = 0時,upper = x向右位移16bit,也就是upper = 高位16bit的意思。 **第11行**:`c == 3`,進入遞迴停止的條件是檢查的bit數為2時,而當c == 3 時,表示upper已經只有2 bit。 **第12行**:若upper = 0,則表示lower前面2 bit都是0,所以前導0個數+2,故這邊為2 + magic[lower] **第13行**:每次檢查的精度*2,所以c+1 ## quiz2_3 ```c= struct hlist_head { struct hlist_node *first; }; struct hlist_node { struct hlist_node *next, **pprev; }; ``` 這段程式碼非常神奇,剛看到有點疑惑,所以在這邊紀錄: `struct`裡面怎麼又包了自己呢? [規格書 6.2.5 - 22](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf) >A structure or union type of unknown content (as described in 6.7.2.3) is an incomplete type. It is completed, for all declarations of that type, by declaring the same structure or union tag with its defining content later in the same scope. > 這段是說:struct裡面不能有自己的實例,但可以有自己的指標,因為指標大小事已知的。 一開始疑惑的點是:「可以這樣包?這甚麼寫法」後來想到常見的含指標的node裡面也是這樣寫的。 ```c= static struct hash_key *find_key(map_t *map, int key) { struct hlist_head *head = &(map->ht)[hash(key, AAAA)]; for (struct hlist_node *p = head->first; p; p = p->next) { struct hash_key *kn = container_of(p, struct hash_key, node); if (kn->key == key) return kn; } return NULL; } ``` 邏輯概述:目標找到hash表中的特定key,所以要先取得hash後的bucket值,接著在該bucket中尋找該key。 所以第三行`AAAA`應該要填:`map->bit`。 ```c= void map_add(map_t *map, int key, void *data) { struct hash_key *kn = find_key(map, key); if (kn) return; kn = malloc(sizeof(struct hash_key)); kn->key = key, kn->data = data; struct hlist_head *h = &map->ht[hash(key, BBBB)]; struct hlist_node *n = &kn->node, *first = h->first; n->next = first; if (first) CCCC = &n->next; h->first = n; DDDD = &h->first; } ``` 邏輯概述:要把新的節點插在bucket的第一個。先創好節點後填入數據,再將該節點插到bucket的第一格。 `h`:該節點要被分配到的bucket `n`:指向要插入的節點的指標 `first`:該bucket目前第一個節點的指標 所以`BBBB`應該填入:map->bit,當作取得hash值的參數。 ```c= n->next = first; if (first) CCCC = &n->next; ``` 如果該bucket中已經有節點的話,`if`成立,要把新節點插入bucket的頭,所以`CCCC`填`first->pprev`,將原第一節點的往前指標指向`&n->next` 最後將`n->pprev`指向`h->first`,以上這段就是在將新節點n插入bucket的頭部的過程。 ```c= void map_deinit(map_t *map) { if (!map) return; for (int i = 0; i < MAP_HASH_SIZE(map->bits); i++) { struct hlist_head *head = &map->ht[i]; for (struct hlist_node *p = head->first; p;) { struct hash_key *kn = container_of(p, struct hash_key, node); struct hlist_node *n = p; p = p->next; if (!n->pprev) /* unhashed */ goto bail; struct hlist_node *next = n->next, **pprev = EEEE; *pprev = next; if (next) next->pprev = pprev; n->next = NULL, n->pprev = NULL; bail: free(kn->data); free(kn); } } free(map); } ``` 邏輯概述:這段程式碼目標是移除一個節點,並保持串列結構正常。所以選定移除的節點之後,把與他相關的指標處理好。 ``` struct hlist_node *next = n->next, **pprev = EEEE; *pprev = next; ``` 當要移除節點 n 時,會先取得它的下一個節點 next,並透過 n->pprev 這個 pointer to pointer 取得前一個節點中指向自己的指標位置,因此 EEEE 應填入 n->pprev。接著將 *pprev 設為 next,斷開目前節點與前一節點的連結;若 next 存在,則更新 next->pprev 指向原本的 pprev,讓其指向前一個節點指向自己這個節點的指標記憶體位址。最後將 n 的指標清空,並釋放該節點,即可正確地將節點從鏈結串列中移除,並保持整體結構的完整。

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully