C++实现双向链表操作

双向链表是在单链表的基础上为每个结点添加一个前趋指针域prior,这样形成的链表可有两个不同的方向。

双向链表一般也可由头指针唯一确定,其每一结点均有:
数据域(data)
左链域(prior):指向前趋结点.
右链域(next):指向后继
它是一种既有前趋也有后继的对称结构,它的对称性可表述为:
p->prior->next=p->next->prior=p
即:结点*p的存储位置,既存放在其前趋结点(*p->prior)的后继指针域中;也存放在其后继结点(*p->next)的前趋指针域中。

双向链表的示意图如下:
图1
同单链表相比,双向链表的插入、删除和查找的操作都更为便利。

0.双向链表的结点类型

typedef struct DNode
{
    int data;
    DNode *prior;
    DNode *next;
}DLNode;

1.初始化双向链表

/*初始化链表,该链表含有一个为空的头结点,该节点的next指针和prior指针都指向自身*/
void ListInitiate(DLNode **head)
{
    *head=new DLNode;
    (*head)->next=*head;
    (*head)->prior=*head;
}

初始化的双向链表其结构大致如下:
图2
2.创建双向链表

/*创建含(n-m+1)个元结点的链表,每个结点数据域中的值为i(m≤i≤n)*/
void ListCreate(DLNode *head,int m,int n)
{
    DLNode *p,*q;
    p=head;
    int i;
    for(i=m;i<=n;i++)
    {
        q=new DLNode;  //新建一个结点
        q->data=i;    //为结点的数据域赋值
        q->prior=p;       //①
        q->next=p->next;  //②
        p->next->prior=q; //③
        p->next=q;        //④
        p=q;
    }
}

图3
注意代码中的①②③④语句所建立的前趋或后继的指向与图3中的①②③④箭头对应。

3.查找值为x的结点*p

/*查找数据域值为x的指针p;
该函数返回的是一个指针,该指针指向DLNode类型数据*/
DLNode *ListGet(DLNode *head,int x)
{
    DLNode *p;
    p=head->next;
    while(p!=head)
    {
        if(p->data!=x)
            p=p->next;
        else
            return(p);
    }
    return NULL;
}

4.插入新结点
在步骤3中找到的*p结点之前插入一个新结点

/*在结点*p之前插入值为x的新结点*/
void ListInsert(DLNode *p,int x)
{
    DLNode *q;
    q=new DLNode;
    q->data=x;
    p->prior->next=q;
    q->prior=p->prior;
    p->prior=q;
    q->next=p;
}

5.删除结点*p

/*删除链表中的*p结点*/
void ListDelete(DLNode *p)
{
    DLNode *q;
    p->next->prior=p->prior;
    p->prior->next=p->next;
    q=p;
    delete q;
}

6.打印链表中的元素

/*打印链表中的元素*/
void ListPrint(DLNode *head)
{
    DLNode *p;
    p=head;
    while(p->next!=head){
        p=p->next;
        cout<<p->data<<' ';
    }
    cout<<endl;
}

完整的代码如下:

#include <iostream>
using namespace std;

typedef struct DNode
{
    int data;
    DNode *prior;
    DNode *next;
}DLNode;

int main()
{
    void ListInitiate(DLNode **head);
    void ListCreate(DLNode *head,int m,int n);
    DLNode *ListGet(DLNode *head,int x);
    void ListInsert(DLNode *p,int x);
    void ListDelete(DLNode *p);
    void ListPrint(DLNode *head);

    DLNode *head,*p;
    ListInitiate(&head);
    ListCreate(head,1,10);  //创建一个链表,链表中元素值在1~10之间
    p=ListGet(head,5);     //返回元素值为5的结点(p)的地址,
    ListInsert(p,99);     //在结点p之前插入一个元素值为99的新结点
    ListDelete(p);       //删除p结点
    ListPrint(head);    //打印链表中的元素
    return 0;
}

/*初始化链表,该链表含有一个为空的头结点,该节点的next指针和prior指针都指向自身*/
void ListInitiate(DLNode **head)
{
    *head=new DLNode;
    (*head)->next=*head;
    (*head)->prior=*head;
}

/*创建含(n-m+1)个元结点的链表,每个结点数据域中的值为i(m≤i≤n)*/
void ListCreate(DLNode *head,int m,int n)
{
    DLNode *p,*q;
    p=head;
    int i;
    for(i=m;i<=n;i++)
    {
        q=new DLNode;
        q->data=i;
        q->prior=p;       //①
        q->next=p->next;  //②
        p->next->prior=q; //③
        p->next=q;        //④
        p=q;
    }
}


/*查找数据域值为x的指针p;
该函数返回的是一个指针,该指针指向DLNode类型数据*/
DLNode *ListGet(DLNode *head,int x)
{
    DLNode *p;
    p=head->next;
    while(p!=head)
    {
        if(p->data!=x)
            p=p->next;
        else
            return(p);
    }
    return NULL;
}

/*在结点*p之前插入值为x的新结点*/
void ListInsert(DLNode *p,int x)
{
    DLNode *q;
    q=new DLNode;
    q->data=x;
    p->prior->next=q;
    q->prior=p->prior;
    p->prior=q;
    q->next=p;
}

/*删除链表中的*p结点*/
void ListDelete(DLNode *p)
{
    DLNode *q;
    p->next->prior=p->prior;
    p->prior->next=p->next;
    q=p;
    delete q;
}

/*打印链表中的元素*/
void ListPrint(DLNode *head)
{
    DLNode *p;
    p=head;
    while(p->next!=head){
        p=p->next;
        cout<<p->data<<' ';
    }
    cout<<endl;
}
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值