Fork me on GitHub

数据结构与算法——循环链表的算法实现(Joseph 问题)

Joseph 问题:

如果有10 个人,按编号顺序1,2,。。。,10 顺时针方向围成一圈。从1 号开始顺时针方向1,2,。。。,9 报数,凡报数9 者出列(显然,第一个出圈为编号9 者)。

最后一个出圈者的编号是多少?

第5 个出圈者的编号是多少?z

 

 

 

 .

代码实现

  1 #include<iostream>
  2 #include<string>
  3 #include<stdlib.h>
  4 
  5 using namespace std;
  6 
  7 typedef struct _LinkNode
  8 {
  9     int data;                           //结点的数据域
 10     struct _LinkNode* next;             //结点的指针域
 11 }LinkNode, LinkList;                    //LinkList 为指向结构体LNode 的指针类型
 12 
 13 void LinkPrint(LinkList* L);
 14 
 15 bool InitList(LinkList*& L)             //构造一个空的循环链表L
 16 {
 17     L = new LinkNode;                   //生成新结点作为头结点,用头指针L 指向头结点
 18     if (!L)return false;                //生成结点失败
 19     L->next = L;                        //头结点的指针域指向自己
 20     L->data = -1;
 21     return true;
 22 }
 23 
 24 //尾插法
 25 bool ListInsert_back(LinkList*& L, LinkNode* node)
 26 {
 27     LinkNode* last = NULL;
 28     if (!L || !node) return false;
 29 
 30     //找到最后一个节点
 31     last = L;
 32     while (last->next != L) last = last->next;
 33 
 34     //新的节点链接到最尾部
 35     node->next = L;
 36     last->next = node;
 37 
 38     return true;
 39 }
 40 
 41 bool Joseph(LinkList*& L, int interval)
 42 {
 43     //在带头结点的循环链表L 中,每个interval 个间隔循环删除节点
 44     LinkList* p, * q;
 45     int j = 0, i = 0;
 46     int times = 0, num = 0;
 47     p = L;
 48 
 49     if (!L || p->next == L) {
 50         cout << "链表为空!" << endl;
 51         return false;
 52     }
 53 
 54     if (interval < 1)
 55     {
 56         cout << "报数淘汰口令不能小于1!" << endl;
 57         return false;
 58     }
 59 
 60     do
 61     {
 62         i += interval;
 63         while ((p->next))                            //查找第i 个结点,p 指向该结点的上一个节点
 64         {
 65             if (p->next != L) j++;
 66             if (j >= i) break;
 67             p = p->next;
 68         }
 69         times++;
 70 
 71         /*if (!(p->next)||(j>i))//当i>n 或i<1 时,删除位置不合理
 72         return false;*/
 73 
 74         q = p->next;                                //临时保存被删结点的地址以备释放空间
 75         num = q->data;
 76         if (times == 5)cout << "第 5 个出圈的编号是:" << num << endl;
 77         printf("cur: %d last: %d next:%d\n", q->data, p->data, q->next->data);
 78         p->next = q->next;                            //改变删除结点前驱结点的指针域
 79         delete q;                                    //释放被删除结点的空间
 80         LinkPrint(L);
 81     } while (L->next != L);                            //链表不为空,继续报数
 82     cout << "最后一个出圈的编号是:" << num << endl;
 83 
 84     return true;
 85 }
 86 
 87 void LinkPrint(LinkList* L)                            //循环链表的输出
 88 {
 89     LinkList* p;
 90     if (!L || L == L->next) {
 91         cout << "链表为空!" << endl;
 92         return;
 93     }
 94     p = L->next;
 95     while (p != L)
 96     {
 97         cout << p->data << "\t";
 98         p = p->next;
 99     }
100     cout << endl;
101 }
102 
103 int main()
104 {
105     int i, x;
106     LinkList* L;
107     LinkNode* s;
108 
109     //1. 初始化一个空的循环链表
110     if (InitList(L))
111     {
112         cout << "初始化一个空的循环链表!\n";
113     }
114 
115     //2. 创建循环链表(尾插法)
116     std::cout << "尾插法创建循环链表, 插入 10 个元素..." << endl;
117     i = 0;
118 
119     while ((++i) <= 10)
120     {
121         s = new LinkNode;//生成新结点
122         s->data = i; //输入元素值赋给新结点的数据域
123         s->next = NULL;
124         if (ListInsert_back(L, s)) {
125             cout << "插入成功!" << endl;
126         }
127         else {
128             cout << "插入失败!" << endl;
129         }
130     }
131 
132     cout << "尾插法创建循环链表输出结果:\n";
133     LinkPrint(L);
134 
135     //3. 解答约瑟夫问题
136     Joseph(L, 9);
137     system("pause");
138     return 0;
139 }

 

 

 

 

 

===================================================================================================================

posted @ 2020-08-18 19:49  索智源  阅读(252)  评论(0编辑  收藏  举报