C代码实现:操作循环链表按规则移除结点

 一组顺序数字 1~10,依123 123 循环数数,每遇到3的位置移除该位置数,重新123继续数;

 直至剩余一个数,问该数是多少?

 

 同事提起的一个问题,思考之后使用C语言实现了下,代码如下:

 

#include <stdlib.h>
#include <stdio.h>

//定义一个数据结构 用于创建链表的结点
typedef struct list{
    int num;            //结点值
    struct list * next; //结点指向下一个结点的指针
}List;

//*创建循环链表 接收链表长度 返回头结点指针
List * create(int n){
    List * head;    //头结点 指针
    List * p1;      //当前结点的前一结点 指针
    List * p2;      //当前结点 指针
    
    int i;          //变量i 用于指示循环;同时也用作后续结点的num值(便于理解)
    
    //为头结点 动态分配其数据类型大的空间 返回指针 赋值给head指针;出错则打印error
    if ((head = (List *)malloc(sizeof(List))) == NULL) {
        printf("Error");
        return NULL;
    }
    
    //为头结点赋值:将头结点的next指针置空,num设置为链表长度
    head->next = NULL;
    head->num = n;
    
    //循环添加头结点之后的后续结点
    for (i= 1; i < n + 1; i++) {
        //动态分配结点 赋值给临时变量 指针p
        List * p=(List *)malloc(sizeof(List));
        
        //p num字段赋值为i的值(对应一个数字)
        p->num = i;
        
        if (head->next == NULL) {
            //将后续结点连入链表头结点(只连入一次)
            head->next = p;
            
            p1 = head;  //更新当前结点的前一结点 指针
            p2 = p;     //更新当前结点 指针
        }else{
            p1 = p2;    //更新当前结点的前一结点 指针
            p2->next = p;   //将新创建结点 连入链表
            p2 = p;     //更新当前结点 指针
        }
    }
    
    p2->next = head->next;//将链表 首尾链接 形成循环
    
    //返回头结点指针
    return head;
}

//*操作循环链表 将对应数数3的位置结点跳过 重新数数 直至链表剩余一个结点 返回该结点指针
//*接收参数:链表头结点指针 链表长度
List * lastOne(List * table,int lenth){
    //判断链表是否为空
    if (table->next == NULL) {
        return NULL;
    }
    
    //判断链表是否只有一个结点 若只有一个结点 返回其指针即可
    if (table->next->next == NULL) {
        return table->next;
    }
    
    List * beforEnd = table;    //当前结点的前一结点指针
    List * end = table->next;   //当前结点指针
    
    int i = 0;      //变量 表示1-3循环
    int count = 0;  //循环条件:长度为length的链表 最多只需要循环遍历处理length-1次 最后保留1个数
    while (count < lenth - 1) {
        i++;//表示位置 从1开始
        if (i%3 == 0) {
            //位置数数至3 则对应位置的结点需要移除 用p表示
            List * p = end;
            printf("对应下标3的位置:需要移除的数是%d\n",p->num);
            
            //链表重新连接
            beforEnd->next = end->next;
            
            //更新当前结点指针(当前结点的前一结点指针不变)
            end = end->next;
            
            //释放移除的结点内存
            if (p != NULL) {
                free(p);
                count ++;//处理次数 用作循环条件
            }
            i = 0;//位置标识置0
        }else{
            //继续遍历
            printf("对应下标%d的位置:数字=%d\n",i,end->num);
            beforEnd = end; //更新当前结点的前一结点指针
            end = end->next;//更新当前结点指针
        }
    }
    printf("最后剩余的数字=%d\n",end->num);
    //返回最终剩余的一个结点
    return end;
}

int main() {
    //定义链表长度
    int num = 10;
    
    //创建循环链表 返回链表头结点
    List * start = create(num);
    
    //测试 循环打印链表 我们可以打印2*num次
    List * p = start->next;
    int i =0;
    while (p && i<(num*2)) {
        printf("%d\n",p->num);
        p = p->next;
        i++;
    }
    
    //操作循环链表
    List * point = lastOne(start,num);
    
    //释放最终链表中剩余的一个结点
    if (point != NULL) {
        free(point);
    }
    
    //释放链表头结点
    if (start != NULL) {
        free(start);
    }
    
    return 0;
}

 

 

C语言的部分也不太熟悉了,代码实现不是很简洁,希望和大家交流,学习更简洁易懂的处理;

log如下:

 

./linkedlist 
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
对应下标1的位置:数字=1
对应下标2的位置:数字=2
对应下标3的位置:需要移除的数是3
对应下标1的位置:数字=4
对应下标2的位置:数字=5
对应下标3的位置:需要移除的数是6
对应下标1的位置:数字=7
对应下标2的位置:数字=8
对应下标3的位置:需要移除的数是9
对应下标1的位置:数字=10
对应下标2的位置:数字=1
对应下标3的位置:需要移除的数是2
对应下标1的位置:数字=4
对应下标2的位置:数字=5
对应下标3的位置:需要移除的数是7
对应下标1的位置:数字=8
对应下标2的位置:数字=10
对应下标3的位置:需要移除的数是1
对应下标1的位置:数字=4
对应下标2的位置:数字=5
对应下标3的位置:需要移除的数是8
对应下标1的位置:数字=10
对应下标2的位置:数字=4
对应下标3的位置:需要移除的数是5
对应下标1的位置:数字=10
对应下标2的位置:数字=4
对应下标3的位置:需要移除的数是10
最后剩余的数字=4

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值