约瑟夫问题(三种方法)

首先是循环链表法(运行出错!暂时未找到具体原因!跳过)

#include <iostream>
 
using namespace std;
struct node {
    int data;
    struct node* next;
};
int main() {
    int n, m, count, j = 1;
    int answer[100];
    struct node* head, * tail, * p, * q;
    head = (struct node*)malloc(sizeof(struct node*));
    head->next = NULL;
    while (1) {
        cout << "输入n和m!\n";
        cin >> n; cin >> m;
        if (n == 0 || m == 0)
        {
            free(head);
            break;
        }
 
        else {
            tail = head;//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            for (int i = 0; i < n; i++) {  //尾插法!
                //q = tail;
                p = (struct node*)malloc(sizeof(struct node*));
                p->data = i + 1;
                tail->next = p;
                p->next = head->next;//切记不要忘记该步骤!形成循环链表!
                                     //将p.next也就是最后一个node的next指向head的next结点也就是head的下一个结点也就是头结点!
                tail = p;//将tail定为最后一个!
            }
            q = tail;//注意是tail而不是head!!因为head没有数据,是头结点!而不是存储数据的首结点!
            p = head->next;
            count = 1;
            while (p != q) {
                if (count == m) {
                    q->next = p->next;
                    free(p);
                    p = q->next;//!注意别忘记了!
                    count = 1;//!注意别忘记了!
                }
                else {
                    q = p;
                    p = p->next;
                    count++;
                }
            }
            //head->next = q;//此处是保留循环链表!若不需要可删去!
            answer[j] = p->data;
            j++;
            free(p);
            head->next = NULL;
        }
 
    }
 
    for (int c = 0; c <= j; c++) {
        cout << "大王为: " << answer[c] << endl;
    }
 
    return 0;
}

第二是数组标志位法(运行无问题):

#include <iostream>
using namespace std;
int main() {
	int array[301];
	int pos;
	int n, m, p;
	cout << "请输入n和m(当输入n=0,m=0时退出程序):";
	cin >> n; cin >> m;
	while (1) {
		if (n == 0 || m == 0) {
			cout << "END!\n";
			break;
		}
		else {
			for (int i = 0; i < n; i++) {
				array[i] = i + 1;
			}
			p = n;//p计数!记剩余的非0元素数!当p等于1时说明猴子大王选出来了!
			pos = 0;//pos保证array数组按顺序循环下去!
			int count = 1;//count计数!记是否到达该置0的数组元素处!
			while (p > 1) {
				if (array[pos] > 0) {
					if (count != m) {
						count++;
						pos = (pos + 1) % n;//pos保证array数组按顺序循环下去!
					}
					else {
						array[pos] = 0;
						count = 1;	
						p--;
						pos = (pos + 1) % n;
					}
				}
				else {
					pos = (pos + 1) % n;
				}
			}
			for (int j = 0; j < n; j++) {
				if (array[j] != 0)
					cout << "猴子大王为:" << array[j] << endl;
			}
		}
		cout << "请输入n和m(当输入n=0,m=0时退出程序):";
		cin >> n; cin >> m;
	}
	return 0;
}

用数组模拟循环链表的方法:

#include <iostream>
using namespace std;
int main() {
	int array[301];
	//int pos;
	int n, m, number, i;
	cout << "请输入n和m(当输入n=0,m=0时退出程序):";
	cin >> n; cin >> m;
	while (1) {
		if (n == 0 || m == 0) {
			cout << "END!\n";
			break;
		}
		else {
			for (i = 0; i < n; i++) {
				array[i] = i + 1;
			}
			array[i] = 0;//形成循环!!!

			number = n;//p计数!记剩余的非0元素数!当p等于1时说明猴子大王选出来了!
			int count = 1;//count计数!记是否到达该置0的数组元素处!
			int pos = 0;
			int prior = n - 1;

			while (number > 1) {
				if (count != m) {
					count++;
					prior = pos;
					pos = array[prior];
				}
				else {
					array[prior] = array[pos];
					array[pos] = -1;
					pos = array[prior];
					count = 1;
					number--;
				}
			}

			cout << "猴子大王为:" << array[pos] + 1 << endl;
		}

		cout << "请输入n和m(当输入n=0,m=0时退出程序):";
		cin >> n; cin >> m;
	}
	return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值