数据结构之循环双链表的结构和实现

  1、双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针和一个数据域(存放的是元素的值),分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。当为空表时,循环双链表只有一个头指针,并且它的前后两个指针都指向这个头指针。

#include  "stdafx.h"
#include<iostream>
using namespace std;
#include<malloc.h>

typedef int ElemType;
#define OK               1        //正确
#define ERROR            0        //失败
typedef struct DuLNode
{
    ElemType data;
    struct DuLNode *prior,*next;
}DuLNode,*DuLinkList;

//初始化链表
void InitList(DuLinkList &L)
{    /* 产生空的双向循环链表L */
    L=(DuLinkList)malloc(sizeof(DuLNode));
    if(!L)
    {
        cout<<"初始化失败"<<endl;
        return;        
    }
    L->next=L->prior=L;
}

//销毁链表
void DestroyList(DuLinkList L)
{ /* 操作结果:销毁双向循环链表L */
  DuLinkList q,p=L->next; /* p指向第一个结点 */
  while(p!=L) /* p没到表头 */
  {
    q=p->next;
    free(p);
    p=q;
  }
  free(L);
  L=NULL;
}

//清空
void ClearList(DuLinkList L) /* 不改变L */
{ /* 初始条件:L已存在。操作结果:将L重置为空表 */
  DuLinkList q,p=L->next; /* p指向第一个结点 */
  while(p!=L) /* p没到表头 */
  {
    q=p->next;
    free(p);
    p=q;
  }
  L->next=L->prior=L; /* 头结点的两个指针域均指向自身 */
}

//判断是否为空表
int ListEmpty(DuLinkList L)
{ /* 初始条件:线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */
    if(L->next==L&&L->prior==L)
        return ERROR;
    else
        return OK;
}

//获取链表长度
int ListLength(DuLinkList L)
{ /* 初始条件:L已存在。操作结果: */
    int i=0;
    DuLinkList p=L->next; /* p指向第一个结点 */
    while(p!=L) /* p没到表头 */
    {
        i++;
        p=p->next;
    }
    return i;
}

//获取第i个节点的元素值
int GetElem(DuLinkList L,int i,ElemType *e)
{ /* 当第i个元素存在时,其值赋给e并返回OK,否则返回ERROR */
    int j=1; /* j为计数器 */
    DuLinkList p=L->next; /* p指向第一个结点 */
    while(p!=L)
    {
        p=p->next;
        j++;
    }
    if(p==L||j>i) /* 第i个元素不存在 */
        return ERROR;
    *e=p->data; /* 取第i个元素 */
    return OK;
}

//获取第i个节点链表的地址
DuLinkList GetElemP(DuLinkList L,int i) /* 另加 */
{ /* 在双向链表L中返回第i个元素的地址。i为0,返回头结点的地址。若第i个元素不存在, 返回NULL */
    int j;
    DuLinkList p=L; /* p指向头结点 */
    if(i<0||i>ListLength(L)) /* i值不合法 */
        return NULL;
    for(j=1;j<=i;j++)
        p=p->next;
    return p;
}

//返回前驱
ElemType PriorElem(DuLinkList L,ElemType cur_e)
{ /* 操作结果:若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱, */
  /*           否则操作失败,pre_e无定义 */
  DuLinkList p=L->next->next; /* p指向第2个元素 */
  while(p!=L) /* p没到表头 */
  {
    if(p->data==cur_e)
    {
      return p->prior->data;
    }
    p=p->next;
  }
  return NULL;
}

//返回后继
ElemType NextElem(DuLinkList L,ElemType cur_e)
{ /* 操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继, */
  /*           否则操作失败,next_e无定义 */
  DuLinkList p=L->next->next; /* p指向第2个元素 */
  while(p!=L)                  /* p没到表头 */
  {
    if(p->prior->data==cur_e)
    {  
      return p->data;
    }
    p=p->next;
  }
 return NULL;
}


int ListInsert(DuLinkList L,int i,ElemType e)
{ /* 在带头结点的双链循环线性表L中第i个位置之前插入元素e,i的合法值为1≤i≤表长+1 */
  /* 改进算法2.18,否则无法在第表长+1个结点之前插入元素 */
    DuLinkList p,s;
    if(i<1||i>ListLength(L)+1)     /* i值不合法 */
        return ERROR;
    p=GetElemP(L,i-1);  /* 在L中确定第i个元素前驱的位置指针p */
    if(!p)                /* p=NULL,即第i个元素的前驱不存在(设头结点为第1个元素的前驱) */
        return ERROR;
    s=(DuLinkList)malloc(sizeof(DuLNode));
    if(!s)
        return OVERFLOW;
    s->data=e;
    s->prior=p;     /* 在第i-1个元素之后插入 */
    s->next=p->next;
    p->next->prior=s;
    p->next=s;
    return OK;
}

//删除
int ListDelete(DuLinkList L,int i,ElemType *e)
{ /* 删除带头结点的双链循环线性表L的第i个元素,i的合法值为1≤i≤表长 */
    DuLinkList p;
    if(i<1)                /* i值不合法 */
        return ERROR;
    p=GetElemP(L,i);    /* 在L中确定第i个元素的位置指针p */
    if(!p)                /* p=NULL,即第i个元素不存在 */
        return ERROR;
    *e=p->data;
    p->prior->next=p->next;
    p->next->prior=p->prior;
    free(p);
    return OK;
}

//输出链表
void print(DuLinkList L)
{
    if(L==NULL || L->next==L->prior)
    {
        cout<<"为空表,没有元素"<<endl;
        return;
    }
    DuLinkList p=L->next;
    while(p!=L)
    {
        cout<<"     "<<p->data;
        p=p->next;
    }
}

int main(int argc,char* argv[])
{
    DuLinkList l;
    int a,pos,e;
    InitList(l);
    cout<<"初始链表如下:";
    for(int i=1;i<=10;i++)
    {
        ListInsert(l,i,i);
    }
    print(l);
    cout<<"请输入要删除的位置:    ";
    cin>>pos;
    ListDelete(l,pos,&e);
    cout<<"删除后的链表如下:"<<endl;
    print(l);
    cout<<"当前链表的长度为:"<<ListLength(l)<<endl;
    cout<<"请输入要查找某个元素的前后元素:    ";
    cin>>pos;
    cout<<"元素"<<pos<<"的前驱元素是:"<<PriorElem(l,pos)<<"后驱元素是:"<<NextElem(l,pos)<<endl;
    print(l);
    cout<<"清空链表:"<<endl;
    ClearList(l);
    cout<<l<<endl;
    print(l);
    cout<<"销毁链表:"<<endl;
    DestroyList(l);
    print(l);
    cout<<l<<endl;
    cin>>a;
    return 0;
}

 

2、循环双链表图解:

  

3、循环双链表插入和删除代码图解:

  

  删除:

  

转载于:https://www.cnblogs.com/lbangel/p/3299042.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值