数据结构 之 带头循环双链表

在数据结构中我们经常会接触到链表,链表也分好多种,带头结点和不带头结点、循环和不循环、单向链表和双向链表
而在众多不同结构的链表中 带头循环双链表可以说是一种最优的链表结构
相比于单链表只能访问当前结点的后续结点的局限性,双链表既可以访问前面结点也可以访问后面结点
其次循环的情况下相比于非循环的链表在访问尾节点时,非循环的链表余姚遍历整个链表才能访问尾节点,而循环链表由于它的循环特性,不用遍历链表,头结点前一个结点就是尾节点,在访问速度上大大优于非循环链表
带头相对于不带头在对链表头插时候不会改变头结点的地址,不带头的每次头插和头删都会改变头指针,而带头结点可以解决这个问题


定义我们双链表结点的结构体,包括三个部分,_next和_prev指针分别指向下一个和前一个结点,_data用来存放数据
typedef  int  DataType ;
typedef  struct  DListNode //结点
{
        struct  DListNode * _next;
        struct  DListNode * _prev;
        DataType  _data;
} DListNode ;

对于双链表的基础操作包括结点的插入,结点的删除,寻找某个结点,打印链表,销毁链表等
DListNode* BuyDListNode( DataType  x ); //创建新结点
DListNode * DListInit(); //双链表初始化
void  DListDestory( DListNode *  head ); //销毁链表
void  DListPrint( DListNode *  head ); //打印链表
void  DListPushBack( DListNode *  head ,  DataType  x ); //尾插
void  DListPushFront( DListNode *  head ,  DataType  x ); //头插
void  DListPopBack( DListNode *  head ); //尾删
void  DListPopFront( DListNode *  head ); //头删
DListNode * DListFind( DListNode *  head ,  DataType  x ); //寻找值为x的结点,返回它的地址
void  DListInsert( DListNode *  pos ,  DataType  x ); //在pos位置插入值为x的新结点
void  DListErase( DListNode *  pos ); //删除pos位置结点

创建新的结点时用malloc申请空间,注意要判断是否申请成功,同时对_data赋值,对_prev 和_next指针置空,返回新开辟的结点地址
DListNode * BuyDListNode( DataType  x )//创建新的结点
{
        DListNode * NewNode = ( DListNode *)malloc( sizeof ( DListNode ));
        if  (NewNode)
       {
              NewNode->_data =  x ;
              NewNode->_next =  NULL ;
              NewNode->_prev =  NULL ;
               return  NewNode;
       }
        return  NULL ;
}

带头循环双链表初始化时是初始化链表的 头Head,同样用malloc申请空间,此时链表里面为空,但是由于是循环链表,所以这块对 Head->_next Head->_prev都指向头,也就是自己本身,返回Head的地址
DListNode * DListInit() //链表初始化
{
        DListNode * Head = ( DListNode *)malloc( sizeof ( DListNode ));
        if  (Head)
       {
              Head->_next = Head;
              Head->_prev = Head;
               return  Head;
       }
        return  NULL ;
}

插入操作
void  DListPushBack( DListNode *  head ,  DataType  x ) //尾插
{
        DListNode * NewNode = BuyDListNode( x );
        DListNode * cur =  head ;
        while  (cur->_next !=  head )
       {
              cur = cur->_next;
       }
       cur->_next = NewNode;
       NewNode->_prev = cur;
       NewNode->_next =  head ;
        head ->_prev = NewNode;
}
void  DListPushFront( DListNode *  head ,  DataType  x ) //头插
{
        DListNode * NewNode = BuyDListNode( x );
        DListNode * cur =  head ->_next;
        head ->_next = NewNode;
       NewNode->_prev =  head ;
       NewNode->_next = cur;
       cur->_prev = NewNode;
}
void  DListInsert( DListNode *  pos ,  DataType  x ) //在pos位置插入值为x的新的结点
{
        DListNode * tmp =  pos ->_prev;
        DListNode * NewNode = BuyDListNode( x );
       tmp->_next = NewNode;
       NewNode->_prev = tmp;
       NewNode->_next =  pos ;
        pos ->_prev = NewNode;
}
删除操作
void  DListPopBack( DListNode *  head ) //尾删
{
        DListNode * cur =  head ->_prev->_prev;
       free( head ->_prev);
        head ->_prev = cur;
       cur->_next =  head ;
}
void  DListPopFront( DListNode *  head ) //头删
{
        DListNode * cur =  head ->_next->_next;
       free( head ->_next);
        head ->_next = cur;
       cur->_prev =  head ;
}
void  DListErase( DListNode *  pos ) //删除pos位置结点
{
        DListNode * tmp1 =  pos ->_prev;
        DListNode * tmp2 =  pos ->_next;
       tmp1->_next = tmp2;
       tmp2->_prev = tmp1;
        free(pos);
        pos = NULL;
}

寻找值为x的结点
DListNode * DListFind( DListNode *  head ,  DataType  x ) //寻找值为x的结点,返回它的地址
{
        DListNode * tmp =  head ->_next;
        while  (tmp->_next !=  head ->_next)
       {
               if  (tmp->_data ==  x )
              {
                      return  tmp;
              }
              tmp = tmp->_next;
       }
        return  NULL ;
}
打印链表
void  DListPrint( DListNode *  head ) //打印链表
{
        assert ( head );
        DListNode * cur =  head ;
       printf( "Head->" );
        while  (cur->_next !=  head )
       {
              cur = cur->_next;
              printf( "%d->" , cur->_data);
       }
       printf( "Head\n" );
}
销毁链表
void  DListDestory( DListNode *  head )
{
        if  ( head  ==  NULL )
       {
               return ;
       }
        DListNode * cur1 =  head ;
        DListNode * cur2 =  head ->_next;
        while  (cur2)
       {
              free(cur1);
              cur1 = cur2;
              cur2 = cur2->_next;
       }
}





你可能感兴趣的:(数据结构)