微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 硬件工程师文库 > 周立功新著内容分享:双向链表是什么?

周立功新著内容分享:双向链表是什么?

时间:08-22 来源:电子发烧友网工程师 点击:

近日周立功教授公开了数年的心血之作《程序设计与数据结构》,电子版已无偿性分享到电子工程师与高校群体下载,经周立功教授授权,特对本书内容进行连载。

>>>> 1.1 双向链表

单向链表的添加、删除操作,都必须找到当前结点的上一个结点,以便修改上一个结点的p_next指针完成相应的操作。由于单向链表的结点没有指向其上一个结点的指针,因此只有从头结点开始遍历链表。当某一结点的p_next指向当前结点时,表明它为当前结点的上一个结点。显然每次都要从头开始遍历,其效率极为低下。在单向链表中,之所以可以直接获取单向链表中当前结点的下一个结点,是因为结点中包含了指向下一个结点的指针p_next。如果在双向链表的结点中再增加一个指向它的前一个结点的前向指针p_prev,则一切问题将迎刃而解。那么,既有指向下一个结点的指针,又有指向前一个结点的指针的链表称之为双向链表,示意图详见图3.15。

图3.15  双向链表示意图

与单向链表一样,双向链表也定义了一个头结点,基于单向链表将应用数据与链表结构相关数据完全分离的设计思想,则双向链表结点仅保留p_next和p_prev指针。其数据结构定义如下:

typedef struct _dlist_node{

           struct _dlist_node  *p_next;

           struct _dlist_node  *p_prev;

}dlist_node_t; 

其中,dlist是double list 的缩写,表明该结点是双向链表结点。由此可见,虽然前向指针使得寻找链表的上一个结点变得非常容易,但由于结点中新增了一个指针,因此其内存开销将会是单向链表的两倍。在实际应用中,应该权衡效率与内存空间,在内存资源非常紧缺的场合,如果结点的添加、删除操作很少,一点效率的影响可以接受,则选择使用单向链表。而不是一味地追求效率,认为双向链表比单向链表好,始终选择使用双向链表。

在图3.15中,头结点的p_prev和尾结点的p_next直接被设置为了NULL,此时,如果要直接由头结点找到尾结点,或者由尾结点找到头结点,都必须遍历整个链表。可以对这两个指针稍加利用,使头结点的p_prev指向尾结点,尾结点的p_next指向头结点,此时,该双向链表就成了一个循环双向链表,示意图详见图3.16。

图3.16  循环双向链表示意图

由于循环双向链表的效率更高,可以直接从头结点找到尾结点,或者从尾结点找到头结点,且没有额外的内存空间消耗,仅仅是使用了两个不打算使用的指针,算是废物利用,因此下面介绍的双向链表均视为循环双向链表。

类似于单向链表,虽然头结点与普通结点的内容完全相同,但它们的含义却有所区别,头结点是链表的头,代表了整个链表,拥有此头结点,就表示其拥有了整个链表。为了便于区分头结点与普通结点,可以单独定义一个头结点类型。比如:

typedef  dlist_node_t  dlist_head_t;

当需要使用双向链表时,首先需要使用该类型定义一个头结点。比如:

dlist_head_t  head;

由于此时还没有添加其它任何结点,仅存在一个头结点,因此该头结点既是第一个结点(头结点),又是最后一个结点(尾结点)。按照循环链表的定义,尾结点的p_next指向头结点,头结点的p_prev指向尾结点,仅有一个结点的示意图详见图3.17。

图3.17  空链

显然,仅有头结点时,其p_next和p_prev都指向本身。即:

head.p_next = &head;

head.p_prev = &head; 

为了避免用户直接操作成员,需要定义一个初始化函数,专门用于初始化链表头结点中各个成员的值,其函数原型(dlist.h)为:

int dlist_init(dlist_head_t *p_head);

其中,p_head指向待初始化的链表头结点。其调用形式如下:

dlist_head_t  head;

    dlist_init(&head); 

dlist_init()函数的实现详见程序清单3.33。

程序清单3.33  双向链表初始化函数

1    int dlist_init(dlist_head_t *p_head)

2    {

3             if (p_head == NULL){

4                  return -1;

5             }

6             p_head -> 6             p_head -> p_next = p_hea

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top