C++ は循環単連結リストを使用してジョセフ リング問題を解決します

1 番から n 番までの番号が付けられた n 個の要素があり、k 番から数えてリングを形成し、すべての要素がデキューされるまで m のデキューに報告します。

要件: n、k、m の値はユーザーによって入力され、関数を呼び出すことによって実装されます。

テストデータ:

例: 1 から始まる 10 個の要素、3 に報告された要素がデキューされます。この場合、リストの順序は 3、6、9、2、7、1、8、5、10、4 になります。

5 番目から始まる 10 個の要素、1 に報告された要素がデキューされます。この場合、リストの順序は 5、6、7、8、9、10、1、2、3、4 になります。

20 から始まり 33 に報告された要素が 100 個の要素からデキューされます。デキューの順序は何ですか?

テストデータ 1 を例として取り上げます。

-------------------------------------------------- -----------------------------------

単一リンクリストのデータ構造を定義する

#include <iostream>
using namespace std;

typedef int ElemType;
typedef struct LNode 
{
	ElemType data;
	LNode* next;
} LinkNode;

1. 循環単一リンクリストを初期化する

void InitNode (LinkNode*& L)
{
	L = new LinkNode;
	L-> next = L;
}

 

2. 循環単一リンクリストを作成する末尾挿入法

void CreateListByRear (LinkNode*& L, LinkNode*& r, ElemType arr[], int n) 
{
	r = L;     				// 尾指针并指向头节点
	L->data = arr[0];       // 头节点的data赋值
	
	for (int i = 1; i < n; ++i) // 新建节点并插入数据
    {       
		LinkNode* s = new LinkNode;
		s->data = arr[i];
		r->next = s;
		r = s;
    }
	r->next = L;
}   

 

 3. サークルオーダーを出力する

pre ポインタは p の先行ノードを指します。これは、ノードを破棄した後に次のノードを接続するのに便利です。

void out(LinkNode*& p, LinkNode*& pre, int count, int move) 
{
	int i = 1;
	
//  移动节点,到开始的那个数
	while (--move) {
		p = p->next;
		pre = pre->next;
	}
	
//  当圈不为1个人时,循环出圈
	while (p->next != p)
    {
		
		if (i == count) // 数到某个数,就出圈
        {       
			i = 1;
			cout << p->data << " ";
			
			pre->next = p->next;    // 删除出圈节点
			delete p;
			p = pre->next;
			
		} 
        else
        {
			pre = pre->next;        // 如果没数到指定的数,就继续移动,并统计
			p = p->next;
			++i;
		}
	}
	cout << p->data << endl;        // 输出圈的最后一个数
}

-------------------------------------------------- - - - - - - - - - - - - - - - - - - - - メイン機能

int main() 
{
// 1. 定义头尾节点指针, 初始化头节点指针
	LinkNode* head; InitNode(head);
	LinkNode* rear;
	
// 2.定义, 输入需要的参数; 初始化数组并赋值
	int n, m, from;
	cout << "请输入元素个数: "; cin >> n;
	cout << "从第几个人开始? "; cin >> from;
	cout << "第几个人出圈? "; cin >> m;
	int* a = new int[n];        // 创建动态数组

	for (int i = 0; i < n; ++i) {   // 把元素插入到数组中
		a[i] = i + 1;
	}
	
//  3. 尾插法创建循环单链表并得到尾指针
	CreateListByRear(head, rear, a, n);
	
//  4. 出圈并输出
    cout << "出圈顺序为: ";
	out(head, rear, m, from);
	
//  5. 出圈后仅剩头节点,释放头节点指针所指空间即可
	delete head;
	
	return 0;
}

おすすめ

転載: blog.csdn.net/henry594xiaoli/article/details/124205699