作业:循环链表--选班长
作业:循环链表--选班长
约瑟夫环问题
题目:有44人,从1开始报数,每次到3时淘汰那个人,重新开始从1报数,直到只有最后一人为止。
单链表---》循环链表
单链表的最后一个结点的next指向头结点 形成一个循环
//构建循环链表 最后一个结点的指向为head
p->next = head;
获取最后1人
当p->next等于p时 表明只剩下1个节点
while (p->next!=p)//所以这里p->next!=p时 表明至少存在两个
{
//移动到待删除元素前一个
while ((index+1)!=m)
{
p = p->next;
index++;
}
index = 1;
//打印待删除元素的信息
//printf("%d \t", p->next->data);
//执行链表上的删除 但是删除元素任然存在于内存中
p->next = p->next->next;
//删除后 移动到下一个重新开始报数c
p = p->next;
}
链表的反转
额外申请空间,当前node->next-next暂存起来
node->next的这个结点的next指向node
node* tmp,*orginHead=head, * newHead, *newTmp;
newHead = head->next;
tmp = head->next->next;//先记录下一个即将操作的节点
//先反转一次 第二个节点的next指向原来的第一个节点
head->next = NULL;
newHead->next = head
完整的代码
#include <stdio.h>
#include <malloc.h>
//
//约瑟夫环问题
//
//循环链表
typedef struct Node {
struct Node *next;
int data;
}node;
node* initLinkList(int* arrStart,int len) {
struct Node* head = (node*)malloc(sizeof(node)), * tmp, * p;
p = head;
head->data = *arrStart;
for (int i = 1; i < len; i++) {
tmp = (node*)malloc(sizeof(node));
tmp->data = *(arrStart + i);
tmp->next = NULL;
p->next = tmp;
p = p->next;
}
//构建循环链表 最后一个结点的指向为head
p->next = head;
return head;
}
/// <summary>
/// 链表反转 时间复杂度:O(n)
/// </summary>
/// <param name="head"></param>
/// <returns></returns>
node* linkListReverse(node* head) {
node* tmp,*orginHead=head, * newHead, *newTmp;
newHead = head->next;
tmp = head->next->next;//先记录下一个即将操作的节点
//先反转一次 第二个节点的next指向原来的第一个节点
head->next = NULL;
newHead->next = head;
while (tmp!=head)
{
newTmp = tmp->next;
tmp->next = newHead;
newHead = tmp;
tmp = newTmp;
}
head->next = newHead;//形成一个循环
return newHead;
}
void displayLinkList(node* head,int n) {
int count = 0;
while (count<n)
{
printf("%d \t", head->data);
head = head->next;
count++;
}
printf("\n\n");
}
/// <summary>
/// 获取最后一个人 约瑟夫环问题
/// </summary>
/// <param name="n">n人</param>
/// <param name="m">第m人出局</param>
/// <returns>最后剩下的那个人</returns>
int GetLastRemain(node* head,int m) {
node* p = head,*originHead=head;
int index = 1;
while (p->next!=p)
{
//移动到待删除元素前一个
while ((index+1)!=m)
{
p = p->next;
index++;
}
index = 1;
//打印待删除元素的信息
//printf("%d \t", p->next->data);
//执行链表上的删除 但是删除元素任然存在于内存中
p->next = p->next->next;
//删除后 移动到下一个重新开始报数
p = p->next;
}
return p->data;
}
int main() {
int arrs[44] = { 761,762,770,774,775,800,807,825,826,842,849,879,884,885,892,893,896,900,903,912,947,951,955,959,
962,965,970,977,978,980,1004,1008,1041,1045,1048,1050,1056,1057,1081,1082,1084,1088,1089,1121 };
node* head = initLinkList(&arrs, 44);
displayLinkList(head, 44);
int p=GetLastRemain(head, 3);
printf("\n%d\n\n", p);
head = initLinkList(&arrs, 44);
head=linkListReverse(head);
displayLinkList(head, 44);
p = GetLastRemain(head, 3);
printf("\n%d\n\n", p);
system("pause");
}