I'm having a couple issues with the Josephus game. My first issue is that I can't figure out how to start counting at the person to the left of the person eliminated each round (game goes clockwise). It deletes correctly, but starts counting at the person to the right of the deleted person. My second issue is that I can't figure out how to print the eliminated person each round. I have the algorithm down for the most part, but I can't figure out these small details. Any help would be appreciated!
import java.io.*;
////////////////////////////////////////////////////////////////
class Link
{
public int iData; // data item (key)
public Link next; // next link in list
// -------------------------------------------------------------
public Link(int id) // constructor
{ iData = id; }
// -------------------------------------------------------------
public void display() // display ourself
{ System.out.print(iData + " "); }
} // end class Link
////////////////////////////////////////////////////////////////
class CircList
{
private Link current; // ref to current link
private int count; // # of links on list
// -------------------------------------------------------------
public CircList() // constructor
{
count = 0; // no links on list yet
current = null;
}
// -------------------------------------------------------------
public boolean isEmpty()
{ return count==0; }
// -------------------------------------------------------------
public int getSize()
{ return count; }
// -------------------------------------------------------------
public void insert(int id) // insert after current link
{ // make new link
Link newLink = new Link(id);
if(count == 0) // if first one
{
current = newLink; // current points to it
current.next = current; // next one is us
}
else
{
newLink.next = current.next; // downstream of new link
current.next = newLink; // upstream of new link
}
count++; // one more link
}
// -------------------------------------------------------------
public Link delete() // delete link following currrent
{
Link tempLink;
switch(count)
{
case 0: // current is already null
tempLink = current;
break;
case 1: // delete ourself
tempLink = current;
current = null;
count--;
break;
default: // delete the next one
tempLink = current.next;
current.next = tempLink.next;
count--;
break;
}
return tempLink;
}
// -------------------------------------------------------------
public Link find(int key) // find link with given key
{ // at one past current
int getHome = count;
while(getHome > 0) // while not back to
{ // beginning
if(current.next.iData == key) // found it?
return current.next; // return next one
else // not found
{ // go to next link
current = current.next;
getHome--; // one item closer to home
}
}
return null; // can't find it
}
// -------------------------------------------------------------
public Link delete(int key) // delete link with given key
{
Link nextLink = find(key); // find it
if(nextLink != null) // if found,
{
current.next = nextLink.next; // delete it
count--;
}
return nextLink; // return null or link
}
// -------------------------------------------------------------
public void display() // display the list
{
for(int j=0; j<count; j++)
{
current.next.display();
current = current.next;
}
System.out.println("");
}
// -------------------------------------------------------------
public void step()
{
if(count != 0)
current = current.next; // go to next link
}
// -------------------------------------------------------------
public Link peek()
{ return current.next; }
// -------------------------------------------------------------
} // end class CurcList
////////////////////////////////////////////////////////////////
class CircApp
{
public static void main(String[] args) throws IOException
{
int j, nPlayers, nSkips, startNo;
CircList theList = new CircList(); // make list
putText("Enter the number of players: ");
nPlayers = getInt();
for(j=nPlayers; j>0; j--) // number 10, 20, ...
theList.insert(j);
putText("Players: ");
theList.display();
putText("Enter the the number of spaces to skip: ");
nSkips = getInt();
putText("Enter the the starting player's number: ");
startNo = getInt();
// Add your code here
int m = 1, n;
while(m != startNo)
{
theList.step();
m++;
}
putText("Players: ");
theList.display();
while(theList.getSize() > 1){
n = 0;
while(n != nSkips){
theList.step();
n++;
}
theList.delete();
theList.display();
}
}
// end main()
// -------------------------------------------------------------
public static void putText(String s)
{
System.out.print(s);
System.out.flush();
}
// -------------------------------------------------------------
public static String getString() throws IOException
{
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
String s = br.readLine();
return s;
}
// -------------------------------------------------------------
public static char getChar() throws IOException
{
String s = getString();
return s.charAt(0);
}
//-------------------------------------------------------------
public static int getInt() throws IOException
{
String s = getString();
return Integer.parseInt(s);
}
// -------------------------------------------------------------
} // end class CircApp
Displaying the deleted player is a very easy to fix. Your delete() method returns the deleted Link, so you just need to use it when it's returned. Instead of just calling theList.delete() use something like:
theList.delete().display(); //start line
System.out.println("is eliminated"); //finish line
As for starting to the left of the deleted player, you need a way to move backwards through your circle. In small circles one way to do this is to step() one time fewer than the number of players (since stepping one time for each player makes a full trip around the circle back to the current player). So after the above code add
for(int i=0; i<theList.getSize()-1; i++)
theList.step();
I hope I understand you correctly - you want to start counting on the next person from the deleted, not the one before. Something like that:
public Link delete(int key) // delete link with given key
{
Link nextLink = find(key); // find it
if(nextLink != null) // if found,
{
current.next = nextLink.next; // delete it
current = current.next; //move to the next person
count--;
}
return nextLink; // return null or link
}
As for the second question - you return the deleted element, just print it like so:
Link retVal = theList.delete();
if (retVal != null) {
retVal.display();
}
Related
I am using a Linked list/ Iterater combo to compute the Josephus problem, and need it to only print if there is only one element left in the list, but how would I use an if statement to check a condition that references to the size of the list rather than the number in the list with "ourList" being of type "LinkedList"?
Here is a piece of the code:
if(atEnd() == true){
//System.out.println("Value removed: " + current.dData);
previous.next = current.next;
current = ourList.getFirst();
//if(ourList == Only contains one element){ <--------------
//ourList.displayList();
// }
}
for reference heres my LinkedList + Iterator:
class Link{
public int dData;
public Link next;
public Link(int data){
dData = data;
}
public void displayLink(){
System.out.print(dData + " ");
}
}
class LinkList{
private Link first;
public LinkList(){
first = null;
}
public Link getFirst(){
return first;
}
public void setFirst(Link f){
first = f;
}
public boolean isEmpty(){
return first == null;
}
public ListIterator getIterator(){
return new ListIterator(this);
}
public void displayList(){
Link current = first;
while(current != null){
current.displayLink();
current = current.next;
}
System.out.println("");
}
}
class ListIterator{
private Link current;
private Link previous;
private LinkList ourList;
public ListIterator(LinkList list){
ourList = list;
reset();
}
public void reset(){
current = ourList.getFirst();
previous = null;
}
public boolean atEnd(){
return(current.next == null);
}
public boolean atEndPrevious(){
return(previous.next == null);
}
public Link getCurrent(){
return current;
}
public void nextLink(){
previous = current;
current = current.next;
}
public void insert(int value){
Link newLink = new Link(value);
if(ourList.isEmpty() == true){
ourList.setFirst(newLink);
current = newLink;
}else{
newLink.next = current.next;
current.next = newLink;
nextLink();
}
}
public void beginningPoint(int begin){
if(begin == 1){
current = ourList.getFirst();
previous = null;
// System.out.println("Current Location: " + current.dData);
}else if(begin != 1){
current = ourList.getFirst();
previous = null;
for(int i = 1; i < begin; i++){
nextLink();
// System.out.println("Current Location: " + current.dData);
}
}
}
Adding pseudocode, since it will help you understand the process, but learn by programming it yourself. Also note you could remove some else's through the behavior of exiting.
All of this functions through the iterator.
if at end
dont print and exit (0 elements)
else
get and save next element to variable
if at end
print the variable you saved (only 1 element)
else
dont print and exit (more than 1 element)
(disclaimer: for school, so cant import other Java utilities)
So I have to merge sort on a linked list, and I have almost all of it down. Here it is:
class musicNode {
String track; // The name of the track
int played= 0; // The number of times played
int shuffleTag= 0; // For shuffling
musicNode next;
public musicNode() { // Here's how we construct an empty list.
next = null;
}
public musicNode(String t) {
track = t; next = null;
}
public musicNode(String t, musicNode ptr) {
track = t; next = ptr;
}
public boolean LTTrack(musicNode x) { // Compares tracks according to alphabetical order on strings
if (this.track.compareTo(x.track)<=0) return true;
else return false;
}
};
// This class represents a playlist;
// We assume that each track appears at most once in the playlist
public class MusicPlayer {
protected musicNode head = null; // Pointer to the top of the list.
int length=0; // the number of nodes in the list.
boolean debug= false;
public MusicPlayer() {
}
public void setToNull() {
head = null;
}
public boolean isEmpty() {
return head == null;
}
public musicNode head() {
return head;
}
void insertTrack(String name) { // Inserts a new track at the top of the list.
musicNode temp= new musicNode(name, head);
head= temp;
length++;
}
void sortTrack() { // TODO
musicNode main = this.head;
mergeSort(main);
}
public musicNode mergeSort(musicNode head) {
if ((head == null) || (head.next == null)){
return head;
}
musicNode left = head;
musicNode right = head.next;
while((right != null) && (right.next != null)){
head = head.next;
right = (right.next).next;
}
right = head.next;
head.next = null;
return merge(mergeSort(left), mergeSort(right));
}
There also this JUnit test:
public void testSortMixed() {
MusicPlayer trackList= new MusicPlayer();
trackList.insertTrack("d");
trackList.insertTrack("b");
trackList.insertTrack("e");
trackList.insertTrack("a");
trackList.insertTrack("c");
MusicPlayer trackListTwo= new MusicPlayer();
trackListTwo.insertTrack("e");
trackListTwo.insertTrack("d");
trackListTwo.insertTrack("c");
trackListTwo.insertTrack("b");
trackListTwo.insertTrack("a");
trackList.sortTrack();
musicNode tmp= trackList.head;
musicNode tmp2= trackListTwo.head;
for(int i=0; i< 5; i++){
assertEquals(tmp2.track, tmp.track);
tmp2= tmp2.next;
tmp=tmp.next;
}
}
The problem is that it sorts according to the last track you insert, and only from then on. So say you insert alphabets from a-f, but the last one you insert was "c", itll only show you "cdef". But if the last one was "a" then it works as intended.
So how it works is, when you insert a track it gets inserted onto the beginning of the list, not end, becoming the head. I feel like that may be whats messing it up, as I adapted and looked from my notes and online which insert at the bottom.
I dont know how to account for this though. Also I know it sorts based on what was inserted last (in the JUnit test above it sorts to "cde" because I created a main function and played around with it)
ANY help appreciated.
The key point is the second line in the method sortTrack:
void sortTrack() {
musicNode main = this.head;
this.head = mergeSort(main); // you forgot to set the head of linked list to the merged
}
I'd tested it in my laptop and everything goes okay now xD
I have some problems that code. I read file in code and build one stack and one queues structure. But the code wasn't run correctly.
This is Node class
I used Double LinkedList
public class Node
{
String data;
Node next;
Node prev;
public Node(String data,Node next, Node prev){
this.next=next;
this.data=data;
this.prev=prev;
}
public Node(){
}
public String getData(){
return data;
}
public void setData(String data){
this.data=data;
}
public Node getNext(){
return next;
}
public void setNext(Node next){
this.next=next;
}
public Node getPrev(){
return prev;
}
public void setPrev(Node prev){
this.prev=prev;
}
}
** this is stack class. **
public class Stack {
Node head = null;
Node tail = null;
int size=0;
public int getSize() {
return size;
}
public boolean isEmpty()
{
return head == null;
}
public void Push(String data) {
tail = head;
head = new Node(data,null,null);
head.data=data;
head.next= tail;
head.prev = null;
if(tail != null) {
tail.prev=head;
}
size++;
}
public void Pop() {
if (!isEmpty()) {
head = head.next; // delete first node
size--;
} else {
System.out.println("İs Empty");
}
}
public void Top() {
Node tmp = head;
while (tmp != null) {
System.out.println(tmp.getData());
tmp = tmp.getNext();
}
}
}
This is Queues Class
public class Oueues {
Node head ;
Node tail;
int size=0;
public Oueues(){
this.head=null;
this.tail=null;
}
public boolean isEmpty()
{
return head == tail;
}
public int getSize()
{
return size;
}
public void insert(String data){
Node tmp = new Node(data,null,null);
tmp.data=data;
tmp.next=null;
if(head==null){
head=tail=tmp;
head.prev=null;
}
else{
tail.next=tmp;
tmp.prev=tail;
tail=tmp;
}
}
public String remove(){
if(head.next==tail)
return null;// list empty
Node tmp=head.next;
head.next=tmp.next;
tmp.next.prev=head;
list();
return tmp.data;
}
public void list(){
System.out.println("Queues");
if(size==0){
System.out.println("İs Empty");
}
Node tmp=head;
while(tmp !=tail.getNext()){
System.out.println(tmp.getVeri()+" ");
tmp= tmp.getNext();
}
System.out.println();
}
}
This is Queues Class
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;
public class OGrenci {
public static void main(String[] args) throws IOException {
Scanner s = new Scanner(System.in);
Stack y = new Stack();
Oueues k = new Oueues();
FileWriter fwy;
FileWriter fwk;
File stack = new File("stack.txt");
if (!stack.exists()) {
stack.createNewFile();
} else {
System.out.println("already exists ");
}
BufferedReader reader = null;
reader = new BufferedReader(new FileReader(stack));
String line = reader.readLine();
while (line != null) {
y.Push(line = reader.readLine());
System.out.println(line);
}
File queue = new File("queue.txt");
if (!queue.exists()) {
queue.createNewFile();
} else {
System.out.println("already exists ");
}
BufferedReader read = null;
read = new BufferedReader(new FileReader(queue));
String lines = read.readLine();
while (lines != null) {
lines = read.readLine();
k.insert(lines);
System.out.println(lines);
}
int choice;
System.out.println("1. Stack out- queue add");
System.out.println("2. Stack add- queue out");
System.out.println("3. Stack and queue ");
System.out.println("4. File writer");
choice = s.nextInt();
switch (choice) {
case 1:
k.insert(s.next());
k.list();
y.pop();
break;
case 2:
y.Push(s.next());
y.Top();
k.remove();
break;
case 3:
y.Top();
k.list();
break;
case 4:
fwy = new FileWriter(stack);
Node no = y.head;
while (no.next != null) {
fwy.write("\n" + no.data);
no = no.next;
}
fwy.flush();
fwy.close();
fwk = new FileWriter(queue);
Node noo = k.head;
while (noo.next != null) {
fwk.write("\n" + noo.data);
noo = noo.next;
}
fwk.flush();
fwk.close();
break;
}
}
Ok, so you have a couple of problems. I'm going to point out a few and let you work to fix the rest because this looks like an assignment and I don't want to do your homework for you :).
First, when you read from the file be careful not to ignore the first element:
String line = reader.readLine();
while (line != null)
{
System.out.println("Read from stack: " + line);
// we already read one element
y.Push(line);
line = reader.readLine();
}
Notice that unlike your solution I first do the push y.Push(line) so that we don't forget to add whatever is already read into line. Same goes for the queue file:
String lines = read.readLine();
while (lines != null)
{
System.out.println("Read from queue: " + lines);
// we already read one line
k.insert(lines);
lines = read.readLine();
}
Just add it if it's not null and then read the next line. You were always missing on the first element from the file.
Another problem is the Queues class (which by the way is misspelled you should replace O with Q). This one is not working properly because you forgot to increment and decrement the size when you insert or remove.
public void insert(String data){
Node tmp = new Node(data,null,null);
tmp.data=data;
tmp.next=null;
if(head==null){
head=tail=tmp;
head.prev=null;
}
else{
tail.next=tmp;
tmp.prev=tail;
tail=tmp;
}
size++;
}
Notice that at the end of insert I'm increasing the size so that the list method doesn't throw a NullPointerException every time we call it. Same goes for the remove method:
public String remove(){
if(head == null)
return null;// list empty
Node tmp=head.next;
head.next=tmp.next;
tmp.next.prev=head;
size--;
list();
return tmp.data;
}
Please also notice that your check before (if(head.next==tail)) was also throwing NullPointerException because at the beginning the head is always null so you cannot access the next member.
Finally I've made a small improvement to the list method as well so that we return earlier:
public void list(){
System.out.println("Queues");
if(size==0){
System.out.println("İs Empty");
return;
}
Node tmp=head;
while(tmp != tail.getNext()){
System.out.println(tmp.getData() + " ");
tmp= tmp.getNext();
}
System.out.println();
}
Notice the return if the Queue is empty, otherwise we will attempt to do tail.getNext() which will always throw a NullPointerException.
Some important thoughts about the code in general
Please avoid weird naming. Why Queues? There is just one so it should be Queue.
Please avoid weird variable names. Your code is not just for you, chances are someone else might need to read and it gets hard to know who it is s, y, k, fwy and fwk. Why not naming them like this:
Scanner scanner = new Scanner(System.in);
Stack stack = new Stack();
Queues queue = new Queues();
FileWriter stackFileWriter;
FileWriter queueFileWriter;
And the same goes for methods . Why Push, Pop and Top are the only methods that start with upper-case letter ? If you don't agree with the standard Java naming convention that is fine but at least be consistent :).
Try the suggested improvements and see how your program it's working. I'm almost sure there are more problems with it. If you can't figure them out yourself leave a comment and I will help you. Good luck!
So like the title says I'm trying to input a node in the third position of the linked list. The way I originally tried to do it was to insert two places down the list after numberOfItems was >= 3. I figured if I was getting an error it would be outputting the last 2 Players wrongly but it's just continuing to output Player 1. Can anybody point me to the right direction as to why this is happening?
Here is my linkedlist class
public class PlayerLinkedList extends ShellLinkedList
{
public PlayerLinkedList()
{
super();
}//end PlayerLinkedList constructor
public void insert(Player p)
{
if(numberOfItems >= 3)
{
PlayerNode pn = new PlayerNode(p);
head = pn;
pn.setNext(head.getNext().getNext());
numberOfItems++;
}
else
{
PlayerNode pn = new PlayerNode(p);
if(head == null)
{
head = pn;
}
pn.setNext(head);
head = pn;
numberOfItems++;
}
}//end insert method
public Player delete(int searchID) throws DataStructureException
{
PlayerNode current = head;
PlayerNode previous = null;
while(current != null && current.getPlayer().getID()!=searchID)
{
previous = current;
current = current.getNext();
}//end while
if(current == null) //not found
throw new DataStructureException(searchID + "not found: cannot be deleted");
else
{
if(current == head)
head = head.getNext(); //delete head
else
previous.setNext(current.getNext());
numberOfItems--;
return current.getPlayer();
}//end else
}//end delete
}//end class
Also just for reference here is my ShellLinkedList class
public abstract class ShellLinkedList
{
protected PlayerNode head;
protected int numberOfItems;
public ShellLinkedList()
{
head = null;
numberOfItems = 0;
}//end ShellLinkedList constructor
public int getNumberOfItems()
{
return numberOfItems;
}// end of getnumberOfItems
public boolean isEmpty()
{
return (numberOfItems==0);
}//end isEmpty
public String toString()
{
String listString="";
PlayerNode current = head;
for(int i = 0; i<numberOfItems && current != null; i++)
{
listString += current.getPlayer().toString()+"\n";
current = current.getNext();
}
return listString;
}//end toString
}//end class
My input is:
Player one = new Player(1, "Mike", "Mario");
Player two = new Player(2, "Brian", "Halo");
Player three = new Player(3, "John", "Minecraft");
Player four = new Player(4, "Thrall", "WoW");
Player five = new Player(5, "Scott", "Metroid");
list.insert(one);
list.insert(two);
list.insert(three);
list.insert(four);
list.insert(five);
System.out.println(list.toString());
And my output is:
id: 3 name: John game: Minecraft
id: 2 name: Brian game: Halo
id: 1 name: Mike game: Mario
id: 1 name: Mike game: Mario
id: 1 name: Mike game: Mario
There are a few problems with your code, your insert method behaves differently when numberOfItems >= 3 which is why you are not able to add more than 3 times. In that code block you are creating a new PlayerNode instance but you do not keep any reference to it.
You should also check whether you are expecting normal List#add behaviour which appends to the end of a list not the beginning.
I solved the issue by adding
head.getNext().setNext(pn);
after
pn.setNext(head.getNext().getNext());
I'm trying to implement the a Stack in Java with a circular singly linked list as the underlying data structure. I placed the insert function for a circular linked list in replacement of the push function for the stack and so on. I don't have any errors but I'm having troubles displaying the stack. If anyone could point me in the right direction of how to display the stack or what's going wrong I'd really appreciate it!
Here is my stack class:
public class Stack {
private int maxSize; // size of stack array
private long[] stackArray;
private int top; // top of stack
private Node current = null; // reference to current node
private int count = 0; // # of nodes on list
private long iData;
public Stack(int s) // constructor
{
maxSize = s; // set array size
stackArray = new long[maxSize]; // create array
top = -1; // no items yet
}
public void push(long j) // put item on top of stack
{
Node n = new Node(j);
if(isEmpty()){
current = n;
}
n.next = current;
current = n;
count++;
}
//--------------------------------------------------------------
public Node pop() // take item from top of stack
{
if(isEmpty()) {
return null;
}
else if(count == 1){
current.next = null;
current = null;
count--;
return null;
}else{
Node temp = current;
current = current.next;
temp.next = null;
temp = null;
count--;
}
return current;
}
//--------------------------------------------------------------
public Node peek(long key) // peek at top of stack
{
Node head = current;
while(head.iData != key){
head = head.next;
}
return head;
}
//--------------------------------------------------------------
public boolean isEmpty() // true if stack is empty
{
return (count == 0);
}
//--------------------------------------------------------------
public boolean isFull() // true if stack is full
{
return (count == maxSize-1);
}
//--------------------------------------------------------------
Here is my constructor class
public class Node{
public long iData; // data item (key)
public Node next; // next node in the list
public Node(long id){ // constructor
iData = id; // next automatically nulls
}
public void displayNode(){
System.out.print(iData + " ");
}
public static void main(String[] args) {
Stack newlist = new Stack(3);
newlist.push(1);
newlist.push(2);
newlist.push(3);
newlist.push(4);
newlist.pop();
newlist.pop();
newlist.push(4);
newlist.pop();
newlist.peek(1);
newlist.push(5);
while( !newlist.isEmpty() ) // until it’s empty,
{ // delete item from stack
Node value = newlist.pop();
System.out.print(value); // display it
System.out.print(" ");
} // end while
System.out.println("");
}
//newlist.displayList();
}
First, in your main function you are printing value using System.out.print function. This displays the object's class name representation, then "#" followed by its hashcode.
Replace following lines
System.out.print(value); // display it
System.out.print(" ");
with
value.displayNode();
Second, in pop method, you are returning null when count is 1. It should return the last element which is present in the list. Also, in last else if clause, you should return temp. Replace your code with this.
public Node pop() // take item from top of stack
{
if (isEmpty()) {
return null;
}
Node temp = current;
if (count == 1) {
current = null;
} else {
current = current.next;
}
count--;
temp.next = null;
return temp;
}
A few notes on your implementation:
1) stackArray member seems to be a leftover from another array based stack implementation.
2) is max size really a requirement? if so, you don't enforce the stack size limitation in push(..)
3) Your push(..) method doesn't keep the list circular. You should close the loop back to the new node.
4) Adding a dummy node allows you to keep the linked list circular, regardless of the stack size. This can make your push(..) method simpler (as well as any iteration for printing purposes for example)
5) The peek() method contract is unclear. Usually you want the peek method to return the value in the top of the stack, without removing it. Also, why do you return type Node? This class should be hidden from the caller - it's an internal implementation detail, not something you want to expose in your API.
Following is an alternative implementation, that also supports toString():
public class Stack {
private Node EOS;
private int count = 0;
public Stack() {
EOS = new Node(0);
EOS.next = EOS;
}
public void push(long j) {
Node newNode = new Node(j);
Node tmp = EOS.next;
EOS.next = newNode;
newNode.next = tmp;
count++;
}
public Long pop() {
if (isEmpty()) {
return null;
} else {
count--;
Node node = EOS.next;
EOS.next = node.next;
return node.iData;
}
}
public Long peek() {
if (isEmpty()) {
return null;
} else {
Node node = EOS.next;
return node.iData;
}
}
public boolean isEmpty() {
return (count == 0);
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
Node p = EOS.next;
while (p != EOS) {
sb.append(p).append("\n");
p = p.next;
}
return sb.toString();
}
private static class Node {
public long iData;
public Node next;
public Node(long id) {
iData = id;
}
#Override
public String toString() {
return "<" + iData + ">";
}
}
}