日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

C语言实现通用链表初步(四)----双向链表

發布時間:2025/3/15 编程问答 13 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C语言实现通用链表初步(四)----双向链表 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在前面的文章中,我們討論了如何實現通用類型的鏈表,方法是用void *類型的指針,指向數據。那么還有其他的方法嗎(不考慮內核鏈表)?

答案是肯定的。用零長數組也可以實現。


struct node_info {struct node_info *next;struct node_info *prev;char data[0]; };
這里的最后一個元素,是元素個數為0的數組。 其不占用任何空間,甚至是一個指針的空間都不占!

注意:在標準C和C++中,長度為0的數組是被禁止使用的。不過在GNU C中,存在一個非常奇怪的用法,那就是長度為0的數組。

在一個結構體的最后?,定義一個長度為0的數組,就可以使得這個結構體是可變長的。對于編譯器來說,這個長度為0的數組并不占用空間,因為數組名本身不占空間,它只是一個偏移量,?數組名這個符號本身代 表了一個不可修改的地址常量?

先來看看整個代碼的頭文件吧

#pragma once struct node_info {struct node_info *next;struct node_info *prev;char data[0]; };struct student {char name[20];unsigned char age;};//for test//有頭雙向循環鏈表 struct dlist_info {struct node_info *head;void (*add_head)(struct dlist_info *info,const void *data, size_t size);void (*add_tail)(struct dlist_info *info,const void *data, size_t size);void (*del)(struct node_info *node);struct node_info* (*find)(struct dlist_info *info,int (*compare)(void *dest_data, void *key_data), void *key_data);void (*for_each_safe)(struct dlist_info *info,void (*todo)(struct node_info *));};int dlist_init(struct dlist_info *info); void dlist_destroy(struct dlist_info *info);#define node_init(node) \do\{\(node)->next = (node);\(node)->prev = (node);\}while(0)#define dlist_is_empty(info) \((info)->head->next == (info)->head) 接下來我們實現一些方法

1.頭插

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> #include "dlist.h"/* 有頭循環雙鏈表*/static void dlist_add_head(struct dlist_info *info,const void *my_data, size_t size) {assert(info != NULL && my_data != NULL);if (size == 0) {return ;}struct node_info *new_node = (struct node_info *)malloc(sizeof(struct node_info) + size);if (new_node == NULL) {fprintf(stderr, "out of memory\n");return ;} //數據域,內存拷貝memmove(new_node->data, my_data, size);//指針域修改new_node->next = info->head->next;new_node->prev = info->head;info->head->next = new_node;new_node->next->prev = new_node; }size 表示數據域占用了多少個字節。memmove(new_node->data, my_data, size); 這句話把用戶的數據拷貝到了結構體的最后。關于指針域的修改,是不是有點繞呢?沒有關系,畫圖就明白了。


2.尾插

