数据结构—约瑟夫环问题(循环单链表)
n个数据元素构成一个环,从环中任意位置开始计数,计到m将该元素从表中取出,重复上述过程,直至表中只剩下一个元素。
解题思路:用一个无头结点的循环单链表来实现n个元素的存储。循环单链表:尾指针指向头结点。这样指针可以循环移动。
可以使用两个指针来操作,将指针q指向需要操作的结点上,指针p指向需要操作结点的前一个结点。
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <malloc.h> 4 #include <math.h> 5 #define NULL 0 6 typedef struct LNode 7 { 8 int num;///编号 9 struct LNode *next; 10 } LNode, *Linklist; 11 Linklist head,tail; 12 void Createlist(int n)///创建含有n个结点的单循环链表 13 { 14 int i; 15 Linklist p,q; 16 head=(Linklist)malloc(sizeof(LNode)); 17 q=head; 18 q->num=1; 19 for(i=2; i<=n; i++) 20 { 21 p=(Linklist)malloc(sizeof(LNode)); 22 p->num=i; 23 q->next=p; 24 q=p; 25 } 26 p->next=head; 27 tail=p;///尾指针要指向头结点 28 } 29 void Outlist(int k) 30 { 31 int i; 32 Linklist p,q; 33 p = head; 34 for(i=1; i<k-1; i++)///循环k-2次 35 { 36 p = p->next;///指向需要操作元素的前一个指针 37 } 38 q = p->next;///指向需要操作元素的指针 39 while(q != p) 40 { 41 printf("%3d",q->num); 42 p->next = q->next;///删除q所指向的元素 43 for(i=1; i<k; i++)///因为要经过已经删除的元素,所以需要多删除一次 44 { 45 p = p->next; 46 } 47 q = p->next; 48 } 49 printf("%3d\n",q->num); 50 51 } 52 int main() 53 { 54 int k,n; 55 printf("---------------约瑟夫环问题--------------\n"); 56 printf("\n请输入总人数和从第几个人开始报数n,k:\n"); 57 scanf("%d%d",&n,&k); 58 Createlist(n); 59 printf("\n出队的次序:\n"); 60 Outlist(k); 61 return 0; 62 }
我看了一下我同学的做法,可以p直接使用尾指针,而q来自头指针,这样在遍历的时候,p指针一直会在q指针之前。
1 void Outlist(int k) 2 { 3 int i; 4 Linklist p,q; 5 q = head; 6 p = tail; 7 for(i=1;i<k;i++) 8 { 9 p = p->next; 10 q = q->next; 11 } 12 while(q != p) 13 { 14 printf("%3d",q->num); 15 p->next = q->next; 16 q = p->next; 17 for(i=1;i<k;i++) 18 { 19 p = p->next; 20 q = q->next; 21 } 22 } 23 printf("%3d\n",q->num); 24 }