周立功新著内容分享:双向链表是什么?
6 p_head -> 6 p_head -> p_next = p_head;
7 p_head -> p_prev = p_head;
8 return 0;
9 }与单向链表类似,将提供一些基础的操作接口,它们的函数原型如下:
dlist_node_t *dlist_prev_get (dlist_head_t *p_head, dlist_node_t *p_pos); // 寻找某一结点的前一结点
dlist_node_t *dlist_next_get (dlist_head_t *p_head, dlist_node_t *p_pos); // 寻找某一结点的后一结点dlist_node_t *dlist_tail_get (dlist_head_t *p_head); // 获取尾结点
dlist_node_t *dlist_begin_get (dlist_head_t *p_head); // 获取开始位置,第一个用户结点
dlist_node_t *dlist_end_get (dlist_head_t *p_head); // 获取结束位置,尾结点下一个结点的位置对于dlist_prev_get()和dlist_next_get(),在链表结点中已经存在指向前驱后后继的指针,详见程序清单3.34。
程序清单3.34 得到结点前驱和后继的函数实现
1 dlist_node_t *dlist_prev_get(dlist_head_t *p_head, dlist_node_t *p_pos)
2 {
3 if (p_pos != NULL){
4 return p_pos -> p_prev;
5 }
6 return NULL;
7 }
89 dlist_node_t *dlist_next_get(dlist_head_t *p_head, dlist_node_t *p_pos)
10 {
11 if (p_pos != NULL){
12 return p_pos -> p_next;
13 }
14 return NULL;
15 }dlist_tail_get()函数用于得到链表的尾结点,在循环双向链表中,头结点的p_reev即指向了尾结点,详见程序清单3.35。
程序清单3.35 dlist_tail_get()函数实现
1 dlist_node_t *dlist_tail_get(dlist_head_t *p_head)
2 {
3 if (p_head != NULL) {
4 return p_head->p_prev;
5 }
6 return NULL;
7 }dlist_begin_get()函数用于得到第一个用户结点,详见程序清单3.36。
程序清单3.36 dlist_begin_get()函数实现
1 dlist_node_t *dlist_begin_get(dlist_head_t *p_head)
2 {
3 if (p_head != NULL){
4 return p_head->p_next;
5 }
6 return NULL;
7 }dlist_end_get()用于得到链表的结束位置,当双向链表设计为循环双向链表时,则头结点的p_prev和尾结点的p_next都被有效地利用了,任何有效结点的p_next和p_prev都不再为NULL。显然,不能再以NULL作为结束位置了,当从第一个结点开始顺序访问链表的各个结点时,尾结点的下一个结点就是链表头结点(head),因此结束位置就是头结点本身。dlist_end_get()的实现详见程序清单3.37。
程序清单3.37 dlist_end_get()函数实现
1 dlist_node_t *dlist_end_get(dlist_head_t *p_head)
2 {
3 if (p_head != NULL) {
4 return p_head-> 4 return p_head->p_prev;
- 电源软启动的实用设计技巧(07-16)
- 周立功:动态分布内存——malloc()函数与calloc()函数(07-22)
- 周立功“程序设计与数据结构”:深度解剖动态分布内存的free()函数与realloc()函数(07-25)
- 周立功教你学程序设计技术:做好软件模块的分层设计,回调函数要这样写(07-30)
- 周立功教你学C语言编程:教你数组是如何保存指针的(07-31)
- 算法的泛化问题,这些坑你可能都经历过!|周立功教你学软件设计(08-01)