// Josephus问题变形.cpp :有N张纸牌,记为1,2,…,N。将它们牌面朝下垂直叠放在一起,应该怎样排放,才能使:从上面抽出的第一张牌是1,然后把该牌后面的两张牌依次插入牌叠的末尾,抽出面上一张,刚好是2;再依次把该牌后面的三张牌依次插入牌叠的末尾,抽出面上一张,刚好是3;如此继续下去直至抽到最后一张是N。
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//建立尾指针表示的单循环链表
typedef int DataType;
struct Node
{
DataType data;
struct Node *next;
bool flag;//访问标签,访问过了设0
};
typedef struct Node *PNode;
typedef struct Node *ClinkList;
//打印链表
void printLinkList(ClinkList llist,int n)
{
PNode p;
if (llist == NULL)
printf("\n The Linklist is NULL !\n");
p = llist->next;
int count=0;
while (count<n)
{
printf("%d ", p->data);
p = p->next;
count++;
}
printf("\n");
}
//JosephusCard算法
ClinkList JosephusCard(int n,int s,int k[])//总牌数n,从s开始,//k[]是预先设定好的含n个元素(1-n)数组
{
Node *current,*prev,*head;//*current为每次建立的结点,放入一个数据创建一个;pre相当于尾插法里的尾指针;*head为头结点
head=(Node*)malloc(sizeof(Node));//头指针指向头结点
prev=head;//初始prev指向头结点
for(int i=1;i<=n;i++)//尾插法建立单循环,prev指向最后那个结点
{
current=(Node*)malloc(sizeof(Node));
current->data=-1;//初始结点数据都设为-1
current->flag=false;//初始结点flag都设为假
prev->next=current;
prev=current;
}
prev->next=head->next;//使最后一个元素指针域指向头结点后的那个结点构成循环链表
current=head->next;//使current指向头指针后的那个结点,即输入的第一个数
for(int i=1;i<s;i++)//从1开始数,使prev指针指向s-1,使current指向s
{
prev=prev->next;
current=current->next;
}
current->data=s;
current->flag=true;
int r=0;
while(r<n-1)
{
r++;
for (int i = 1; i <= k[r] + 1; i++)
{
prev = prev->next;
current = current->next;
if (current->flag)
{
i--;
continue;
}
}
current->data = k[r];
current->flag = true;
}
return head;
}
//主函数
int main()
{
const int n=15;
int k[n];
for(int i=0;i<n;i++)
k[i]=i+1;
PNode head=JosephusCard(n,1,k);
printLinkList(head,n);
system("pause");
}
数据结构—Josephus问题变形
最新推荐文章于 2022-01-27 13:54:34 发布