or
or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up
Syntax | Example | Reference | |
---|---|---|---|
# Header | Header | 基本排版 | |
- Unordered List |
|
||
1. Ordered List |
|
||
- [ ] Todo List |
|
||
> Blockquote | Blockquote |
||
**Bold font** | Bold font | ||
*Italics font* | Italics font | ||
~~Strikethrough~~ | |||
19^th^ | 19th | ||
H~2~O | H2O | ||
++Inserted text++ | Inserted text | ||
==Marked text== | Marked text | ||
[link text](https:// "title") | Link | ||
 | Image | ||
`Code` | Code |
在筆記中貼入程式碼 | |
```javascript var i = 0; ``` |
|
||
:smile: | ![]() |
Emoji list | |
{%youtube youtube_id %} | Externals | ||
$L^aT_eX$ | LaTeX | ||
:::info This is a alert area. ::: |
This is a alert area. |
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.
Do you want to remove this version name and description?
Syncing
xxxxxxxxxx
2022q1 Homework1 (lab0)
contributed by <
tseng0201
>在「作業區」以「固定網址」填寫 HackMD 超連結,請注意細節!
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →前置作業:
queue.c實現進度:
更多
實驗環境:
queue.c實現:
想法 :利用 linux 已經實現的
struct list_head
與其相關巨集/函式進行 queue 節點間的移動,再透過 container_of / list_entry 取得其他該節點的成員進行操作自定義struct
q_head
在原有的head定義下新增 count 用於計算queue的長度,
count 為0時代表一個空的 queue
定義queue節點
queue_member
已定義於queuq.h
藉由定義好的 struct list_head 進行節點間的移動, 以成員 value(pointer to char)紀錄該節點的資料
自定義函式
q_delete_element()
delete 一個 queue member 先移出 queue 再釋放其記憶體位置
void list_swap()
交換兩個 list_head* 所指向的位置
實現的函式
q_new()
建立一個空的queue head,並將 count 設為0
並透過 INIT_LIST_HEAD() 將 prev, next指標都指向自己
當 memory allocate 失敗將會返回 NULL
新增
當 allocate 失敗時回傳 NULL 不再進行後續操作
q_free()
將整個 queue 包含 queue head 所佔用的記憶體釋放,由於 queue 的資料是由 pointer 紀錄,所以要先釋放掉其指向的記憶體,再釋放掉節點本身
函式透過 temp 紀錄要消除的節點, 並修改 queue head 的 next 紀錄下一個要消去的節點, 最後才將queue head 釋放
q_insert_head
建立一個新的節點插入在 head next, 由於字串是由 pointer傳入 無法使用 sizeof 取得字串長度所以直接使用 for loop 計算長度後再分配適當的空間
建立新的節點後使用 list_add 自動將其指標指向正確位置
使用strlcpy 而非 strncpy 兩者都可以防止輸入大於分配的空間,但strlcpy還會將最後一個改為 '\0' 用起來更安全
新增
當 data malloc 失敗時函式回傳 false,且要將剛建立的 element_t 物件釋放 (free)
q_insert_tail
同 q_insert_head ,但指標操作改為list_add_tail
新增
當 data malloc 失敗時函式回傳 false,且要將剛建立的 element_t 物件釋放 (free)
q_size
回傳 queue 的長度, 直接回傳 q_head 的 count 即可
q_remove_head
將第一個 queue 節點從 queue 中斷開, 並將其 value 轉移至
sp
當 head 為 NULL 或 empty 時回傳 NULL
使用strlcpy 進行字串複製這樣會自動在最後加上 '\0'
並使用list_del進行 queue之間的修改
q_remove_tail
刪除queue中最後的節點 ,概念q_remove_head
q_size
回傳 queue 的長度, 直接回傳 q_head 的 count 即可
q_delete_mid
移除queue中間的節點, 透過 queue head 的 count 即可快速求出該中間節點,透過ptr移動至該節點後先移出(remove) queue 再進行刪除(delete)
count 要減1
待改進的點 :
head 其實算完 count 後不需要了可以直接拿來當ptr
q_delete_dup
把重複的節點都刪除 e.g. old: 1->2->2->3 改為 1->3
注意 :此程式必須為排序過的 list 才適用
設定 ptr 為當前節點的節點並與 ptr->next 比較,如果相同則刪除ptr->next 否則該節點保留
kill_self 用來紀錄當前 ptr 是否為duplicate的一部分 如果kill_self 為 true 則節點也應該刪除
q_swap()
將 queue 中的節點每兩個兩個相反,且不能改變node value
e.g. a->b->c->d 改為b->a->d->c
此程式以單向 link_list 方向思考,最後再以 while 迴圈將prev 指向正確的節點
ptr 紀錄當前節點 first second 紀錄當前節點的下個與下下個
代表要交換的兩個節點
q_reverse
由於 queue是雙向的環 所以只要將每個節點(包含 head)的 prev 與 next 指向的位置換就好
q_sort
以三個函式實現
1.q_sort : 呼叫界面
2.list_mergesort() : 執行mergesort
3.merge_two_list : 執行merge
merge_two_list()
引用:你所不知道的 C 語言: linked list 和非連續記憶體中的實做
進行
概念是讓一個指標 ptr 每次都走向 q_1 或 q_2 value 比較小的節點,然後移動被選中的節點至其下一個,當ptr走完兩個 list 便可得到一個依 value 由小到大串在一起的list
程式碼解析
在引用的實做中, 使用** 進行對指標的紀錄與移動
1.ptrㄧ開始指向節點本身而之後都是指向節點的 next
2.node 為紀錄目前比較小的那個節點並進行操作
上列函式可看做
3.透過 node 紀錄當前較小的節點並透過 ptr 串起走訪的節點
4.地址的 bitwise操作
c 不允對指標指向的地址做 or 所以將地址強制轉形成 unsigned int 進行操作後再轉回本的型態
C99規格書上面寫道
以下為完整程式碼
merge_two_list()
利用 divine and counquer 的概念進行分割與合併,將原本 queue
分隔為多個長度為1的 queue 後再進行合併,分割使 用slow、fast 指標取的中間的節點、並分為left 與 right 處理
最後回傳merge後的queue
q_sort()
首先先將環狀的queue 斷開成直線的queue
再將queue進行sort
最後透過迴圈將 prev 修正並修復回環狀的queue
以下為完整程式碼
更多
在 qtest 提供新的命令 shuffle
shuffle實現
使用 Fisher–Yates shuffle 演算法,每次隨機選擇一個節點與最後一個尚未交換過的節點交換其 value (不改變節點順序)
修改qtest
根據 lab0 的引導在 console_init()新增指令shuffle, 並實現 do_shuffle 函式進行 q_shuffle
此函式參考 do_swap() 實現