static void dlist_add_tail(struct dlist_info *info,const void *my_data, size_t size) {assert(info != NULL && my_data != NULL);if (size == 0) {return ;}struct node_info *new_node = (struct node_info *)malloc(sizeof(struct node_info) + size);if (new_node == NULL) {fprintf(stderr, "out of memory\n");return ;} //數據域,內存拷貝memmove(new_node->data, my_data, size);//指針域修改new_node->next = info->head;new_node->prev = info->head->prev;info->head->prev->next = new_node;info->head->prev = new_node;}

3.刪除

static void dlist_del(struct node_info *node) {assert(node != NULL);node->next->prev = node->prev;node->prev->next = node->next;node_init(node); free(node); }因為申請空間的時候是帶著size一起申請的,所以這里的釋放就全部釋放了,不存在內存泄漏。


4.查找

static struct node_info *dlist_find(struct dlist_info *info,int (*key)(void *dest_data, void *key_data), void *key_data) {assert(info != NULL && key != NULL);if (dlist_is_empty(info)) {fprintf(stderr, "dlist is empty\n");return NULL;}struct node_info *cur = NULL;for (cur = info->head->next; cur != info->head; cur = cur->next) {if (key(cur->data, key_data) != 0) {return cur;}}return NULL; } 回調函數需要用戶自己實現,不用多說。

5.安全遍歷

static void dlist_for_each_safe(struct dlist_info *info,void (*todo)(struct node_info *)) {assert(info != NULL && todo != NULL);struct node_info *cur = NULL;struct node_info *Next = NULL;for (cur = info->head->next; cur != info->head;cur = Next) {Next = cur->next;todo(cur);} }
6.構造和析構

int dlist_init(struct dlist_info *info) {info->head = (struct node_info *)malloc(sizeof(struct node_info));if (info->head == NULL) {fprintf(stderr, "Error:Out of memory\n");return -1;}/*頭節點空間的初始化*/node_init(info->head);/*函數指針的掛接*/info->add_head = dlist_add_head;info->add_tail = dlist_add_tail;info->del = dlist_del;info->find = dlist_find;info->for_each_safe = dlist_for_each_safe;return 0; }void dlist_destroy(struct dlist_info *info) {// 依次刪除,直到為空while (!dlist_is_empty(info)) {dlist_del(info->head->next);} free(info->head); }
接下來是單元測試。

測試一下頭插和尾插吧。

#include "uni_test.h"#include "dlist.h"#include <stdio.h>void setup (void) {// will excute in every case }void teardown (void) {}void print_student(struct node_info *node) {struct student *p = (struct student *)(node->data);printf("Name: %15s Age:%d\n",p->name,p->age);}int compare_student(void *dest,void *src) {struct student *p1 = dest;struct student *p2 = src;if(strcmp(p1->name,p2->name)==0)return 1;elsereturn 0; }START_TEST(my_dlist_1) {struct student students[8] = {{"WangDong",18},{"LiuMing",19},{"SunYazhou",21},{"ChenYu",27},{"LiuXuewei",28},\{"ZhangGuorong",47},{"LiuDehua",53},{"WangGuozhen",48}};struct dlist_info list;dlist_init(&list);int i = 0;for(;i<sizeof(students)/sizeof(students[0]);++i)list.add_head(&list,students+i,sizeof(students[0]));list.for_each_safe(&list,print_student);printf("===========\n");dlist_destroy(&list);} END_TESTSTART_TEST(my_dlist_2) {struct student students[8] = {{"WangDong",18},{"LiuMing",19},{"SunYazhou",21},{"ChenYu",27},{"LiuXuewei",28},\{"ZhangGuorong",47},{"LiuDehua",53},{"WangGuozhen",48}};struct dlist_info list;dlist_init(&list);int i = 0;for(;i<sizeof(students)/sizeof(students[0]);++i)list.add_tail(&list,students+i,sizeof(students[0]));list.for_each_safe(&list,print_student);printf("===========\n");dlist_destroy(&list);} END_TEST
運行結果如圖


Running suite(s): two_way_list_with_head

Name: ? ? WangGuozhen? Age:48

Name:? ? ? ? LiuDehua? Age:53

Name:? ? ZhangGuorong? Age:47

Name: ? ? ? LiuXuewei? Age:28

Name:? ? ? ? ? ChenYu? Age:27

Name: ? ? ? SunYazhou? Age:21

Name: ? ? ? ? LiuMing? Age:19

Name:? ? ? ? WangDong? Age:18

===========

Name:? ? ? ? WangDong? Age:18

Name: ? ? ? ? LiuMing? Age:19

Name: ? ? ? SunYazhou? Age:21

Name:? ? ? ? ? ChenYu? Age:27

Name: ? ? ? LiuXuewei? Age:28

Name:? ? ZhangGuorong? Age:47

Name:? ? ? ? LiuDehua? Age:53

Name: ? ? WangGuozhen? Age:48

===========


測試一下遍歷,在遍歷的過程中,我們把節點給刪除了。這可以體現出安全遍歷的好處。

START_TEST(my_dlist_3)//遍歷刪除 {struct student students[8] = {{"WangDong",18},{"LiuMing",19},{"SunYazhou",21},{"ChenYu",27},{"LiuXuewei",28},\{"ZhangGuorong",47},{"LiuDehua",53},{"WangGuozhen",48}};struct dlist_info list;dlist_init(&list);int i = 0;for(;i<sizeof(students)/sizeof(students[0]);++i)list.add_tail(&list,students+i,sizeof(students[0]));list.for_each_safe(&list,list.del);list.for_each_safe(&list,print_student);printf("===========\n");dlist_destroy(&list);} END_TEST
運行結果是:

===========


果然沒有節點了。


查找并刪除。

START_TEST(my_dlist_4)//查找并刪除 {struct student students[8] = {{"WangDong",18},{"LiuMing",19},{"SunYazhou",21},{"ChenYu",27},{"LiuXuewei",28},\{"ZhangGuorong",47},{"LiuDehua",53},{"WangGuozhen",48}};struct dlist_info list;dlist_init(&list);int i = 0;for(;i<sizeof(students)/sizeof(students[0]);++i)list.add_tail(&list,students+i,sizeof(students[0]));list.del(list.find(&list,compare_student,"ChenYu"));list.for_each_safe(&list,print_student);printf("===========\n");dlist_destroy(&list);} END_TEST

Name:? ? ? ? WangDong? Age:18

Name: ? ? ? ? LiuMing? Age:19

Name: ? ? ? SunYazhou? Age:21

Name: ? ? ? LiuXuewei? Age:28

Name:? ? ZhangGuorong? Age:47

Name:? ? ? ? LiuDehua? Age:53

Name: ? ? WangGuozhen? Age:48

===========


(完)

總結

以上是生活随笔為你收集整理的C语言实现通用链表初步(四)----双向链表的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 六月色 | 视频这里只有精品 | v在线| 久久久久性色av无码一区二区 | 99热网 | 国产欧美视频一区二区三区 | 免费看裸体网站视频 | 色播在线播放 | 日日碰狠狠躁久久躁蜜桃 | 尹人综合在线 | 高h大肚孕期孕妇play | 久久伊人操| 日韩精品视频一区二区在线观看 | 亚洲免费观看高清 | 亚洲成熟丰满熟妇高潮xxxxx | 人人妻人人澡人人爽人人精品 | 韩国91视频 | 日韩毛片一级 | 夜夜撸| 亚洲黄色在线免费观看 | 成人a级免费视频 | 毛片毛片毛片毛片毛片毛片毛片毛片 | 多毛的亚洲人毛茸茸 | 亚洲人天堂 | 免费日皮视频 | 福利社午夜影院 | 男生和女生操操 | 亚洲五月激情 | 亚洲精品中文字幕成人片 | 久久久久久夜 | 一二区视频 | www..com色 | 色一情一伦一子一伦一区 | 国产第一页屁屁影院 | 高潮av在线 | 日韩电影网址 | 黄色69 | 日韩爱爱网 | 日本黄色录相 | 日韩精品卡通动漫网站 | 蜜臀av一区 | 日韩欧美中 | 亚洲无卡视频 | av片一区二区三区 | 西西毛片 | 欧美福利小视频 | 九色91popny蝌蚪新疆 | 五月婷婷综合网 | 国产玖玖在线 | 欧美高清hd | 91偷拍一区二区三区精品 | 欧美bbbbbbbbbbbb18av | 日产精品久久久久 | 青青欧美| 久久久九九九热 | 精品人妻一区二 | 激情综合五月 | 91精品国产自产在线观看 | 97超碰精品 | 少妇人妻综合久久中文字幕 | 欧美精品成人一区二区三区四区 | 麻豆国产精品777777在线 | 亚洲色图制服丝袜 | 粗了大了 整进去好爽视频 日本女优中文字幕 | 日本久久一区二区 | 极品粉嫩国产18尤物 | 蜜桃视频在线播放 | 亚洲免费成人网 | 亚洲成年人免费观看 | 一区二区三区小说 | 手机在线成人av | 久久精品99国产精 | 午夜久久久久久噜噜噜噜 | 精品无码一区二区三区爱欲 | 国产精品麻豆视频 | 日韩精品偷拍 | 亚洲热热 | 插插看 | 一区二区视频在线免费观看 | 中文在线日韩 | 久草视频福利在线 | 五月天综合视频 | 亚洲人无码成www久久 | 91久久国语露脸精品国产高跟 | 五月天亚洲色图 | 久久亚洲成人 | 成人a级免费视频 | 亚洲欧美精品久久 | 亚洲а∨天堂久久精品2021 | 相亲对象是问题学生动漫免费观看 | 国内精品人妻无码久久久影院蜜桃 | 欧美日韩一区二区三区视频 | 欧美videos另类精品 | 免费看污的网站 | 99国产精品免费 | 欧美成人精品一区 | 久久久久久久亚洲精品 | 欧美性生活一区二区 | 伊人焦久影院 |