I was tasked with creating my own linked list class, using a book class i made. One of the questions was to Determine the book that appears first alphabetically.
i was able to sort the Linked list alphabetically using bubble sort(i know its not efficient but im still new) here is the code.
public void alphaBubbleSort() {
int size = size();
if (size > 1) {
boolean wasChanged;
do {
Node current = head;
Node previous = null;
Node next = head.next;
wasChanged = false;
while (next != null) {
if (current.book.getName().compareToIgnoreCase(next.book.getName()) > 0) {
wasChanged = true;
if (previous != null) {
Node sig = next.next;
previous.next = next;
next.next = current;
current.next = sig;
} else {
Node temp = next.next;
head = next;
next.next = current;
current.next = temp;
}
previous = next;
next = current.next;
} else {
previous = current;
current = next;
next = next.next;
}
}
} while (wasChanged);
}
}
my problem is i only want the front node and i do not want to alter the linked list order. i tried to do this in my main.
Linky tempLinky = new Linky(); // create temp linked list
tempLinky = linky; // copy temp main linked list to temp
tempLinky.alphaBubbleSort(); // sort temp list
System.out.println(tempLinky.peek());// return object in first node
This did not seem to work. Ive tried some other code that does not work, so ive come here as a last resort.
If you need to find the first book alphabetically, there's no need to sort the entire list (and, as you commented, you don't want to alter the list's order anyway).
Instead, you could iterate over the list and keep the "first" object as you go:
public Book getFirstAlphabetically() {
Node current = head;
Book retVal = head.book;
while (current != null) {
if (current.book.getName().compareToIgnoreCase(retVal.getName()) < 0) {
retVal = current.book;
}
current = current.next;
}
return retVal;
}
Here's an example:
import java.util.Random;
class Book {
String title;
Book(String title){this.title = title;}
}
class Node {
Book b; Node next;
Node(Book b){this.b = b;}
}
public class Main {
static Book least(Node head){
if (head == null) return null;
Book least = head.b;
for(Node n=head.next; n.next!=null; n=n.next)
least = least.title.compareTo(n.b.title) > 0 ? n.b : least;
return least;
}
static void print(Node head){
for(Node n=head; n.next!=null; n=n.next)
System.out.println(n.b.title);
}
static String randString(){
Random r = new Random();
int len = r.nextInt(20)+1;
char[] chars = new char[len];
for(int i=0; i<chars.length; i++)
chars[i]= (char) (r.nextInt(26)+97);
return new String(chars);
}
public static void main(String[] args) {
Node head = new Node(new Book(randString()));
Node next = head;
for(int i = 0; i<20; i++)
next = next.next = new Node(new Book(randString()));
print(head);
System.out.println("==========");
System.out.println(least(head).title);
}
}
Related
I am trying to return all node contents that match a given String input. What I am trying to do is essentially a very simple search engine, where the user is able to type in a String and the program returns all characteristically similar contents it can find in the linked list. The linked list itself is built from a file, formatted as
<<Game’s Name 0>>\t<<Game’s Console 0>>\n
<<Game’s Name 1>>\t<<Game’s Console 1>>\n
where the lines are delimited with a \n and the game and its corresponding console are delimited with a \t.
My current methodology follows searching the linked list with a while loop, assigning a temporary value to the head and reassigning it to it's link as it goes down the list. Once the loop finds contents within a node that matches the current input, it stops the loop and returns the data found in the node. I have yet to try if this could be done with a for loop, as the while loop more than likely would not know when to continue once it has found a match. I am also unsure if the while loop argument is the most efficient one to use, as my understanding of it is very minimal. I believe !temp.equals(query) is stating "temp does not equal query," but I have a feeling that this could be done in a more efficient manner.
This is what I have so far, I will provide the entire Generic linked list class for the sake of context, but the method I am questioning is the very last one, found at line 126.
My explicitly stated question is how can I search through a linked list's contents and return those contents through the console.
import java.io.FileNotFoundException;
import java.util.Scanner;
public class GenLL<T>
{
private class ListNode
{
T data;
ListNode link;
public ListNode(T aData, ListNode aLink)
{
data = aData;
link = aLink;
}
}
private ListNode head;
private ListNode current;
private ListNode previous;
private int size;
public GenLL()
{
head = current = previous = null;
this.size = 0;
}
public void add(T aData)
{
ListNode newNode = new ListNode(aData, null);
if (head == null)
{
head = current = newNode;
this.size = 1;
return;
}
ListNode temp = head;
while (temp.link != null)
{
temp = temp.link;
}
temp.link = newNode;
this.size++;
}
public void print()
{
ListNode temp = head;
while (temp != null)
{
System.out.println(temp.data);
temp = temp.link;
}
}
public void addAfterCurrent(T aData)
{
if (current == null)
return;
ListNode newNode = new ListNode(aData, current.link);
current.link = newNode;
this.size++;
}
public T getCurrent()
{
if(current == null)
return null;
return current.data;
}
public void setCurrent(T aData)
{
if(aData == null || current == null)
return;
current.data = aData;
}
public void gotoNext()
{
if(current == null)
return;
previous = current;
current = current.link;
}
public void reset()
{
current = head;
previous = null;
}
public boolean hasMore()
{
return current != null;
}
public void removeCurrent()
{
if (current == head)
{
head = head.link;
current = head;
}
else
{
previous.link = current.link;
current = current.link;
}
if (this.size > 0)
size--;
}
public int getSize()
{
return this.size;
}
public T getAt(int index)
{
if(index < 0 || index >= size)
return null;
ListNode temp = head;
for(int i=0;i<index;i++)
temp = temp.link;
return temp.data;
}
public void setAt(int index, T aData)
{
if(index < 0 || index >= size || aData == null)
return;
ListNode temp = head;
for (int i = 0; i < index; i++)
temp = temp.link;
temp.data = aData;
}
public T search() throws FileNotFoundException {
Scanner keyboard = new Scanner(System.in);
System.out.println("Search: ");
String query = keyboard.nextLine();
ListNode temp = head;
while(!temp.equals(query))
temp = temp.link;
return temp.data;
//plus some sort of print function to display the result in the console
}
}
You can apply regex for every node's content, if the data type is string apply it if it is of some other datatype convert it into string if possible, else throw some exceptions.
In this linked list I am trying to delete a node and return the list after deleting the particular node. Here I am not using the Value to delete, I am using the position to delete that particular node. Here in my code the delete function seems to have no effect over the output. What am I doing wrong here?
import java.util.*;
class LinkedList{
Node head;
static class Node{
int data;
Node next;
Node(int d){
this.data = d;
next = null;
}
}
public LinkedList insert(LinkedList l, int data){
Node new_node = new Node(data);
if(l.head == null){
l.head = new_node;
}
else{
Node last = l.head;
while(last.next != null){
last = last.next;
}
last.next = new_node;
}
return l;
}
public LinkedList delete(LinkedList l, int position){
Node current = l.head;
if(position == 0){
current = current.next;
}
int index = 1;
while(index < position - 1){
current = current.next;
index++;
}
current = current.next.next;
Node iterating = l.head;
while(iterating != null){
System.out.print(iterating.data + " ");
iterating = iterating.next;
}
return l;
}
}
public class Main
{
public static void main(String[] args) {
LinkedList l = new LinkedList();
Scanner sc = new Scanner(System.in);
int number = sc.nextInt();
int position = sc.nextInt();
for(int i=0; i<number; i++){
int num = sc.nextInt();
l.insert(l,num);
}
l.delete(l,position);
}
}
current=current.next doesn't have any effect on the original LinkedList because with that line of code, you just change where the reference (named as current) points to.
Think about this way,
Node a = new Node()
Node b = new Node()
Node c = new Node()
a.next =b
a = c
These lines of code doesn't result in c being connected to b.
Change code to this:
if (position == 0) return l.head.next;
else {
Node head = l.head;
int index = 1;
Node itr = l.head;
while(index < position) {
itr = itr.next;
index++;
}
if(itr.next != null) itr.next = itr.next.next;
return head;
}
public LinkedList delete(LinkedList l, int position) {
Node previous = null;
Node current = l.head;
int index = 0;
while (current != null && index < position){
previous = current;
current = current.next;
index++;
}
if (current != null) {
if (previous == null) {
l.head = current.next;
} else {
previous.next = current.next;
}
}
System.out.print("[");
Node iterating = l.head;
while (iterating != null) {
System.out.print(iterating.data + ", ");
iterating = iterating.next;
}
System.out.println("]");
return l;
}
The problem in java is that to delete a node either the head must be changed to its next, or the previous node's next must be changed to current's next.
Then too current might become null, have reached the list's end, position > list length.
I am doing a linked list project for my class at school. Essentially we are supposed to make a linked list from scratch, and have add, delete, and find commands. No matter how hard I've been trying I cannot seem to get the list to display anything other than the head node. here are my classes starting from node
public class main {
public static void main(String args[]) {
for (int i = 0; i < 3; i++) {
LinkedList list = new LinkedList();
Node focus = new Node();
String start;
start = JOptionPane.showInputDialog("Enter 'A' to add an item"
+ "\n" + "Enter 'D' to delete an item\nEnter 'F' to find an item.");
if (start.equals("a") || start.equals("A")) {
focus.data = JOptionPane.showInputDialog("enter an item to ADD");
list.Add(focus);
while (focus != null) {
focus = list.head;
focus = focus.next;
JOptionPane.showMessageDialog(null, "your list is\n" + focus.getData());
}
}
}
}
}
public class Node {
String data;
Node next;
Node prev;
public Node(String data, Node next) {
this.data = data;
this.next = next;
}
Node() {
}
public void setData(String data) {
this.data = data;
}
public String getData() {
return this.data;
}
public void setNext(Node next) {//setnext
this.next = next;
}
public Node getNext() {
return next;
}
}
public class LinkedList extends Node {
Node head;
int listcount = 0;
public LinkedList() {
this.prev = null;
this.next = null;
this.listcount = 0;
}
LinkedList(Node Set) {
}
public void Add(Node n) {
Node current = this.prev;
if (current != null) {
current = this.prev;
this.prev = new Node();
} else {
head = this.prev = new Node();
current = head;
}
listcount++;
}
}
I think my biggest problem is the "your list is" part. I can't seem to get it to display anything other than the head node. I would really appreciate the help, as this has been giving me a huge headache. :)
First of all, why does your LinkedList extends the Node class? It's a linked list not a node. There's nothing coming before and after the linked list. So the linked list has no prev and next. All the elements are added in the list and the elements are inserted after the head node. The head of the node has a prev and a next. In the Add method, if the head of the list is null (i.e, the list is empty), the new element becomes the head of the list. Otherwise, the new node is inserted after the head.
public class LinkedList {
Node head;
int listcount = 0;
public LinkedList() {
this.head = null;
this.listcount = 0;
}
public void Add(Node n) {
Node current = this.head;
if (current == null) {
head = n;
} else {
Node prev = null;
while (current != null) {
prev = current;
current = current.next;
}
prev.next = n;
}
listcount++;
}
public String toString() {
StringBuilder builder = new StringBuilder();
Node current = this.head;
while (current != null) {
builder.append(current.data).append(", ");
current = current.next;
}
return builder.toString();
}
}
I added a toString method which loops over the list and builds a string with the content from each node.
In the main method there are a few problems. The linked list is initialised only once not every time you select a choice. If you initialise the linked list every time you select something, then the linked list will always be reinitialised and the only node that will contain will be the head node after you add the new element.
public class main {
public static void main(String args[]) {
String start;
boolean finished=false;
LinkedList list = new LinkedList();
while(!finished) {
start = JOptionPane.showInputDialog("Enter 'A' to add an item"
+ "\n" + "Enter 'D' to delete an item\nEnter 'F' to find an item.");
if (start.equals("a") || start.equals("A")) {
Node focus = new Node();
focus.data = JOptionPane.showInputDialog("enter an item to ADD");
list.Add(focus);
JOptionPane.showMessageDialog(null, "your list is\n" + list.toString());
}
else {
finished = true;
}
}
}
}
Try to go over the code and understand what is happening and why. Also use pencil and paper to understand the logic.
I am given two data structures of Nodes, and I am supposed to combine them into one single Node with alternating data structures. The data structures may or may not be of equal lengths.
I have already attempted this problem and I have checked over my code, but it still isn't correct. I have written other methods that I use in this one particular method, so I will post the code for those too. I came up with my method by looking at examples of how the data organization for this particular problem works.
Get the head of the Node list:
public static <E> Node<E> getHead(Node<E> current) {
Node<E> head = null;
while (current != null) {
head = current;
current = current.previous;
}
return head;
}
Get the number of Nodes in the data structure:
public static <E> int countNodes(Node<E> current) {
int count = 0;
while (current != null) {
count++;
current = current.next;
}
return count;
}
Note that I have tested these two methods (getHead and countNodes) and they have proven to be correct. I have posted them to see if they are missing something.
The Node class itself was written by my instructor and has been tested to be correctly written
public static class Node<E> {
public Node<E> next;
public Node<E> previous;
public E data;
public Node(E d) {
data = d;
}
public String toString() {
if (next == null)
return "";
return data + ", " + next.toString();
}
public boolean equals(Object o) {
Node<E> node = (Node<E>) o;
if (node == null)
return false;
Node<E> current = this;
while (current != null && node != null) {
if (!current.data.equals(node.data)) {
return false;
}
current = current.next;
node = node.next;
}
return current == null && node == null;
}
}
Finally, the method that I am having problems with: (Updated with edits)
public static <E> Node<E> combineNodes(Node<E> current, Node<E> current2) {
Node<E> newNode = null;
int currentSize = countNodes(current);
int current2Size = countNodes(current2);
int size = Math.max(currentSize, current2Size);
for (int i = 0; i < size; i++) {
if (i <= currentSize - 1) {
Node<E> node = new Node<E>(current.data);
newNode.next = node;
node.previous = newNode;
newNode = newNode.next;
current = current.next;
}
if (i <= current2Size - 1) {
Node<E> node = new Node<E>(current2.data);
newNode.next = node;
node.previous = newNode;
newNode = newNode.next;
current2 = current2.next;
}
}
return getHead(newNode);
}
Again, I have looked through the code and I feel like it should work. Is there anything that I am missing or doing wrong?
Edit
I should have included the test case that I was given. My instructor is using the JUnit test case library for the assignment. This is the test case that I have to pass:
#Test
public void combineNodesTest1() {
LinkedData.Node<String> node = makeStructure(10); // Makes a data structure of Nodes from "Fred 0" to "Fred 9"
LinkedData.Node<String> node2 = makeStructure(10);
LinkedData.Node<String> ret = new LinkedData.Node<String>("Fred 0");
ret.next = new LinkedData.Node<String>("Fred 0");
LinkedData.Node<String> r = ret.next;
for(int i = 1; i<10;i++) {
r.next = new LinkedData.Node<String>("Fred "+i);
r = r.next;
r.next = new LinkedData.Node<String>("Fred "+i);
r = r.next;
}
LinkedData.Node<String> answer = LinkedData.combineNodes(node, node2); // Method that I wrote
assertEquals(ret, answer);
}
The makeStructure() method is correctly written.
Edit 2
I have updated the code to actually link the nodes together, but it is still wrong. I'd like to know what I'm doing wrong now.
Thanks,
Steward
From my perspective, you don't change any of pointers (next, previous) in your combineNodes method. You only traverse the structure. What is missing in the first if is
newNode = current;
newNode.next = current2;
current = current.next;
and then the following in the second if
newNode = current2;
newNode.next = current;
current2 = current2.next;
I have created my own custom Linked List (code is below). Now, I can't understand how to create an array of that Linked list like LinkedList[] l = new LinkedList[10]. Can anyone help me.
class Node {
public int data;
public Node pointer;
}
class LinkedList {
Node first;
int count = 0;
public void addToEnd(int data){
if(first == null){
Node node = new Node();
node.data = data;
node.pointer = null;
first = node;
count = 1;
return;
}
Node next = first;
while(next.pointer != null){
next = (Node)next.pointer;
}
Node newNode = new Node();
newNode.data = data;
newNode.pointer = null;
next.pointer = newNode;
count++;
}
public Node getFirst(){
return first;
}
public Node getLast(){
Node next = first;
while(next.pointer != null)
next = next.pointer;
return next;
}
public int[] get(){
if(count != 0){
int arr[] = new int [count] ;
Node next = first;
int i = 0;
arr[0]= next.data;
while(next.pointer != null){
next = next.pointer;
i++;
arr[i] = next.data;
}
i++;
return arr ;
}
return null ;
}
public int count(){
return count;
}
}
I'm going to guess that your problem is just that when you create an array of objects, like
LinkedList[] lists = new LinkedList[10];
you get an array full of nulls; you need to create objects to store in the array:
for (int i=0; i<lists.length; ++i)
lists[i] = new LinkedList();