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

来源:互联网 发布:可信金融软件 编辑:程序博客网 时间:2024/05/17 21:52

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;}
0 0
原创粉丝点击