数据结构—循环链表与双向链表

作为想从事嵌入式方面的机械院学生,相比于搞计算机的,接触数据结构可能相对来说有点晚了,但我相信只要肯学习啥时都不算晚,博客就是督促我追赶上别人的最好见证。博客停更两天,第一天复习课程,昨天考试,当然,昨天也学习了,只是由于时间问题,加上调程序,没来得及更新博客,今天补上昨天的学习内容。接下来言归正传,首先来说下昨天的学习内容。

一 循环链表
在单链表中,可用于表示任意的线性关系,但是有些线性关系是循环的,即没有队尾元素(如生活中的月、周等),针对这些生活中的具体情况,为解决实际问题,我们引入循环链表。

循环链表的定义:将单链表中的最后一个数据元素的next指针指向第一个元素
当然,循环链表也拥有单链表的所有操作
循环链表之所以不同与单链表,是因为其引入了游标,可以完成一些新操作。
游标的定义:在循环链表中可以定义一个“当前”指针,这个指针通常称为游标,可以通过这个游标来遍历链表中的所有元素。
下边来说说循环链表的新操作:
获取当前游标指向的数据元素
CircleListNode* CircleList_Current(CircleList* list);
将游标重置指向链表中的第一个数据元素
CircleListNode* CircleList_Reset(CircleList* list);
将游标移动指向到链表中的下一个数据元素
CircleListNode* CircleList_Next(CircleList* list);
直接指定删除链表中的某个数据元素
CircleListNode* CircleList_DeleteNode(CircleList* list,CircleListNode* node);
下面为循环链表的各部分的实现代码:

#include <stdio.h>
#include <malloc.h>
#include "CircleList.h"

typedef struct _tag_CircleList
{
 CircleListNode header;
 CircleListNode* slider;
 int length;
}TCircleList;

CircleList* CircleList_Create()
{
 TCircleList* ret = (TCircleList*)malloc(sizeof(TCircleList));
 if(ret != NULL)
 {
  ret->length = 0;
  ret->header.next = NULL;
  ret->slider = NULL; 
 }
 return ret;
}

void CircleList_Destroy(CircleList* list)
{
   free(list);  
}

void CircleList_Clear(CircleList* list)
{
    TCircleList* slist = (TCircleList*)list;
    if(slist != NULL)
    {
     slist->length = 0;
     slist->header.next = NULL; 
     slist->slider = NULL; 
    }
}

int CircleList_Length(CircleList* list)
{
    TCircleList* slist = (TCircleList*)list;
    int ret = -1;
    if(slist != NULL)
    {
     ret = slist->length;    
    }
    return ret;
}

int CircleList_Insert(CircleList* list, CircleListNode* node, int pos)
{
   TCircleList* slist = (TCircleList*)list;
   int ret = (slist != NULL) && (pos >= 0) && (node != NULL);
   int i = 0;
   if(ret)
   {
    CircleListNode* current =(CircleListNode*)slist;
    for(i = 0;(current->next != NULL) && (i < pos);i++)
    {
      current = current->next;
    }
     node->next = current->next;
     current->next = node;
     if(slist->length == 0)
     { 
       slist->slider = node;
       node->next = node;
     }
     slist->length++;       
   }    
  return ret;
}

CircleListNode* CircleList_Get(CircleList* list, int pos)
{
   TCircleList* slist = (TCircleList*)list;
   CircleListNode* ret = NULL;
   int i = 0;
   if((pos >= 0) && (slist != NULL))
   {
    CircleListNode* current = (CircleListNode*)slist;
    for(i=0;i<pos;i++)
    {
     current = current->next; 
    }
      ret = current->next;
   }
   return ret;  
}

