C++ HOJ 约瑟夫问题 的 数组、链表及STL实现

【问题描述】

设编号为1,2,… n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m 的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。

【数组实现】

#include <iostream>
#include <stdio.h>
int Josephu(int n, int m)
{
  int flag, i, j = 0;
  int *arr = (int *)malloc(n * sizeof(int));
  for (i = 0; i < n; ++i)
    arr[ i ] = 1;
  for (i = 1; i < n; ++i)
  {
    flag = 0;
    while (flag < m)
    {
      if (j == n)
        j = 0;
      if (arr[j])
        ++flag;
      ++j;
    }
    arr[j - 1] = 0;
    printf("第%4d个出局的人是:%4d号/n", i, j);
  }
  free(arr);
  return j;
}
int main()
{
  int n, m;
  scanf("%d%d", &n, &m);
  printf("最后胜利的是%d号!/n", Josephu(n, m));
  system("pause");
  return 0;
}
int main()
{
  int n, m;
  scanf("%d%d", &n, &m);
  printf("最后胜利的是%d号!/n", Josephu(n, m));
  system("pause");
  return 0;
}

【链表实现——单链表】

#include <iostream>
#include <stdio.h>
using namespace std;
typedef struct Node
{
  int index;
  struct Node *next;
}JosephuNode;
int Josephu(int n, int m)
{
  int i, j;
  JosephuNode *head, *tail;
  head = tail = (JosephuNode *)malloc(sizeof(JosephuNode));
  for (i = 1; i < n; ++i)
  {
    tail->index = i;
    tail->next = (JosephuNode *)malloc(sizeof(JosephuNode));
    tail = tail->next;
  }
  tail->index = i;
  tail->next = head;
  // 接下来 tail和head将不是头为节点的表示,而是作为指针,用以互进
  // 今后实现 采用 p、q 表示 更合理
  for (i = 1; tail != head; ++i)
  {
    for (j = 1; j < m; ++j)
    {
      tail = head;
      head = head->next;
    }
    tail->next = head->next;
    printf("第%4d个出局的人是:%4d号/n", i, head->index);
    free(head);
    head = tail->next;
  }
  i = head->index;
  free(head);
  return i;
}
int main()
{
  int n, m;
  scanf("%d%d", &n, &m);
  printf("最后胜利的是%d号!/n", Josephu(n, m));
  system("pause");
  return 0;
}

【STL实现】

<pre name="code" class="cpp">#include<iostream>
#include<list>
using namespace std;
//使用标准库
int JosephusProblem_Solution(int n, int m)
{
	if(n < 1 || m < 1)
		return -1;
	list<int> listInt;
	unsigned i;
	//初始化链表
	for(i = 0; i < n; i++)
		listInt.push_back(i);

	list<int>::iterator iterCurrent = listInt.begin();
	while(listInt.size() > 1)
	{
		//前进m - 1步
		for(i = 0; i < m; i++)
		{
			if(++iterCurrent == listInt.end())
				iterCurrent = listInt.begin();
		}
		//临时保存删除的结点
		list<int>::iterator iterDel = iterCurrent;
		cout<<*iterDel;
		if(++iterCurrent == listInt.end())
			iterCurrent = listInt.begin();
		//删除结点
		listInt.erase(iterDel);
	}
	return *iterCurrent;
}
int main()
{
	JosephusProblem_Solution(8,5);
	return 0;
}

【小结】

1.数组实现是通过,flag标志位与数组下标实现数组读取的;

2.循环链表的节点结构与单链表的节点的结构是一样的;

3.循环链表的建表方式与单链表是不一样的,单链表需要练个指针伸缩互进,循环链表建表时一个指针飙到底;

4.循环链表实现约瑟夫计数的两个指针,采用的是同时指向实现伸缩互进的

5.循环链表的遍历终止条件使用首尾指针相等实现的;

6.STL中list.end()指的是链表的最后一个元素的下一个地址。

    原文作者:约瑟夫环问题
    原文地址: https://blog.csdn.net/u013630349/article/details/46963647
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