本文已参与「新人创作礼」活动,一起开启掘金创作之路。
接着上面说,说这一个最后一个算法题目,这是最后一个题目,也是最复杂的题目,题目如下: 4、算法题目,转圈数M数,最后出局的是哪个数。
#include <stdio.h>
#include <stdlib.h>
typedef struct Link
{
int data;
struct Link *next;
} LinkList;
LinkList * createLink(int n)
{
printf("enter function createLink\n");
LinkList *head, *rear, *new;
head = rear = (LinkList *)malloc(sizeof(LinkList));
int i = 0;
for(i = 0; i< n; i++)
{
new = (LinkList *)malloc(sizeof(LinkList));
new->data = i+1;
new->next = NULL;
rear->next = new;
rear = new;
}
rear->next = head->next;
printf("exit function createLink\n");
return rear;
}
LinkList* getJosephus(LinkList* rear, int m)
{
printf("enter function getJosephus\n");
LinkList *newHead, *newRear, *newLinkList;
LinkList *tempList;
newHead = newRear = (LinkList *)malloc(sizeof(LinkList));
//LinkList *oldHead = rear->next;
int i = 0;
while(rear != rear->next)
{
//原链表走m-1节点
for(i = 0; i < m-1; i++)
{
rear = rear->next;
}
//原链表删除第m个节点
tempList = rear->next;
rear->next = tempList->next;
tempList->next = NULL;
//新链表加入删除的第m个节点
newRear->next = tempList;
newRear = tempList;
}
//新链表加入原链表剩下的最后一个节点
newRear->next = rear;
newRear = rear;
newRear->next = newHead->next;
printf("exit function getJosephus\n");
return newRear;
}
void printJosephus(LinkList* newRear)
{
printf("enter function printJosephus\n");
//temp2先获取头节点
LinkList *temp2 = newRear->next;
do
{
printf("temp2->data=%d,", temp2->data);
temp2 = temp2->next;
}
while(temp2 != newRear->next);
//上面如果是头节点则结束循环
printf("\n");
printf("exit function printJosephus\n");
}
int main()
{
//1/创建5个节点的链表
LinkList *oldLinkList = createLink(5);
//打印当前链表的情况
printJosephus(oldLinkList);
//2/进行m循环,也就是约瑟夫循环
LinkList *newLinkList = getJosephus(oldLinkList, 3);
//打印约瑟夫循环的输出列表
printJosephus(newLinkList);
}
运行情况如下:
root@mkx:~/learn/Josephus# gcc josephus.c -o josephus
root@mkx:~/learn/Josephus# ./josephus
enter function createLink
exit function createLink
enter function printJosephus
temp2->data=1,temp2->data=2,temp2->data=3,temp2->data=4,temp2->data=5,
exit function printJosephus
enter function getJosephus
exit function getJosephus
enter function printJosephus
temp2->data=3,temp2->data=1,temp2->data=5,temp2->data=2,temp2->data=4,
exit function printJosephus
root@mkx:~/learn/Josephus#
5个数,用手画一下,就可知道,结果是对的。
这道题目,其实就是著名的约瑟夫算法,循环链表实现,是非常经典的实现方法,这里用了循环链表,比如非循环列表多了一个尾节点,这是需要注意的地方:
下面用图就可以非常形象的表现出来:
其关键就是head与rear两个指针,其操作对这两个指针进行操作就可以了。