1 //循环链表,链表的尾结点的link域中不是NULL,而是存放了指针链表开始结点的指针
2 设p是在循环链表中逐个结点检测指针,则在判断p是否达到链表的链尾时p->link == first
3
4
5 //循环链表的结构定义
6 typedef int DataType;
7 typedef struct node//循环链表定义
8 {
9 DataType data;//结点数据
10 struct node *link;//后继结点指针
11 }CirNode, *CirList;
12
13 //循环链表的插入算法
14 int Insert(CirNode *first, int i, DataType x)
15 {//将新元素x插入在循环链表中第i(1<=i)个结点位置。如果插入失败函数返回0,否则函数返回1.
16 if(i<1)
17 return 0;
18 CirNode *p = first, *q;
19 int k = 0;
20 while(p->link != first && k< i-1)//定位于第i-1个结点,如果i超出表长度则插入到链尾
21 {
22 p = p->link;
23 k++;
24 }
25 q = new CirNode;//创建新结点用q指示
26 if(!q){cerr<<"存储分配错误!\n"; exit(1);}
27 q->data = x;
28 q->link = p->link;//将*q链接在*p之后
29 p->link = p;
30 return 1;//插入成功
31 }
32
33 //循环链表的删除算法
34 int Remove(CirList& first, int i, DataType& x)
35 {//将链表中的第i个元素删去,通过引用型参数x返回该元素的值
36 //如果i不合理则删除失败,函数返回0, 否则函数返回1
37 if(i<1)return 0;//i太小,不合理
38 CirNode *p = first, *q;
39 int k = 0;
40 while(p->link != first && k < i-1)
41 {
42 p = p->link;
43 k++;
44 }
45 //if(p->link == L)//i太大,被删结点不存在
46 // return 0;
47 q = p->link;//用q保存被删结点地址
48 p->link = q->link;//重新链接,将被删结点从链中摘下
49 x = q->data;//取出被删结点的数据
50 delete q;//释放结点
51 return 1;
52 }
55 //仅设尾指针的循环链表
56 //不用表头指针而用一个指向表尾结点的指针rear标识,可以将插入和删除的时间复杂度提高到O(l)
57 //删除循环链表的指针p所指示的结点
58 int Remove(CirNode* &p, DataType& x)
59 {//将链表中的指针p所指示结点的元素删去,通过引用型参数x返回该元素的值
60
61 CirNode *q = p->link;
62 x = p->data;//取出p结点的元素
63 p->data = q->data;//下一结点的元素复制给被删结点
64 p->link = q->link;//重新链接,将下一结点从链中摘下
65 delete q;//释放下一结点
66 return 1;
67 }
68 //在循环尾端插入一个由newNode所指示的新结点
69 int Insert(CirNode* &p, DataType& x)
70 {//rear为尾指针
71 CirNode *newNode;
72 newNode->data = x;
73 newNode->link = rear->link;
74 rear->link = newNode;
75 }
78 //求解约瑟夫环问题
79
80 void Josephus(CirNode* & Js, int n, int m)
81 {
82 CirNode *p = Js, *pre = NULL;
83 for(int i = 0; i<n-1; i++)//执行n-1趟虚循环
84 {
85 for(int j = 0; j<m; j++)//令p向后移动m-1个结点
86 {
87 pre = p;
88 p=p->link;
89 }
90 cout<<"出列的人"<<p->data<<endl;//输出结点*p的数据
91 pre->link = p->link;
92 delete p;//删去结点*p
93 p = pre->link;
94 }
95 cout<<"最终优胜者是:"<<p->data<<endl;//输出结果
96 }
97 int main()
98 {
99 CirNode *clist, *last;
100 int n, m;
101 clist = new CirNode;//创建循环链表头结点
102 //if(!clist){cerr<<"存储分配失败!\n"; exit(1);}
103 clist->link = clist;
104 last = clist;//循环链表置空
105 cout<<"输入游戏者人数和报数间隔:";
106 cin>>n>>m;
107 for(int i=1; i<=n; i++)
108 {
109 last->link = new CirNode;//创建链表结点
110 if(!last->link){cerr<<"存储分配失败!\n"; exit(1);}
111 last = last->link;//逐个插入结点形成约瑟夫环
112 last->data = i;
113 }
114 Josephus(clist, n, m);//解决约瑟夫环问题
115 return 0;
116 }
117 //算法时间复杂度O(n*m)
约瑟夫环实现(C语言)
1 #include"stdio.h"
2 #include <malloc.h>
3
4 //单链表结构体
5 typedef struct Node
6 {
7 int index;
8 int key;
9 struct Node *next;
10 }LinkNode, *LinkList;
11
12 //创建链表
13 LinkList CreatLinkList()
14 {
15 LinkList L;
16 L = (LinkList)malloc(sizeof(Node));
17 printf("请输入第一个人的密码:\n");
18 int key;
19 scanf_s("%d",&key);
20 L->key = key;
21 L->index = 1;
22 L->next = L;
23 Node *tail;
24 Node *s;
25 tail = L;
26
27 printf("请输入构建循环单链表的长度-1:");//除去已经输入的第一个人
28 int len;
29 scanf_s("%d",&len);
30
31 for (int i = 1; i < len; i++)
32 {
33 s = (Node *)malloc(sizeof(Node));
34 scanf_s("%d", &s->key);
35 s->index = i + 1;
36 s->next = tail->next;
37 tail->next = s;
38 tail = s;
39 }
40 return L;
41 }
42
43 //约瑟夫环的实现
44 void yuesef(LinkList L,int Password)
45 {
46 int count = 1;
47 Node *p;
48 Node *s, *r;
49 p = L;
50 while (p->next != p)
51 {
52 if (count == Password - 1)
53 {
54 printf("下标:%d 密码:%d\n", p->next->index, p->next->key);
55 s = p->next;
56 p->next = s->next;
57 Password = s->key;
58 while (Password == 1 && p->next != p)
59 {
60 printf("下标:%d 密码:%d\n", p->next->index, p->next->key);
61 r = p->next;
62 p->next = r->next;
63 Password = r->key;
64 free(r);
65 }
66 free(s);
67 count = 1;
68 p = p->next;
69 }
70 else
71 {
72 p = p->next;
73 count++;
74 }
75 }
76 printf("下标:%d 密码:%d\n", p->index, p->key);
77 }
78
79 int main(void)
80 {
81 LinkList L;
82 L = CreatLinkList();
83 Node *p;
84 p = L;
85 printf("%d %d \n", p->index, p->key);
86 p = p->next;
87 //单链表的遍历
88 while (p != L)
89 {
90 printf("%d %d \n", p->index, p->key);
91 p = p->next;
92 }
93 printf("请输入初始关键值:\n");
94 int Password;
95 scanf_s("%d",&Password);
96 yuesef(L, Password);
97 getchar();
98 getchar();
99 return 0;
100 }