CircleListNode* CircleList_Delete(CircleList* list, int pos) // O(n)
{
    TCircleList* slist = (TCircleList*)list;
    CircleListNode* ret = NULL;
    int i = 0;

    if( (slist != NULL) && (pos >= 0) )
    {
        CircleListNode* current = (CircleListNode*)slist;
        CircleListNode* first = slist->header.next;
        CircleListNode* last = (CircleListNode*)CircleList_Get(slist, slist->length - 1);

        for(i=0; i<pos; i++)
        {
            current = current->next;
        }

        ret = current->next;
        current->next = ret->next;

        slist->length--;

        if( first == ret )
        {
            slist->header.next = ret->next;
            last->next = ret->next;
        }

        if( slist->slider == ret )
        {
            slist->slider = ret->next;
        }

        if( slist->length == 0 )
        {
            slist->header.next = NULL;
            slist->slider = NULL;
        }
    }

    return ret;
}

CircleListNode* CircleList_DeleteNode(CircleList* list,CircleListNode* node)
{
   TCircleList* slist = (TCircleList*)list;
   CircleListNode* ret = NULL;
   int i = 0;
   if(slist != NULL)
   {
    CircleListNode* current = (CircleListNode*)slist;
    for(i = 0;i < slist->length; i++)
    {
      if(current->next == node)
      {
      ret = current->next;  
      break;    
      }
      current = current->next; 
    }

    if(ret != NULL)
    {
    CircleList_Delete(slist,i); 
    }
   }
   return ret;
}

CircleListNode* CircleList_Reset(CircleList* list)
{
  TCircleList* slist = (TCircleList*)list;
  CircleListNode* ret = NULL;
  if(slist != NULL)
  {
    slist->slider = slist->header.next;
    ret = slist->slider;
  }
 return ret;
}

CircleListNode* CircleList_Current(CircleList* list)
{
  TCircleList* slist = (TCircleList*)list;
  CircleListNode* ret = NULL;
  if(slist != NULL)
  {
    ret = slist->slider;
  }
 return ret;
}

CircleListNode* CircleList_Next(CircleList* list)
{
  TCircleList* slist = (TCircleList*)list;
  CircleListNode* ret = NULL;
  if((slist != NULL) && (slist->slider != NULL))
  {
    ret = slist->slider;
    slist->slider = ret->next;
  }
 return ret;
}

二、双向链表
同循环链表一样,双向链表也是针对于单项链表有些完不成的操作而进行的改进。
其中单链表的结点都有一个指向下一个结点的指针,单链表的数据元素无法直接访问其前驱元素,如果我们需要逆序访问单链表中的元素,那么使用单链表那就是极其耗时的操作,所以我们在此引入双向链表。

双向链表的定义:在单链表的结点中增加一个指向其前驱的pre指针
双向链表同样拥有单链表的所有操作,当然,同循环链表一样,双向链表也引入了一些新操作:
获取当前游标指向的数据元素
CircleListNode* CircleList_Current(CircleList* list);
将游标重置指向链表中的第一个数据元素
CircleListNode* CircleList_Reset(CircleList* list);
将游标移动指向到链表中的下一个数据元素
CircleListNode* CircleList_Next(CircleList* list);
将游标移动指向到链表中的上一个数据元素
CircleListNode* CircleList_Pre(CircleList* list);
直接指定删除链表中的某个数据元素
CircleListNode* CircleList_DeleteNode(CircleList* list,CircleListNode* node);

每部分的具体代码如下:

#include <stdio.h>
#include <malloc.h>
#include "DLinkList.h"

typedef struct _tag_DLinkList
{
 DLinkListNode header;
 DLinkListNode* slider;
 int length;
}TDLinkList;

DLinkList* DLinkList_Create()
{
 TDLinkList* ret = (TDLinkList*)malloc(sizeof(TDLinkList));
 if(ret != NULL)
 {
  ret->length = 0;
  ret->header.next = NULL; 
  ret->header.pre = NULL;
  ret->slider = NULL;
 }
 return ret;
}

void DLinkList_Destroy(DLinkList* list)
{
   free(list);  
}

void DLinkList_Clear(DLinkList* list)
{
    TDLinkList* slist = (TDLinkList*)list;
    if(slist != NULL)
    {
     slist->length = 0;
     slist->header.next = NULL;
     slist->header.pre = NULL;
     slist->slider = NULL;   
    }
}

