[]データ構造それぞれLINKLIST鎖配列表SeqListは、問題を解決するヨセフス

ヨセフスの問題

次のようにヨセフスの問題が記載されている:
セット番号1,2,3,4、...、nは円形に座ってn個の個体を、合意された数がk(1 <= K <=である n)をオフ番号ヒトから、多数の個人的なコラムとM、および1から報告された次のいくつかを開始するようにm列の中と外の個人、および数、までラインアップし、それによって、シーケンス番号のうちのチームを作成する、のうち誰もしてくださいこのシーケンスの出力。

LINKLISTリストとシーケンステーブルSeqList

リストやテーブルは、線形シーケンステーブルであり、シーケンステーブルは、メモリセルに連続したアドレスのセットに格納された論理要素の順に線形のテーブルであり、リストは、ポインタによってつなぎ合わせ線形リストの要素であり、リスト隣接するメモリセルに隣接しない要素は、換言すれば、隣接する物理アドレスせずに記憶された隣接リスト要素間の論理的な順序を有します。
そして、前に順次テーブルの特定のリストを実装して、この記事を参照してください。

[] JavaクラスSeqList配列表に実装されるデータ構造
のJava objectlist LINKLISTに実装[]データ構造

個人的な推奨事項は、リストの順番を見てテーブルを見てください。

ヨセフスの問題分析

この問題を解決する鍵は、次の要素が最初の部分でなければならないときにアレイの端部に横断するときに、データ端に接続された端部を作ることです。シーケンステーブル場合、インデックスはゼロにリセットされ、データの最後までトラバース。あなたが単語のリストを使用している場合は、単に頭を指すテールポインタをしたい、単鎖循環リストになります。
デキュー操作は、リストは、シーケンステーブルが、デキューの関数呼び出しを削除する場合には、力要素の後部要素に要素デキューポインタの前に必要なだけである場合、比較的簡単であろう要素の削除、および前方ユニットの背後にある全体の要素をしましょう。
終結配列表は配列が原因各デキュー動作と、テーブルが空で終了する条件は、テーブル内の要素の順序は、1つ減少されるべきです。ポインタが空の場合、終了条件リストトラバーサルを終了します。

コードの実装

上記キーポイントの分析は、我々は次のステップ上記のロジックを達成するためにコードを使用することで、第1の順序テーブルを達成することです。

package DS;

import java.util.Scanner;

/*
 * SeqList API介绍
 * setIncr(int inc): 设置顺序表每次增加时增量的大小
 * setCapacity(int newSize): 设置新的最大容量
 * getCapacity(): 获取数组的最大容量
 * size(): 获取顺序表已经存放数据的数量,同length()
 * get(int i): 获取顺序表下标为i的元素值
 * set(int i,T x): 修改下标值为i的元素值,即为修改data[i]
 * indexOf(int begin,int end,T value): 在begin和end之间查找值为value的元素下标值,使用顺序查找法
 * indexOf(T o): 在整个线性表中查找元素o的下标值
 * indexOf(int begin,T o): 在下标为begin到末尾的线性表中查找元素o的下标值
 * add(int i,T x): 在i位置插入数据元素x
 * add(T x): 在表尾添加数据元素x
 * append(T x): 在表尾添加数据元素x
 * addSort(T x): 以有序方式向顺序表中插入数据元素x
 * sort(): 对顺序表从小到大排序
 * remove(int i): 删除下标为i的元素,并返回被删除的元素
 * remove(T value): 删除值为value的元素,并返回被删除的元素
 * clear(): 清除整个顺序表
 * toString(): 将顺序表转化成字符串,便于直接输出顺序表
 * toArray(): 将顺序表转化成Object数组,并返回
 * toArray(T[] a): 将顺序表转换为类型为E的数组
 * iterator(): 返回一个迭代对象
 * length(): 获取线性表长度
 * isEmpty(): 判断线性表是否为空
 */

