2037:【例5.4】约瑟夫问题C语言数组+链表解法

【题目描述】

N个人围成一圈,从第一个人开始报数,数到M的人出圈;再由下一个人开始报数,数到M

的人出圈;…输出依次出圈的人的编号。

输入NM。

输出一行,依次出圈的人的编号。

【输入样例】

8 5

【输出样例】
5 2 8 7 1 4 6 3

【数据范围】

对于所有数据,2≤N,M≤1000

数组解法

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
	int n,m,i,j=0,l=0,a[1020];
	//l为当前位置
    //开始从第一位数,所以我们要规定l=0
	scanf("%d%d",&n,&m);
	a[0]=1;
	for(i=1;i<=n;i++)//先给生命值
	{
		a[i]=1;
	}
	for(i=1;i<=n;i++)
	{	
		j=m;//用个变量j来数就不会改变m的值
		while(j>0)
		{
			
			if(a[l+1]==0&&l<n)
            //检测下一位数字,判断是否要j--
			{
				l++;
			}
			else if(a[l+1]==1&&l<n)
			{
				
				l++;
				j--;
			}
			else if(l==n&&a[1]==1)
                //末尾的下一位是首位
			{
				l=1;//归位
				j--;
			}
			else if(l==n&&a[1]==0)
			{
				l=1;//归位
				
			}
			
		}
		a[l]=0;
		//消去生命值
		printf("%d ",l);
	}
	
	return 0;
}

也可以试试数组向前覆盖来删除某一元素的方式来写。

单向循环链表解法

注意==与=的区别

函数想要修改一级指针,要不返回一级指针,要不形参用二级指针。

下面代码自己改改输出就行了

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

typedef struct LN {
    int data;
    struct LN* next;//指针域
}LN;
LN* createNode();
void deleteNode(LN** m);
LN* initLN() {
    LN* head = (LN*)malloc(sizeof(LN));//创建一个头结点
    if (head == NULL) {
        printf("内存分配失败,寄!");
        return NULL;
    }
    else {
        head->data = 0;
        head->next = head;
    }
    return head;
}
int insert_behind(LN** m) {//尾插
    //用二级指针修改函数外的一级指针
    if ((*m)->next == *m) {//如果只有头结点
        LN* node = createNode();
        (*m)->next = node;//头指针指向第一个结点
        node->next = node;//第一个结点指向自己
        node->data = ((*m)->data) + 1;
        return 0;
    }
    LN* current = (*m)->next;//当前指针
    do {//遍历到最后一个元素
        current = current->next;
    } while (current->next != (*m)->next);
    LN* node = createNode();
    node->next = (*m)->next;//指向第一个节点
    node->data = (current->data) + 1;
    current->next = node;
    return 0;
}
LN* createNode() {
    LN* node = (LN*)malloc(sizeof(LN));
    if (node != NULL) {
        return node;
    }
    else {
        printf("结点创建失败\n");
        return NULL;
    }
}
void deleteNode(LN** m) {
    printf("%d ", (*m)->data);
    LN* n = *m;
    while (n->next != (*m)) {
        n = n->next;//n的下一个节点为m
    }
    n->next = (*m)->next;
    n = (*m);
    (*m) = (*m)->next;//当前指针要指向删掉结点的下一个结点
    free(n);
    
}


int main() {
    int n, m;
    printf("请输入依次输入人数n,数到第m个人: ");
    scanf("%d %d", &n,&m);
    LN* head = initLN();
    for (int i = 0; i < n; i++) {
        insert_behind(&head);
    }
    LN* current = head->next;//当前指针
    while (n) {
        for (int i = 0; i < m - 1; i++) {
            current = current->next;
        }
        deleteNode(&current);
        n--;
    }
    
    printf("\n");
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值