int DLinkList_Length(DLinkList* list)
{
    TDLinkList* slist = (TDLinkList*)list;
    int ret = -1;
    if(slist != NULL)
    {
     ret = slist->length;    
    }
    return ret;
}

int DLinkList_Insert(DLinkList* list, DLinkListNode* node, int pos)
{
   TDLinkList* slist = (TDLinkList*)list;
   int ret = (slist != NULL) && (pos >= 0) && (node != NULL);
   int i = 0;

   if(ret)
   {
    DLinkListNode* current = (DLinkListNode*)slist;
    DLinkListNode* next = NULL; 
    for(i = 0;(current->next != NULL) && (i < pos);i++)
    {
      current = current->next;
    } 
     next = current->next;

     current->next = node;
     node->next = next;
     if(next != NULL)
     {
     next->pre = node;
     }
     node->pre = current;

     if( slist->length == 0)
     {
     node->pre = NULL;
     slist->slider = node;
     }
     slist->length++;       
   }

  return ret;
}

DLinkListNode* DLinkList_Get(DLinkList* list, int pos)
{
   TDLinkList* slist = (TDLinkList*)list;
   DLinkListNode* ret = NULL;
   int i = 0;
   if((pos >= 0) && (pos <= slist->length) && (slist != NULL))
   {
    DLinkListNode* current = (DLinkListNode*)slist;
    for(i=0;i<pos;i++)
    {
     current = current->next; 
    }
      ret = current->next;
   }
   return ret;  
}

DLinkListNode* DLinkList_Delete(DLinkList* list, int pos)
{
   TDLinkList* slist = (TDLinkList*)list;
   DLinkListNode* ret = NULL;
   int i = 0;
   if((pos >= 0) && (pos <= slist->length) && (slist != NULL))
   {
    DLinkListNode* current = (DLinkListNode*)slist;
    DLinkListNode* next = NULL;
    for( i=0;i<pos;i++ )
    {
     current = current->next; 
    }
      ret = current->next;
      next = ret->next; 

      current->next = next;
      if( next != NULL )
      {
      next->pre = current;
       if( current == (DLinkListNode*)slist )
       {
        next->pre = NULL;   
       }
      }
      if( slist->slider == ret )
      {
       slist->slider = next;        
      }

      slist->length--;
   }

   return ret;  
}

DLinkListNode* DLinkList_DeleteNode(DLinkList* list,DLinkListNode* node)
{
   TDLinkList* slist = (TDLinkList*)list;
   DLinkListNode* ret = NULL;
   int i = 0;
   if(slist != NULL)
   {
    DLinkListNode* current = (DLinkListNode*)slist;
    for( i=0; i<slist->length; i++)
    {
     if(current->next == node)
     {
      ret = current->next;
      break;        
     }
      current = current->next;  
    }
    if(ret != NULL)
    {   
    DLinkList_Delete(slist,i);  
    }
   }

   return ret;  
}

DLinkListNode* DLinkList_Reset(DLinkList* list)
{
   TDLinkList* slist = (TDLinkList*)list;
   DLinkListNode* ret = NULL;
   if(slist != NULL)
   {
    slist->slider = slist->header.next;
    ret = slist->slider;    
   }    
 return ret;
}

DLinkListNode* DLinkList_Current(DLinkList* list)
{
   TDLinkList* slist = (TDLinkList*)list;
   DLinkListNode* ret = NULL;
   if(slist != NULL)
   {
    ret = slist->slider;    
   }    
 return ret;
}

DLinkListNode* DLinkList_Next(DLinkList* list)
{
   TDLinkList* slist = (TDLinkList*)list;
   DLinkListNode* ret = NULL;
   if((slist != NULL) && (slist->slider != NULL))
   {
    ret = slist->slider;
    slist->slider = ret->next;  
   }    

 return ret;
}

DLinkListNode* DLinkList_Pre(DLinkList* list)
{
   TDLinkList* slist = (TDLinkList*)list;
   DLinkListNode* ret = NULL;
   if(slist != NULL)
   {
    ret = slist->slider;
    slist->slider = ret->pre;   
   }

 return ret;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值