数据结构之循环链表

循环链表概述

循环链表是单链表的另一种形式,它是一个首尾相接的链表。它的特点是表中最后一个节点的指针域由NULL改为指向头结点或者线性表的第一个节点,整个链表形成一个环,就得到了单链形式的循环链表。因此,再循环链表中,从表的任意一个节点出发均可找到表中的其他节点。

头结点形式为下图

 如下图所有节点都被连接到一个环上

循环链表和单链表的主要差异就在于循环的条件判断上,原来是 p->next == NULL,现在是 p->next != 头结点 ,则循环未结束。 
如果用头指针表示循环链表,则需 O(n) 时间找到最后一个结点。若改用尾指针表示循环链表,此时查找开始结点和终端结点都很方便了。(这是由循环链表的特点决定的)如图: 


 
此时若尾指针用rear指示,则查找终端结点时间是O(1),而开始结点,其实就是 rear->next->next ,其时间复杂也为O(1)。

合并两个链表

 合并后

循环链表的实现
 

CList.h     

typedef struct CNode
{
    int data;
    struct CNode *next;
}CNode,*CList;
 
void InitList(CList plist);  //初始化
 
bool Insert_head(CList plist,int val);  //头插法
 
bool Insert_tail(CList plist,int val);  //尾插法
 
CNode *Search_pri(CList plist,int key);  //查找前驱
 
bool Delete(CList plist,int key);  //删除
 
bool IsEmpty(CList plist);   //是否为空
 
void Destroy(CList plist);   //摧毁
 
int GetLength(CList plist); //得到长度
 
void Show(CList plist);    //显示函数


CList.cpp     

#include "CList.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
 
void InitList(CList plist)//初始化 
{
    assert(plist != NULL);
    plist->next = plist;  // 与单链表不同 ,初始化时使头节点的next指针域指向头节点本身
}
 
static CNode*GetNode(int val)
{
    CNode *pGet = (CNode*)malloc(sizeof(CNode));
    assert(pGet != NULL);
    pGet->data = val;
    pGet->next = NULL;
    return pGet;
}
 
bool Insert_head(CList plist,int val)  //头插法
{
    assert(plist != NULL);
    CNode *pGet = GetNode(val);
    pGet->next = plist->next;
    plist->next = pGet;
    return true;
}
 
 
bool Insert_tail(CList plist,int val)  //尾插法
{
    assert(plist != NULL);
    CNode *pGet = GetNode(val);
    CNode *p = plist;
    while (p->next != plist)  // 与单链表不同,循环条件发生变化
    {
        p = p->next;
    }
    p->next = pGet;
    pGet->next = plist;  // 与单链表不同,pGet->next = NULL  改为 pGet->next = plist
    return true;
}
 
 
CNode *Search_pri(CList plist,int key)  //查找前驱
{
    assert(plist != NULL);
    CNode *p = plist;
    while (p->next != plist)   // 与单链表不同,循环条件发生变化
    {
        if (p->next->data == key)
        {
            return p;
        }
        p = p->next;
    }
    return NULL;
}
 
 
bool Delete(CList plist,int key)  //删除
{
    assert(plist != NULL);
    CNode *p = Search_pri(plist,key);
    if (p == NULL)
    {
        return false;
    }
    CNode *pDel = p->next;
    p->next = pDel->next;
    free(pDel);
    pDel = NULL;
    return true;
}
 
bool IsEmpty(CList plist) //是否为空
{
    return plist->next == plist;   // 与单链表不同,判断条件发生变化
}
 
 
void Destroy(CList plist) //摧毁
{
    CNode *pDel = NULL;
    while (plist->next != plist)   // 与单链表不同,循环条件发生变化
    {
        pDel = plist->next;
        plist->next = pDel->next;
        free(pDel);
    }
    pDel = NULL;
}
 
 
int GetLength(CList plist)  //得到长度
{
    int len = 0;
    CNode *p = plist->next;
    while (p != plist)    // 与单链表不同,循环条件发生变化
    {
        len++;
        p = p->next;
    }
    return len;
}
 
 
void Show(CList plist)  //显示函数
{
    CNode *p = plist->next;
    while (p != plist)    // 与单链表不同,循环条件发生变化
    {
        printf("%d ",p->data);
        p = p->next;
    }
    printf("\n");
}


test.cpp

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<vld.h>
#include"Clist.h"
 
int main()
{
    CNode head;//头结点
    InitList(&head);
    for(int i = 0; i < 10;i++)
    {
        Insert_tail(&head,i);
    }
    Insert_head(&head,-1);
    Insert_head(&head,-2);
    Show(&head);
    CNode *p = Search_pri(&head,3);
    printf("%d\n",p->data);
    printf("len == %d\n",GetLength(&head));
 
    Delete(&head,9);
    Show(&head);
    printf("len == %d\n",GetLength(&head));
    Destroy(&head);
    return 0;
}

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值