public class Josephus_Seq {
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		int n, k, m;
		System.out.print("请输入n,k,m的值:");
		n = scan.nextInt();
		k = scan.nextInt();
		m = scan.nextInt();
		// 定义一个顺序表代表这组人,1表示这个人还未出队,最初都是未出队状态
		SeqList<Integer> seqList = new SeqList<Integer>();
		for (int i = 0; i < n; i++)
			seqList.add(i);
		// 因为顺序表是从0开始到n-1的,而题之中给的的k是从1到n的,所以将k-1付给k
		k--;
		int flag = 0, i = k;
		while (!seqList.isEmpty()) {
			flag++;
			if (flag == m) {
				//如果要将当前元素移除,i的值就不用变,因为移除后seqList中元素整体向前平移一个单位
				System.out.print((seqList.get(i) + 1) + " ");//输出出队编号,从1到n
				seqList.remove(i);
				if(seqList.isEmpty())
					break;
				flag = 0;
			}
			else {
				//如果这个元素不动,则需要i++来访问下一个元素
				i++;
			}
			if (i >= seqList.length)
				i = 0;
		}
	}
}

リストの実装:

package DS;

import java.util.Scanner;

/*
 * LinkList API介绍
 * 
 * LinkList(): 构造函数
 * clear(): 删除整个列表
 * removeAll(): 删除整个列表,调用clear函数来实现
 * getNode(int i): 获得逻辑上i号节点
 * get(int i): 获得逻辑上i号节点的值
 * set(int i,T x): 修改i号节点的值
 * add(int i,T x): 将值为x的节点插入到i号位置
 * add(T key): 在链表尾部插入元素key
 * addBack(T key): 在链表尾部插入元素key,和add(T key)函数的作用一样
 * addFront(T key): 在链表首部插入元素key
 * remove(int i): 删除i号节点,并返回i号节点对应的值
 * remove(): 重载remove,删除头节点
 * removeFront(): 删除链表头节点,与remove()函数同义
 * removeBack(): 删除链表尾节点
 * addSort(T value): 将值value按从小到大的排序方式插入链表
 * sort(): 对链表按照从小到大的顺序进行排序
 * indexOf(int begin,int end,T key): 在索引begin和end之间查找值key,返回逻辑编号
 * search(T key): 功能同indexOf,遍历整个链表,一般不使用,主要用于实现字典
 * contains(T key): 判断链表中是否存在值为key节点
 * toString(): 将链表中的值转换成字符串
 * toArray(): 将链表转换成Object数组
 * toArray(E[] a): 将单链表转化为特定类型的数组,使用了函数泛型
 * iterator(): 返回迭代器对象
 */

public class Josephus_Link {
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		int n, k, m;
		System.out.print("请输入n,k,m的值:");
		n = scan.nextInt();
		k = scan.nextInt();
		m = scan.nextInt();
		// 实例化LinkList对象来存储队伍信息
		LinkList<Integer> linkList = new LinkList<Integer>();
		// 初始化链表
		for (int i = 0; i < n; i++) {
			linkList.add(i);
		}
		// 将链表首位相连
		linkList.last.next = linkList.first;
		k--;
		int flag = 0;
		Lnode<Integer> pLnode = linkList.getNode(k);
		Lnode<Integer> qLnode = linkList.getNode(0);
		// System.out.print(linkList.first.data);
		while (pLnode != null) {
			flag++;
			if (flag == m) {
				System.out.print((pLnode.data + 1) + " ");
				// 获取pLnode前一个节点qLnode
				while (qLnode.next != pLnode) {
					qLnode = qLnode.next;
				}
				qLnode.next = pLnode.next;
				pLnode.next = null;
				pLnode = qLnode.next;
				flag = 0;
			} else {
				pLnode = pLnode.next;
			}
		}
	}
}

发布了61 篇原创文章 · 获赞 16 · 访问量 1万+

おすすめ

転載: blog.csdn.net/qq_41427568/article/details/89681131