创建一个不带头结点的循环单链表并进行相关操作

        所谓循环链表就是最后一个节点的指针域不是指向空,而是指向第一个节点,这样就实现了循环。

        下面是c语言代码实现

LinkList create_linklist()
{
    int len; //用来存储节点的个数
    int i; //for循环中的循环变量
    int val; //用来存放节点的值域

    LinkList Ll = NULL; //Ll用来存储指向第一个节点的指针
    LinkList pre = NULL; //pre用来存储指向LNew指向节点的前驱节点的指针,初始指向第一个节点

    //请求用户输入节点个数
    printf("请输入节点的个数:\n");
    scanf("%d", &len);

    for (i = 0; i < len; i++)
    {
        //每循环一次生成一个新的节点
        LinkList LNew = (LinkList)malloc(sizeof(LNode));

        //判断是否分配成功
        if(!LNew)
        {
            printf("动态内存分配失败,程序退出!\n");
            exit(-1);
        }

        //请求用户输入新节点的值
        printf("请输入第%d个节点的值\n", i+1);
        scanf("%d", &val);

        //i = 0时,即循环第一次运行时(生成第一个节点时)
        if(0 == i)
        {
            //将指向第一个节点的指针保存在Ll中,便于后续操作
            Ll = LNew;

            //初始化pre,使其指向第一个节点
            pre = Ll;
        }

        //将用户输入的值存储到数据域
        LNew->data = val;

        //将原来的节点挂在新生成的节点上
        pre->pNext = LNew;

        //新节点变成当前的最后一个节点,需要将其指针域指向第一个节点,从而形成循环单链表
        LNew->pNext = Ll;
        
        //pre后移,使其始终指向LNew指向节点的前驱节点,便于进行将LNew指向节点的前驱节点(原来的节点)挂在LNew指向的节点(新生成的节点)上的操作
        pre = LNew;
    }

    //提示用户链表创建成功
    printf("链表创建成功!\n");

    //返回指向第一个节点的指针
    return Ll;   
}

接下来是求链表长度的操作

int length_list(LinkList Ll)
{   
    int len = 1; //用来存储链表长度,初始值为1
    LinkList p = Ll;

    //如果指向第一个节点的指针为空,链表长度为0
    if(!Ll)
        return 0;

    //如果p->pNext不指向第一个节点,表示p不是最后一个节点,则p后移一位,直到p->pNext指向第一个节点为止
    while(p->pNext != Ll)
    {
        //长度加一
        len++;

        //p后移一位
        p = p->pNext;
    }

    //返回链表长度
    return len;
}

 下面是遍历输出的操作

//不含头结点的循环单链表的遍历输出
void show_linklist(LinkList Ll)
{
    LinkList p = Ll;

    if(!Ll)
        return;

    while(true)
    {
        printf("%d ", p->data);

        p = p->pNext;

        if(p == Ll)
            break;
    }

    printf("\n");

    return;
}

最后是删除操作(其中删除第一个节点比较特别)

void delete_node(LinkList * Ll, int pos) //Ll是指向第一个节点的指针的指针,pos是要删除节点的位置,最小值为1,最大值为链表长度
{
    int i; //for中的循环变量
    LinkList p = * Ll;  //定义一个始终指向要删除节点的前驱节点的指针,初始指向第一个节点

    //判断链表是否为空
    if(!length_list(* Ll))
    {
        //提示用户链表为空
        printf("链表为空,无法删除!\n");

        //结束函数
        return;
    }

    //判断pos是否可执行
    if(pos < 1 || pos > length_list(* Ll))
    {
        //提示用户pos输入有误
        printf("删除位置过小或过大,无法删除\n");

        //结束函数
        return;
    }

    //如果删除的是第一个节点
    if(1 == pos)
    {
        //先通过for循环找到指向最后一个节点的指针(因为是循环链表,这里的最后一个节点,相当于第一个节点的前驱节点)
        for (i = 0; i < length_list(* Ll) - 1; i++)
        {
            p = p->pNext;
        }

        // 第一个节点的前驱节点挂在第一个节点的后驱节点上
        p->pNext = (* Ll)->pNext;

        //释放为一个节点分配的空间
        free(* Ll);

        //原来的第二个节点成为新的第一个节点(这一步是传值操作,这样以后才能找到这个链表)
        (* Ll) = p->pNext;

        //结束函数
        return;
    }

    //如果不是删除第一个节点,就要找到指向要删除节点的前驱节点的指针
    for(i = 1; i<pos-1; i++)
    {
        p = p->pNext;//p后移一位
    }

    //定义一个指向要删除节点的指针
    LinkList q = p->pNext;

    //将要删除节点的前驱节点挂在,要删除节点的后驱节点上
    p->pNext = q->pNext;

    //释放为要删除节点分配的空间
    free(q);
    q = NULL;

    //提示用户删除成功
    printf("删除成功!\n");

    //结束函数
    return;
}

  • 7
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值