新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 如何定義鏈表結點的數據結構?

        如何定義鏈表結點的數據結構?

        作者: 時間:2018-07-25 來源:網絡 收藏

        2 {

        本文引用地址:http://www.104case.com/article/201807/383764.htm

        3 if (p_pos) { // 找到p_pos指向的結點

        4 return p_pos->p_next;

        5 }

        6 return NULL;

        7 }

        8

        9 slist_node_t *slist_begin_get (slist_head_t *p_head)

        10 {

        11 return slist_next_get(p_head, p_head);

        12 }

        13

        14 slist_node_t *slist_end_get (slist_head_t *p_head)

        15 {

        16 return NULL;

        17 }

        程序中獲取的第一個用戶結點,其實質上就是頭結點的下一個結點,因此可以直接調用slist_next_get()實現。盡管slist_next_get()在實現時并沒有用到參數p_head,但還是將p_head參數傳進來了,因為實現其它的功能時將會用到p_head參數,比如,判斷p_pos是否在鏈表中。當有了這些接口函數后,即可完成遍歷,詳見程序清單3.18。

        程序清單3.18 使用各個接口函數實現遍歷的范例程序

        1 slist_node_t *p_tmp = slist_begin_get(head);

        2 slist_node_t *p_end = slist_end_get(head);

        3 while (p_tmp != p_end){

        4 printf(%d , ((slist_int_t *)p_tmp)->data);

        5 p_tmp = slist_next_get(head, p_tmp);

        6 }

        由此可見,slist_begin_get()和slist_end_get()的返回值決定了當前有效結點的范圍,其范圍為一個半開半閉的空間,即:[begin,end),包括begin,但是不包括end。當begin與end相等時,表明當前鏈表為空,沒有一個有效結點。

        在程序清單3.18所示的遍歷程序中,只有printf()語句才是用戶實際關心的語句,其它語句都是固定的模式,為此可以封裝一個通用的遍歷函數,便于用戶順序處理與各個相關聯的數據。顯然,只有使用鏈表的用戶才知道數據的具體含義,對數據的實際處理應該交由用戶完成,比如,程序清單3.18中的打印語句,因此訪問數據的行為應該由用戶定義,定義一個回調函數,通過參數傳遞給遍歷函數,每遍歷到一個結點時,都調用該回調函數處理對數據進行處理。遍歷鏈表的函數原型(slist.h)為:

        typedef int (*slist_node_process_t) (void *p_arg, slist_node_t *p_node);

        int slist_foreach(slist_head_t *p_head,

        slist_node_process_t pfn_node_process,

        void *p_arg);

        其中,p_head指向鏈表頭結點,pfn_node_process為結點處理回調函數。每遍歷到一個結點時,都會調用pfn_node_process指向的函數,便于用戶根據需要自行處理結點數據。當調用該回調函數時,會自動將用戶參數p_arg作為回調函數的第1個參數,將指向當前遍歷到的結點的指針作為回調函數的第2個參數。

        當遍歷到某個結點時,用戶可能希望終止遍歷,此時只要在回調函數中返回負值即可。一般地,若要繼續遍歷,函數執行結束后返回0。slist_foreach()函數的實現詳見程序清單3.19。

        程序清單3.19 遍歷鏈表范例程序

        1 int slist_foreach( slist_head_t *p_head,

        2 slist_node_process_t pfn_node_process,

        3 void *p_arg);

        4

        5 {

        6 slist_node_t *p_tmp, *p_end;

        7 int ret;

        8

        9 if ((p_head == NULL) || (pfn_node_process == NULL)){

        10 return -1;

        11 }

        12 p_tmp = slist_begin_get(p_head);

        13 p_end = slist_end_get(p_head);

        14 while (p_tmp != p_end){

        15 ret = pfn_node_process(p_arg, p_tmp);

        16 if (ret 0) return ret; // 不再繼續遍歷

        17 p_tmp = slist_next_get(p_head, p_tmp); // 繼續下一個結點

        18 }

        19 return 0;

        20 }

        現在可以使用這些接口函數,迭代如程序清單3.14所示的功能,詳見程序清單3.20。

        程序清單3.20 管理int型數據的范例程序

        1 #include

        2 #include slist.h

        3

        4 typedef struct _slist_int {

        5 slist_node_t node; // 包含

        6 int data; // int類型數據

        7 }slist_int_t;

        8

        9 int list_node_process (void *p_arg, slist_node_t *p_node)

        10 {

        11 printf(%d , ((slist_int_t *)p_node)->data);

        12 return 0;

        13 }

        14

        15 int main(void)

        16 {

        17 slist_head_t head; // 定義鏈表頭結點

        18 slist_int_t nodel, node2, node3;

        19 slist_init(head);

        20

        21 node1.data = 1;

        22 slist_add_tail(head, (node1.node));

        23 node2.data = 2;

        24 slist_add_tail(head, (node2.node));

        25 node3.data = 3;

        26 slist_add_tail(head, (node3.node));

        27 slist_foreach(head, list_node_process, NULL); // 遍歷鏈表,用戶參數為NULL

        28 return 0;

        29 }


        上一頁 1 2 下一頁

        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 正镶白旗| 海城市| 临颍县| 日喀则市| 英超| 湄潭县| 涟水县| 嵊州市| 正定县| 田东县| 本溪| 卢氏县| 洪洞县| 儋州市| 阿拉善盟| 安吉县| 东兰县| 武冈市| 湖南省| 汝南县| 青浦区| 沙河市| 清涧县| 中山市| 珲春市| 定州市| 嘉黎县| 达州市| 龙岩市| 灵石县| 临武县| 女性| 柘城县| 锦州市| 望城县| 鄯善县| 嘉鱼县| 铜川市| 唐海县| 莲花县| 周口市|