数据结构——循环单链表和双向链表

1.循环单链表

1.循环单链表特点:
链表中最后一个结点的指针域不再是结束标志,而是指向整个链表的第一个结点,从而使链表形成一个环。和单链表相同,循环单链表也有带头结点和不带头结点两种。带头结点的循环单链表实现插入和删除操作较为方便,且更加适用。

2. 单链表与循环单链表比较:
循环单链表可以从尾到头,而单链表不能从尾到头。因此处理的数据序列具有环形结构特点时,适合采用循环单链表。

3. 带头结点的循环单链表和带头结点的单链表比较:
①在初始化函数中,把语句( * head)->next=NULL改为( * head)->next=* head,即形成一个环
②在其他函数中,循环判断条件p->next!=NULL和p->next->next!=NULL中的NULL改成头指针head。


2.双向链表

  1. 双向链表特点:
    每个节点除了有后继指针域还有一个前驱指针域。

  2. 双向链表的分类:
    双向链表有:带头结点和不带头结点的双向链表(但是带头结点的双向链表更为常用)。也有循环和非循环之分,循环结构的双向链表更为常用。因此下面讨论的是带头结点的循环双链表

  3. 双向循环链表结点的结构体定义

    typedef struct Node
    {
        DataType data;
        struct Node *next;
        struct Node *prior;
    }DLNode;

    data域、next域、prior域。其中data域是数据域,next域为指向后继结点的指针域,prior域为指向前驱结点的指针域。

  4. 双向链表的优点:
    在单链中查找当前结点的后继结点并不困难,可以通过当前结点的next指针进行,但要查找当前结点的前驱结点,就要从头指针head开始重新进行。对于一个要频繁进行当前结点的后继结点和前驱结点的应用来说,使用双向链表很有效。


3.双向循环链表的实现

在双向链表中,有如下指针关系:设指针p指向双向循环链表中的第i个位置,则p->next指向i+1个结点。p->next->prior仍指向第i个结点,即p->next->prior==p;同样p->prior指向第i-1个结点,p->prior->next仍指向第i个结点,即p->prior->next==p;双向循环链表关系算法可以方便算法设计。

  1. 初始化

    void ListInitiate(DLNode **head)
    {
        *head=(DLNode *)malloc(sizeof(SLNode));
        (*head)->prior=*head;     //构成前驱指针循环链表
        (*head)->next=*head;      //构成后继指针循环链表
    }
  2. 插入数据元素

    int ListInsert(DLNode *head,int i,DataType x)//在带头结点的双向循环链表head的第i个结点前,插入一个存放       //数据元素x的结点,插入成功返回1,失败返回0
    {
        DLNode *p,*q
        int j;
        p=head->next;
        j=0;
        while(p!=head&&j<i)
        {
            p=p->next;
            j++;
        }
    
        if(j!=i)
        {
            printf("参数i错误!");
            return 0;
        }
    
        s=(DLNode*)malloc(sizeof(SLNode));
        s->data=x;
        s->prior=p->prior;    //新结点指向前一个结点(中——>前)
        p->prior->next=s;     //新结点结点指向前一个结点(前->中)
        s->next=p;           //新节点指向后结点    (中->后)
        p->prior=s;          //后结点指向新节点    (后->中)
        return 1;
    }

    和单链表相比,双向循环链表的插入算法指针p可以直接指在第i个结点上,而不需要让指针p指在i-1上

  3. 删除数据元素

    int ListInitiate(DLNode *headint i,DataType *x)
    {
        DlNode *p;
        int j;
        p=head->next;
        j=0
    }
    if(j!=i)
    {
        printf("删除数据元素为值参数出错!");
        return 0;
    }
    
    *x=p->data;
    p->prior->next=p->next;
    p->next-prior=p->prior;
    free(p);
    return 1;
  4. 求当前数据元素个数ListLength(DLNode *head)

    int ListLength(SLNode *head)
    {
        DLNode *p=head;
        int size=0;
        while(p->next!=NULL)
        {
            p=p->next;
            size++;
        }
        return szie;
    }
  5. 撤销内存空间Destroy(DLNode **head)

    void Destory(DLNode **head)
    {
        DLNode *p,*q;
        int i,n=ListLength(*head);
        p=*head;
        for(i=0;i<=n;i++)
        {
            q=p;
            p=p->next;
            free(p);
        }
        *head=NULL;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值