《数据结构和算法》之双向链表

来源:互联网 发布:淘宝店铺怎么加入淘客 编辑:程序博客网 时间:2024/05/16 16:14
1,双向链表的定义:


       双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。

       怎样理解双向链表,用生活中的一个例子来解释一下:最开始的火车是只有一个火车头的,当一辆火车从A->B->C->D->E->F->G->H->J->K->L这条路线进行行驶,假设或者运行到H站点要运送一批货物到G站点,只能通过H->J->K->L->A->B->C->D->F->G这个路线来进行,相当于是单向循环链表的形式。这个时候大家可以看到很费时和费力,严重的浪费时间和资源,这个时候人们就想了,如果火车可以倒着走那不就很方便吗,于是火车慢慢地开始有了两个火车头,这样可以往后走,直接后退一个站点,这样就可以轻松实现K->G的运输工作。这个小例子就类似于双向链表,但是真正意义上的双向链表跟这个又是有一点的区别,那么这个时候相对于单链表而言。双向链表就可以定义如下的结构体:

typedef struct DualNode{ElemType data;struct DualNode *prior;  //前驱结点struct DualNode *next;   //后继结点 }DualNode, *DuLinkList; 

        如下图1,双向链表的结点结构示意图以及空链表的结构示意图

                                                                 

                                                                                                                    图1 双向链表结点结构图

       在图1中可以看到,结点结构比之前的单链表多了一个结点,多一个头指针prior,存放着前驱结点的指针,当双向链表的两个结点都为空的时候则为空链表。

                        

                                                                                                                图2 非空的双向循环链表

    对于非空双向链表中的一个结点p,它的后继结点的前驱结点是什么? 当然就是它自己。

2,双向链表的插入操作

                                

                                                                                                         图3 可以看到双向循环链表的插入操作

              在图3中可以看到具体的操作步骤,具体代码实现如下:

                                                              

s->next = p;s->prior = p->prior;p->prior->next = s;p->prior = s;


       这四步分别对应着图3中的四步操作,首先将s结点的后继指针指向p;接着将s的前驱结点赋值为p的前驱指针;p的前驱结点的后继结点赋值为s;最后将p的前驱结点赋值为s。

3,双向链表的删除操作

            

                                                                                                   图4   删除操作

         在图4中可以看到,直接将前一个元素的后继指针指向后一个元素的前驱结点,同时将后一个元素的前驱结点指向前一个元素的前驱结点。代码即为:

                              

p->prior->next = p->next;p->next->prior = p->prior;free(p);

4,与单链表的区别

       (1)从任意一个结点开始,可以查找链表中的其他任意结点。
  (2)既可以依照后继的方向(向后)遍历,也可以依照前驱的方向(向前)遍历。
  (3)每个指针域中都增加了一个存储指针的空间,降低了存储密度。
       (4)可以在当前结点前面或者后面插入,可以删除前趋和后继(包括结点自己)。 单链表只能在结点后面插入和删除。
  (5)双向链表通过增加一定的空间复杂度,降低了向前遍历的时间复杂度。

                                                                       

   

1 0
原创粉丝点击