循环链表实现约瑟夫环

循环链表实现约瑟夫环

首先我们先上图帮助理解:(环状顺序队列)
环状顺序队列示意图

top为队首指针
rear为队尾指针

  1. 我们需要注意,顺序队列在判断数组中数据是否存满时,会出现下面情况:
  • 当队列里面啥也没有的时候,队列的头指针等于队列的尾指针(top==rear);
  • 而队列里面没有多余空间存储数据的时候,队列的头指针也等于队列的尾指针(top==rear);
  1. 由上我们发现:
  • 顺序队列的存储状态不同,但是判断条件相同(top==rear)。
  1. 我们为了区分二者,最简单的解决办法是:牺牲掉数组中的一个存储空间

  2. 判断数组满员的条件是:尾指针的下一个位置和头指针相遇,就说明数组满了(top==(rear+1))

  3. 循环队列的操作(i. size为顺序队列申请的空间大小 ii.Q[ ]为数据集合)

  • 入队(移动尾指针rear
    • rear=(rear+1)%size
    • Q[rear]=入队元素
    • ❗注意:队满时不可入队top=(rear+1)%size
  • 出队(移动队首指针top
    • top=(top+1)%size
    • Q[top]=出队元素
    • ❗注意:队空不可出队top==rear
  1. 经上分析,我们可以发现队列为空时跳出循环
    实现:
#include<stdio.h>
#include<stdlib.h>

void JosephusRing(int *Q,int n,int s){
	//为了不影响主方法中所创建的队列,所以令声明两个指向元素并初始化
    int top=0,rear=n;
    int i;
    while(top-rear){
        for(i=0;i<s-1;i++){
        	//(n+1)--因为填充数值是从 1 开始,所以指向元素移动时,队尾指向元素的下一个指向为队首元素的指向,即实际存储空间大小为 n+1
            top=(top+1)%(n+1);
            rear=(rear+1)%(n+1);
            Q[rear]=Q[top];
        }
        top=(top+1)%(n+1);
        printf("%3d",Q[top]);
    }
}

int main(void){
    int *Q;
    int n,s;
    //输入存储个数
    printf("please input a num:\n");
    scanf("%d",&n);
    //输入出队元素(第几个)
    printf("please input s:\n");
    scanf("%d",&s);
    //申请存储空间
    Q=(int *)malloc((n+1)*sizeof(int));
    //为了方便我们填充数值为1到n
    for(int i=1;i<n+1;i++)	Q[i]=i;
    //调用方法
    JosephusRing(Q,n,s);
}

输出结果展示:
运行结果

  1. 由于上述代码实现的时间复杂度为O(n2)
    为了降低时间复杂度,我们可以引入一个计数器cnt
//降低时间复杂度
#include<stdio.h>
#include<stdlib.h>

void JosephusRing(int *Q,int n,int s){
    int top=0,rear=n;
    int cnt=1;
    while(top-rear){
        if(cnt-s){
            top=(top+1)%(n+1);
            rear=(rear+1)%(n+1);
            Q[rear]=Q[top];
            cnt++;
        }else{
        	top=(top+1)%(n+1);
        	printf("%3d",Q[top]);
        	cnt=1;
        }
    }
}

int main(void){
    int *Q;
    int n,s;
    printf("please input a num:\n");
    scanf("%d",&n);
    printf("please input s:\n");
    scanf("%d",&s);
    Q=(int *)malloc((n+1)*sizeof(int));
    for(int i=1;i<n+1;i++)	Q[i]=i;
    JosephusRing(Q,n,s);
}

运行结果同上!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值