3C科技 娛樂遊戲 美食旅遊 時尚美妝 親子育兒 生活休閒 金融理財 健康運動 寰宇綜合

Zi 字媒體

2017-07-25T20:27:27+00:00
加入好友
C# 有很多好用的功能,其中 List 絕對是榜上有名。有時候需要放大量資料到記憶體當中,然而若不知道該放多少資料,而是隨著使用者來動態決定大小的話。既不可能一開始就決定陣列大小,若宣告太大則浪費空間;若宣告太小則放不下!若使用 malloc 動態宣告,也是需要先在一開始就先知道要用多大的大小才能宣告。如果今天我希望有用到才增加,沒用到就刪除,能最有效率的使用記憶體空間,則 List 絕對是箇中翹楚!然而 C/C++ 中沒有像 C# 這麼方便的語法糖,直接 var list = new List(); 就能使用,尤其在 MCU 領域中更是以 C 語言為主,且對記憶體的使用斤斤計較,因此今天就來探討該如何自己實現基礎的 List 功能,又名 “鏈結串列 (Linked List)”! 首先需要了解一個簡單的 List 要有什麼功能?需要能動態增加 (Add);能動態刪除 (Clear);能動態取出 (Display)。 事前準備 那要怎麼實現上述提到的功能呢?首先要先建立一個 struct 這個 struct 看你需要放什麼資料就建什麼樣的 struct,只是最後一定要有一個自己這個 struct 的指標來指向下一個 item。例如我要建一個 “名字對應年齡的資料結構”: 12345678 #define NAME_LENGTH 255struct MyStruct{ char Name[NAME_LENGTH]; int Age; struct MyStruct* Next; // 一定要有這行!}; 資料結構知道了以後,我們會需要知道這個鏈結串列的 頭 跟 尾,故在全域變數中宣告兩個 struct 變數並指向 NULL: 12 struct MyStruct* _head = NULL;struct MyStruct* _end = NULL; 動態增加 (Add) 接著可以開始來實現 Add function 了!整個概念就是: 先用 malloc 動態跟記憶體要了一塊 struct 大小的空間。 接著把資料填入 struct 內 然後確保 struct 指向下一個 item 的位址為 NULL 確認現在要加入的資料是不是第一筆資料,如果是則將剛剛全域的 head 指向現在 malloc 的位址!如果不是則將現在的位址放到全域 end 的下一筆資料 (next)! 最後告訴大家尾巴的位址就是現在這個位址!(所以如果是第一筆資料則頭 (head) 跟尾 (end) 的位址會指向同一個地方) 1234567891011121314151617181920212223242526272829 bool LinkedList_Add(char* name, int age){ struct MyStruct* current = NULL; // 動態跟記憶體要一個空間,如果沒有空間了則 malloc 會返回 NULL current = (struct MyStruct*)malloc(sizeof(struct MyStruct)); if (current == NULL) return false; // 將資料填入 strncpy(current->Name, name, NAME_LENGTH - 1); current->Name[NAME_LENGTH - 1] = '\0'; current->Age = age; // 確保最後資料為 NULL current->Next = NULL; // 如果是第一筆資料則 head 為 NULL,故資料添加到 head // 反之則將資料添加到最後面 (end) 的資料的下一筆 (next) if (_head == NULL) _head = current; else { _end->Next = current; } // 最後面的資料就是現在添加的資料 _end = current; return true;} 動態清除 (Clear) & 動態顯示 (Display) 接著因為 malloc 的資料是放在 heap,而不是 stack,所以不會自己釋放。必須要自己 free 來釋放記憶體,否則會造成 memory leak。而 清除 (clear) 與顯示 (display) 的概念是相似的,只是取出與 free 的差別而已,故放在一起展示。 1234567891011121314151617181920212223242526 void LinkedList_Display(void){ // 從 head 取出現在的資料,如果是 NULL 則代表沒有添加任何資料 // 由於每一筆資料都會確保 next 為 NULL,除非有下一筆資料添加,故若 next 為NULL 則代表沒有下一筆資料! struct MyStruct* current = NULL; current = _head; while (current != NULL) { printf("%s's Age is %d\n", current->Name, current->Age); current = current->Next; }}void LinkedList_Clear(void){ // 概念與 display 相似, // 只是由於 malloc 是將記憶體放在 heap,而不是 stack,所以並不會自己釋放,必須要自己 free 來釋放記憶體,否則會造成 memory leak struct MyStruct* current = NULL; current = _head; while (current != NULL) { _end = current; current = current->Next; free(_end); }} 至此,一個簡單的 Linked List 就完成了!雖然還沒達到 List 這麼樣的靈活變化,但對我目前的專案來說已經足夠!其實整個 Linked List 的可玩性還是滿多的,未來專案有用到再來跟大家補充說明! 完整的 sample code 我放在 github 上了,歡迎下載玩玩看! github sample code:https://github.com/leoli-git/MySampleCode/tree/main/MyLinkedList

本文由leotalk-engineerlifecom提供 原文連結

寫了 5860316篇文章,獲得 23313次喜歡
精彩推薦