线性表(3)

1.前言:

     在前面介绍的单链表时候,我们了解到它的指针域只包含了一个指向后继结点的指针,这会造成它无法逆向检索,因此我们引入双链表,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。

2.双链表的相关操作

2.1 建立存储结构

//存储结构
typedef struct DNode
{
    Elemtype data;
    struct DNode *prior;
    struct DNode *next;
}DNLinkNode,*DLinklist;//DLinklist等价于*DNode

2.2 初始化

      这里我们定义带头结点的双链表,那么具体的建立操作就是先建立头节点,让其后继指针指向NULL,其前继指针永远指向NULL。

//初始化
bool InitDLinkList(DLinklist & L)
{
    L=(DNode *)malloc(sizeof(DNode));//分配一个头节点
    if(L==NULL) //内存不够分配失败
        return false;
    L->prior=NULL;//头节点prior永远指向NULL
    L->next=NULL;//头节点后还没有结点
    return true;
}

2.3 插入与删除

     这两项操作是最不同于单链表的,也是相对麻烦的操作,下面先通过示意图理解其过程。

 

 了解原理后便可以在表的指定位置插入元素,代码如下:

//插入元素
bool InserSqList(DLinklist &L,int i,Elemtype e)
{
    int j=0;
    DNLinkNode *p=L,*s;
    if(i<=0) return false;
    while(j<i-1&&p!=NULL)
    {
        j++;
        p=p->next;
    }
    if(p==NULL)
     return false;
    else 
    {
        s=(DNLinkNode *)malloc(sizeof(DNLinkNode));
        s->data=e;
        s->next=p->next;
        if(p->next!=NULL)
           p->next->prior=s;
        s->prior=p;
        p->next=s;
        return true;
    }
}

 

同样的了解完删除节点原理, 我们就可以删除链表中指定位置的元素。

//删除元素
bool DeleteSqlist(DNode *& L,int i)
{
    int j;
    DNode *p=L,*q;
    if(i<0) return false;
    while (j<i-1&&p!=NULL)
    {
        j++;
        p=p->next;
    }
    if(p==NULL)
      return false;
    else
      {
        q=p->next;
        if(q==NULL)
           return false;
        p->next=q->next;
        if(q->next!=NULL)
           q->next->prior=p;
        free(q);
        return true;
      }
}

2.4 输出表

      这一操作相对就简单许多。

void display(DNode *L)
{
 DNode *p=L->next;
 while(p!=NULL)
 {
    printf("%d",p->data);
    p=p->next;
    printf("\n");
 }
}

 全部代码:

#include<stdio.h>
#include<malloc.h>
typedef int Elemtype;
//存储结构
typedef struct DNode
{
    Elemtype data;
    struct DNode *prior;
    struct DNode *next;
}DNLinkNode,*DLinklist;//DLinklist等价于*DNode
//初始化
bool InitDLinkList(DLinklist & L)
{
    L=(DNode *)malloc(sizeof(DNode));//分配一个头节点
    if(L==NULL) //内存不够分配失败
        return false;
    L->prior=NULL;//头节点prior永远指向NULL
    L->next=NULL;//头节点后还没有结点
    return true;
}
//插入元素
bool InserSqList(DLinklist &L,int i,Elemtype e)
{
    int j=0;
    DNLinkNode *p=L,*s;
    if(i<=0) return false;
    while(j<i-1&&p!=NULL)
    {
        j++;
        p=p->next;
    }
    if(p==NULL)
     return false;
    else 
    {
        s=(DNLinkNode *)malloc(sizeof(DNLinkNode));
        s->data=e;
        s->next=p->next;
        if(p->next!=NULL)
           p->next->prior=s;
        s->prior=p;
        p->next=s;
        return true;
    }
}
//删除指定位置元素
bool DeleteSqlist(DNode *& L,int i)
{
    int j;
    DNode *p=L,*q;
    if(i<0) return false;
    while (j<i-1&&p!=NULL)
    {
        j++;
        p=p->next;
    }
    if(p==NULL)
      return false;
    else
      {
        q=p->next;
        if(q==NULL)
           return false;
        p->next=q->next;
        if(q->next!=NULL)
           q->next->prior=p;
        free(q);
        return true;
      }
}
//后向便历遍历
void display(DNode *L)
{
 DNode *p=L->next;
 while(p!=NULL)
 {
    printf("%d",p->data);
    p=p->next;
    printf("\n");
 }
}
//删除结点
bool DeleteNextDNode(DNode *p)
{
    if(p==NULL) return false;
    DNode *q=p->next;//找到p的后继结点q
    if(q==NULL) return false;
    p->next=q->next;
     if(q->next!=NULL)//q结点不是最后一个结点
        q->next->prior=p;
    free(q);
    return true;
}
//销毁表
void DestoryList(DNode *&L)
{
    while (L->next!=NULL)
        DeleteNextDNode(L);
        free(L);//释放头节点
        L=NULL;//头节点指向NULL
}

int main()
{
    DLinklist L;
    InitDLinkList(L);
    InserSqList(L,1,1);
    InserSqList(L,2,3);
    InserSqList(L,3,4);
    InserSqList(L,4,5);
    display(L);
    DeleteSqlist(L,1);
    display(L);
    DestoryList(L);
    return 0;
}

 结果如图:

不足之处还请多多指教。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值