问题描述
功能描述(Description):有n个小孩子,按顺时针方向围成一个圆。老师指定从第m(m<n)个小孩开始报数,按顺序1,2,3…… 数到k个小孩时,该小孩子退到圈外,然后从报数为k的下一个小孩子开始报数。如此重复下去,直到所有小孩都出列,求小孩的出列顺序。
解题思路
构造一个循环链表,表示围成圈的孩子。
typedef struct _TAG_LinkedNode
{
Data data
;
_TAG_LinkedNode
* next
;
}Node
, *PNode
;
.每次找到一个孩子,就让其从当前链表退出,并加入新链表
直接上代码吧
#include "stdafx.h"
#include "assert.h"
#include<stdlib.h>
#include<iostream>
#define NOT_NUMBER -1
#define INIT_ERROR -3
#define BAD_INPUT -4
#define MALLOC_FAILED -5
#define REMOVE_FAILED -6
using namespace std
;
typedef int Data
;
typedef struct _TAG_LinkedNode
{
Data data
;
_TAG_LinkedNode
* next
;
}Node
, *PNode
;
PNode
init(int listLength
);
PNode
Add(PNode pTargetNode
, PNode pNewNode
);
PNode
Remove(PNode
*pInputStart
, int step
);
void Destory(PNode target
);
void Foreach(PNode head
);
int CheckAndConvert(const char *str
, int *num
);
void Input();
void Input(int *m
, int *n
, int *k
)
{
char buff
[128] = { 0 };
printf("请输入从第几个小孩开始m:");
scanf("%[^\n]", buff
);
while (CheckAndConvert(buff
, m
) != 0)
{
printf("请输入从第几个小孩开始m:");
getchar();
scanf("%[^\n]", buff
);
}
printf("请输入小孩的个数n:");
getchar();
scanf("%[^\n]", buff
);
while (CheckAndConvert(buff
, n
) != 0)
{
printf("请输入小孩的个数n:");
getchar();
scanf("%[^\n]", buff
);
}
printf("请输入每次循环找第几个k:");
getchar();
scanf("%[^\n]", buff
);
while (CheckAndConvert(buff
, k
) != 0)
{
printf("请输入每次循环找第几个k:");
getchar();
scanf("%[^\n]", buff
);
}
}
PNode
init(unsigned int listLength
)
{
int ret
= 0;
PNode pHead
= NULL;
for (int i
= 0; i
< listLength
; i
++)
{
PNode pNewNode
= (PNode
)malloc(sizeof(Node
));
if (pNewNode
== NULL)
{
cout
<< "内存分配失败" << endl
;
ret
= MALLOC_FAILED
;
break;
}
pNewNode
->data
= i
+ 1;
pHead
= Add(pHead
, pNewNode
);
}
if (ret
== MALLOC_FAILED
)
{
Destory(pHead
);
pHead
= NULL;
}
return pHead
;
}
PNode
Add(PNode pTargetNode
, PNode pNewNode
)
{
PNode tHead
= pTargetNode
;
if (pNewNode
== NULL)
{
cout
<< "添加的节点不能为NULL" << endl
;
return NULL;
}
if (tHead
!= NULL)
{
pNewNode
->next
= tHead
->next
;
tHead
->next
= pNewNode
;
}
else
{
tHead
= pNewNode
;
tHead
->next
= tHead
;
}
return pNewNode
;
}
PNode
Remove(PNode
*pInOutStart
, unsigned int step
)
{
PNode pDelPre
= NULL;
PNode pDel
= *pInOutStart
;
if (pDel
== NULL)
{
return NULL;
}
for (int i
= 0; i
< step
; i
++)
{
pDelPre
= pDel
;
pDel
= pDel
->next
;
}
if (pDelPre
== NULL)
{
pDelPre
= pDel
;
while (pDelPre
->next
!= pDel
)
{
pDelPre
= pDelPre
->next
;
}
}
if (pDelPre
== pDel
)
{
*pInOutStart
= NULL;
}
else
{
pDelPre
->next
= pDel
->next
;
*pInOutStart
= pDel
->next
;
}
return pDel
;
}
void Destory(PNode target
)
{
if (target
== NULL)
{
cout
<< "释放的资源为NULL" << endl
;
return;
}
PNode tHead
= target
;
PNode move
= tHead
;
do {
move
= tHead
->next
;
free(tHead
);
tHead
= move
;
} while (tHead
!= target
);
}
void Foreach(PNode head
)
{
if (head
== NULL)
{
cout
<< "遍历时头结点不能为NULL" << endl
;
return;
}
head
= head
->next
;
PNode tHead
= head
;
do {
cout
<< tHead
->data
<< "----";
tHead
= tHead
->next
;
} while (tHead
!= head
);
cout
<< endl
;
}
int CheckAndConvert(const char *str
, int *num
)
{
int i
= 0;
int total
= 0;
if (str
== NULL || num
== NULL)
{
cout
<< "不能传入NULL" << endl
;
return NOT_NUMBER
;
}
if (str
== '\0')
{
cout
<< "输入不能为空" << endl
;
return NOT_NUMBER
;
}
while (str
[i
] != '\0' && (str
[i
] == '\t' || str
[i
] == ' '))
{
i
++;
}
while (str
[i
] != '\0' && str
[i
] != '\t' && str
[i
] != ' ')
{
if (str
[i
] < '0' || str
[i
] > '9')
{
cout
<< "请输入纯数字.." << endl
;
return NOT_NUMBER
;
}
else
{
total
*= 10;
total
= total
+ (str
[i
] - '0');
}
i
++;
}
while (str
[i
] != '\0')
{
if (str
[i
] != '\t' && str
[i
] != ' ')
{
cout
<< "请输入纯数字.." << endl
;
return NOT_NUMBER
;
}
i
++;
}
if (total
== 0)
{
cout
<< "值不能为0" << endl
;
return BAD_INPUT
;
}
*num
= total
;
return 0;
}
int main()
{
int m
= 0;
int n
= 0;
int k
= 0;
int ret
= 0;
PNode pOldHead
= NULL;
PNode pNewHead
= NULL;
PNode pTemp
= NULL;
Input(&m
, &n
, &k
);
if (m
> n
)
{
cout
<< "m不能大于n" << endl
;
system("pause");
return BAD_INPUT
;
}
pOldHead
= init((unsigned int)n
);
if (pOldHead
== NULL)
{
return INIT_ERROR
;
}
pOldHead
= pOldHead
->next
;
for (int i
= 0; i
< m
- 1; i
++)
{
pOldHead
= pOldHead
->next
;
}
while (pOldHead
!= NULL)
{
unsigned int kStep
= k
;
kStep
= (kStep
- 1) % n
;
pTemp
= Remove(&pOldHead
, kStep
);
if (pTemp
== NULL)
{
cout
<< "移除链表失败" << endl
;
ret
= REMOVE_FAILED
;
break;
}
else
{
n
--;
}
pNewHead
= Add(pNewHead
, pTemp
);
}
if (ret
== REMOVE_FAILED
)
{
Destory(pOldHead
);
Destory(pNewHead
);
return REMOVE_FAILED
;
}
cout
<< "依次退出的是:" << endl
;
Foreach(pNewHead
);
Destory(pNewHead
);
system("pause");
return 0;
}