数据结构(循环链表)

数据结构(循环链表)

循环单链表和循环双链表的结点类型,与非循环单链表,非循环双链表一致。

单链表改为循环单链表的过程是将它尾结点的next指针域由原来的空NULL改为指向头结点L
双链表改为循环双链表示将尾结点的next指针域由原来的空NULL改为指向头结点L,同时将头结点的prior指针域改为指向尾结点。
故,循环链表的基本运算的实现算法与对应非循环链表的算法基本相同,差别在于判断表尾结点p的条件变为p->next==L,另外循环双链表可以通过L->prior快速找到尾结点。
以下是书本的体验代码

//
// Created by Snow on 2023/3/6.
//
//循环链表
#include<cstdio>
#include<cstdlib>
typedef int ElemType;
typedef struct LNode
{
    ElemType data;//存放元素值
    struct LNode *next;//指向后继节点
}LinkNode;//单链表结构类型
typedef struct DNode
{
    ElemType data;
    struct DNode *prior;
    struct DNode *next;
}DLinkNode;
//尾插法建立单链表(顺序)
void CreatListR(LinkNode *&L,ElemType arr[],int n)
{
    LinkNode *s,*r;
    L=(LinkNode *)malloc(sizeof(LinkNode));//创建头结点
    r=L;//r始终指向尾结点,初始时指向头结点
    for(int i=0;i<n;i++)//循环建立数据节点
    {
        s=(LinkNode *)malloc(sizeof(LinkNode));
        s->data=arr[i];//创建数据节点s
        r->next=s;//将节点s插入节点r之后
        r=s;
    }
    r->next=L;//将尾结点的指针域置为NULL
}
//尾插法建立双链表
bool CreatListR(DLinkNode *&L,ElemType arr[],int n)
{
    DLinkNode *s,*r;
    L=(DLinkNode *)malloc(sizeof(DLinkNode));
    r=L;
    for(int i=0;i<n;i++)
    {
        s=(DLinkNode *)malloc(sizeof(DLinkNode));
        s->data=arr[i];
        r->next=s;
        s->prior=r;
        r=s;
    }
    r->next=L;
    L->prior=r;
    return true;
}
//统计data域值为x的结点个数
int count(LinkNode *L,ElemType x)
{
    int cnt=0;
    LinkNode *p=L->next;
    while(p!=L)
    {
        if(p->data==x)cnt++;
        p=p->next;
    }
    return cnt;
}
//删除双链表中第一个data域值为x的结点
bool DelElem(DLinkNode *&L,ElemType x)
{
    DLinkNode *p=L->next;
    while(p!=L&&p->data!=x)
        p=p->next;
    if(p!=L)
    {
        p->next->prior=p->prior;
        p->prior->next=p->next;
        free(p);
        return true;
    }
    else return false;
}
//查看循环双链表中的数据结点是否对称
bool Symm(DLinkNode *L)
{
    bool same=true;
    DLinkNode *p=L->next;
    DLinkNode *q=L->prior;
    while(same)
    {
        if(p->data!=q->data)
            same=false;
        else
        {
            if(p==q||p==q->prior)break;
            p=p->next;
            q=q->prior;
        }
    }
    return same;
}
//销毁线性表
void DestroyList(LinkNode *&L)
{
    LinkNode *pre=L,*p=L->next;//pre指向结点p的前驱结点
    while(p!=L)//遍历单链表L
    {
        free(pre);//释放pre结点
        pre=p;//pre,p同步后移一个结点
        p=p->next;
    }
    free(pre);//循环结束时p为NULL,pre指向尾结点,释放他
}
bool DestroyList(DLinkNode *&L)
{
    DLinkNode *pre=L,*p=L->next;
    while(p!=L)
    {
        free(pre);
        pre=p;
        p=p->next;
    }
    free(pre);
    return true;
}
//输出线性表
void DispList(LinkNode *L)
{
    LinkNode *p=L->next;//p指向首结点
    while(p!=L)//p不为NULL,输出p结点的data域
    {
        printf("%d ",p->data);
        p=p->next;//p移动下一个结点
    }
    printf("\n");
}
bool DispList(DLinkNode *L)
{
    if(L==NULL)return false;
    DLinkNode *p=L->next;
    while(p!=L)
    {
        printf("%d ",p->data);
        p=p->next;
    }
    printf("\n");
    return true;
}
int main()
{
    LinkNode *L1;
    DLinkNode *L2;
    ElemType arr[]={1,2,3,3,2,1};
    CreatListR(L1,arr,6);
    DispList(L1);
    printf("%d\n", count(L1,2));
    DestroyList(L1);
    CreatListR(L2,arr,6);
    DispList(L2);
    if(Symm(L2))printf("yes\n");
    DelElem(L2,2);
    DispList(L2);
    return 0;
}
posted @ 2023-03-06 13:12  SnowDreamXUE  阅读(18)  评论(0编辑  收藏  举报  来源