可能有的读者认为上面得代码有点复杂化了,其实不然,我们仅仅是写出了我们要讲解的双链表实现中最简单的部分,其实现的功能是创建一个链表,在链表末端添加结点,然后打印出链表中结点里存放的数据项,对代码的总体动能有了一个大概的了解之后,现在我们来逐一分析代码,为接下来添加功能模块打开思路。
从main()函数开始,通过 DList* dlist = dlist_head_create();我们创建了一个头节点。值得注意的是,为了链表更加通用和符合实际需求,我们在此创建的链表存放的是结构,因为现实中在使用链表时,绝大部分都是存放结构的,而前一篇文章中我们创建单链表时我们存放的是数据,所以这一点读者是要引起注意的,接下来是一个for循环语句,在for循环语句中我们首先使用DStu* stu =(DStu*) malloc(sizeof(DStu));为stu分配了空间,这也是很多读者的一个易错点,不分配就使用下面的stu->score = i;语句,从而导致出错,如果读者对于指针还不是很了解的话可以看看我前面的文章《C语言的那些小秘密之指针》,在往下看dlist_append(dlist, (void*)stu);语句,从函数名称我们也可以看出它的功能是在链表的末端添加结点的,在函数里面我们使用了一个if判断语句来看分配的结点是否成功,如果成功继续往下执行,如果失败则返回DLIST_RETURN_FAIL。对于第一次分配的节点我们使用了 thiz->head = node;语句使其变为头结点,在第二次调用dlist_append(dlist, (void*)stu)函数分配结点之后,由于头结点已经不再为空,那么跳过if(thiz->head == NULL)语句,执行以下语句:
cursor = thiz->head; while(cursor != NULL && cursor->next != NULL) { cursor = cursor->next; } |
其功能为查找末端结点,然后使用 cursor->next = node; node->prev = cursor;语句来将刚刚创建的新结点node作为尾结点。main()函数中的for循环语句执行完之后就轮到了调用dlist_print(dlist, print_int)函数打印我们创建的双向链表保存的数据值了,在这里的时候我们用了前面我博客中提到的函数指针作为参数的使用,如果有对函数指针不熟悉的读者可以参考我之前写的一篇博客《C语言的那些小秘密之函数指针》,到此读者应该都理解了上面的代码,但是其中有个值得注意的地方,那就是main()函数中使用dlist_append(dlist, (void*)stu);的时候,我们传递的是一个无类型的指针,在创建新结点的时候,我们使用了一句node->data =(DStu*)data;进行一个强制转换,使得链表中的数据域指向的就是我们使用DStu* stu =(DStu*) malloc(sizeof(DStu));所创建的空间。创建了空间之后当然要释放掉,所以接下来我们就添加一个释放功能模块。新添加的代码我们用红色部分来标记。以便于读者的阅读
|