I'm having an issue inserting a new object into a linked list. I use a custom method called Insert that takes the object type and the index where it should be placed. However, when I insert the object, the list doesn't update. Any idea why?
The list:
GenericLinkedList<string> bet = new GenericLinkedList<string>();
bet.Add("a");
bet.Add("b");
bet.Add("c");
bet.Add("d");
//bet.Remove();
bet.Insert("x", 2);
The Generic Linked List Class:
public class GenericLinkedList<T> where T : IComparable<T>
{
public GenericLinkedList()
{
count = 0;
head = null;
}
#region Nested Node Class
private class Node<T>
{
private T data;
public T Data
{
get { return data; }
set { data = value; }
}
private Node<T> next;
public Node<T> Next
{
get { return next; }
set { next = value; }
}
public Node<T> Previous { get; set; }
public Node(T obj_t)
{
next = null;
data = obj_t;
}
public Node()
{
next = null;
}
}
#endregion
private Node<T> head;
private Node<T> tail;
private int count;
public int Count
{
get
{
int num;
if (count < 0)
num = 0;
else {
num = count;
}
return num;
}
}
}
The Insert Method:
public void Insert(T data, int index)
{
Node<T> replacedItem = new Node<T>();
Node<T> newItem = new Node<T>(data);
if (head == null)
{
head = new Node<T>(data);
tail = head;
}
else
{
Node<T> current = head;
Node<T> tempNode = new Node<T>();
if (index > 0 && index <= count + 1)
{
int c = 0;
while (current != null)
{
if (c == index)
{
tempNode = current;
current = newItem;
current.Next = tempNode;
}
else
{
current = current.Next;
}
c++;
}
}
count++;
}
}
The Add Method:
public void Add(T data)
{
count++;
if (head == null)
{
head = new Node<T>(data);
tail = head;
}
else
{
tail.Next = new Node<T>(data);
tail.Next.Previous = tail;
tail = tail.Next;
}
}
Need to add count++ in case head is null. Also count++ should go inside if(index>0&&index<=count+1)
public void Insert(T data, int index)
{
Node<T> replacedItem = new Node<T>();
Node<T> newItem = new Node<T>(data);
if (head == null)
{
head = new Node<T>(data);
tail = head;
count++;
}
else
{
Node<T> current = head;
Node<T> tempNode = new Node<T>();
if (index > 0 && index <= count + 1)
{
int c = 0;
while (current != null)
{
if (c == index)
{
tempNode = current;
current = newItem;
current.Next = tempNode;
}
else
{
current = current.Next;
}
c++;
}
count++;
}
}
}
See if this helps.
You not correctly add new item in your Insert method
in this place
tempNode = current; // save pointer to current item
current = newItem; // save in current new item
current.Next = tempNode; //set next to counter
but you don't change link from previous element, so when you again go from head you just miss your added item.
You need change this code something like
public void Insert(T data, int index)
{
Node<T> replacedItem = new Node<T>();
Node<T> newItem = new Node<T>(data);
if (head == null)
{
head = new Node<T>(data);
tail = head;
count++;
}
else
{
Node<T> current = head;
Node<T> tempNode = new Node<T>();
if (index > 0 && index <= count + 1)
{
int c = 0;
while (current != null)
{
if (c == index)
{
tempNode = current;
current = newItem;
//update link from previous element
if(tempNode.Previous != null)
tempNode.Previous.Next = current;
current.Next = tempNode;
current.Previous = tempNode.Previous;
tempNode.Previous = current;
count++;
break;
}
else
{
current = current.Next;
}
c++;
}
}
}
}
Related
I've tried creating linked list/node classes and I'm not sure where to go next. My attempts haven't went well because after creating the classes I'm just not sure what the next step is.
I'm trying to create a program that has a dinosaur node which saves information about the dinosaur such as id, species etc and I want to allow the user to create and remove dinosaurs from the list. So I need to allow the user to input data, I assume there's a way to make dino id get set automatically but I'm not to sure.
I've included the LinkedList.cs and the Node.cs so you can see where I'm going but I have no idea what to do within my program class to utilise the linked list and achieve what I'm trying to do.
Added Program.cs class incase that helps identify/show where I am within the program/what I need to do.
Linked List Class:
using System;
using System.Collections.Generic;
using System.Runtime.ExceptionServices;
using System.Text;
namespace JurrasicFinal
{
public class LinkedList
{
private Node head;
private int count;
public LinkedList()
{
this.head = null;
this.count = 0;
}
public bool Empty
{
get { return this.count == 0; }
}
public int Count
{
get { return this.count; }
}
public object this[int index]
{
get { return this.Get(index); }
}
public object Add(int index, object o)
{
if (index < 0)
throw new ArgumentOutOfRangeException("Index: " + index);
if (index > count)
index = count;
Node current = this.head;
if (this.Empty || index == 0)
{
this.head = new Node(o, this.head);
}
else
{
for (int i = 0; i < index - 1; i++)
{
current = current.Next;
current.Next = new Node(o, current.Next);
}
}
count++;
return o;
}
public object Add(object o)
{
return this.Add(count, o);
}
public object Remove(int index)
{
if (index < 0)
throw new ArgumentOutOfRangeException("Index: " + index);
if (this.Empty)
return null;
if (index >= this.count)
index = count - 1;
Node current = this.head;
object result = null;
if (index == 0)
{
result = current.Data;
this.head = current.Next;
}
else
{
for (int i = 0; index < index - 1; i++) ;
current = current.Next;
result = current.Next.Data;
current.Next = current.Next.Next;
}
count--;
return result;
}
public void Clear()
{
this.head = null;
this.count = 0;
}
public int IndexOf(object o)
{
Node current = this.head;
for (int i = 0; i < this.count; i++)
{
if (current.Data.Equals(o))
return i;
current = current.Next;
}
return -1;
}
public bool Contains(object o)
{
return this.IndexOf(o) >= 0;
}
public object Get(int index)
{
if (index < 0)
throw new ArgumentOutOfRangeException("Index: " + index);
if (this.Empty)
return null;
if (index >= this.count)
index = this.count - 1;
Node current = this.head;
for (int i = 0; i < index; i++)
current = current.Next;
return current.Data;
}
}
}
Node Class:
using System;
using System.Collections.Generic;
using System.Text;
namespace JurrasicFinal
{
public class Node
{
private object data;
private Node next;
private string DinoSpecies;
private string DinoName;
public Node(object data, Node next)
{
this.data = data;
this.next = next;
}
public object Data
{
get { return this.data; }
set { this.data = value; }
}
public Node Next
{
get { return this.next; }
set { this.next = value; }
}
}
}
Program Class:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq.Expressions;
namespace JurrasicFinal
{
class Program
{
class Dinosaur
{
public string Name;
public string Classification;
public char Sex;
}
static void Main(string[] args)
{
LinkedList<Dinosaur> DinoList = new LinkedList<Dinosaur>();
Dinosaur Dino1 = new Dinosaur();
Dino1.Name = "Tyrannosaurus Rex";
Dino1.Classification = "Carnivorous";
Dino1.Sex = 'M';
Dinosaur Dino2 = new Dinosaur();
Dino2.Name = "Velociraptor";
Dino2.Classification = "Carnivorous";
Dino2.Sex = 'F';
Dinosaur Dino3 = new Dinosaur();
Dino3.Name = "Procompsognathus";
Dino3.Classification = "Carnivorous";
Dino3.Sex = 'M';
void printList()
{
Console.WriteLine("Current Queue: ");
Console.WriteLine("\n");
foreach (Dinosaur d in DinoList)
{
Console.WriteLine("Name: " + d.Name);
Console.WriteLine("Classification: " + d.Classification);
Console.WriteLine("Sex " + d.Sex);
Console.WriteLine("\n");
}
Console.WriteLine(Dino1.Name + Dino1.Sex);
}
DinoList.AddLast(Dino1);
DinoList.AddLast(Dino2);
DinoList.AddLast(Dino3);
printList();
Console.WriteLine(DinoList.Count);
FileStream fileStream = File.OpenWrite("E:/Work/Dinosaur.txt");
BinaryWriter writer = new BinaryWriter(fileStream);
foreach (Dinosaur d in DinoList)
{
writer.Write(d.Name);
writer.Write(d.Classification);
writer.Write(d.Sex);
}
writer.Close();
Console.WriteLine("Reading Back From File");
FileStream file = File.OpenRead("E:/Work/Dinosaur.txt");
BinaryReader reader = new BinaryReader(file);
for (int i = 1; i < 3; i++)
{
Dinosaur d = new Dinosaur();
d.Name = reader.ReadString();
d.Classification = reader.ReadString();
d.Sex = reader.ReadChar();
DinoList.AddLast(d);
}
reader.Close();
Console.ReadKey();
}
}
}
I think you might be looking for something like this, which hangs on user input and tries to do simple validation. I made it a bit overly complex to demonstrate some options.
class Sample
{
private static int index = 0;
static void Main(string[] args)
{
LinkedList<Dinosaur> DinoList = new LinkedList<Dinosaur>();
while (true)
{
var dino = new Dinosaur();
dino.Name = GetInput("Enter dino name (q to quit): ");
if (dino.Name == "q" || dino.Name == "Q")
{
break;
}
dino.Classification = GetInput("Enter dino classification: ");
char[] sexes = new char[] {'F', 'f', 'M', 'm'};
while (true)
{
Console.WriteLine("Enter dino sex (M/F): ");
dino.Sex = (char) Console.Read();
if (sexes.Contains(dino.Sex))
{
break;
}
}
int inputIndex = default;
while (true)
{
var indexString = GetInput($"Enter 0-index list position (max {DinoList.Count})");
inputIndex = Convert.ToInt32(indexString);
if (inputIndex <= DinoList.Count)
{
break;
}
}
DinoList.Add(inputIndex, dino);
index++;
Console.WriteLine("Dinosaurs:");
Console.WriteLine(new string('-', 30));
for (var i = 0; i < DinoList.Count; i++)
{
var dinosaur = (Dinosaur) DinoList.Get(i);
Console.WriteLine("Name: " + dinosaur.Name);
Console.WriteLine("Classification: " + dinosaur.Classification);
Console.WriteLine("Sex: " + dinosaur.Sex);
}
}
}
private static string GetInput(string prompt)
{
Console.WriteLine(prompt);
var input = Console.ReadLine();
while (string.IsNullOrWhiteSpace(input))
{
input = Console.ReadLine();
}
return input;
}
}
Note that you have to make your LinkedList and Node into LinkedList<T> and Node<T> but they converted directly, so it's just a bit of typing.
Hope it helps!
Edit: Add classes provided in question, modified to be generic.
public class Node<T>
{
private object data;
private Node<T> next;
private string DinoSpecies;
private string DinoName;
public Node(object data, Node<T> next)
{
this.data = data;
this.next = next;
}
public object Data
{
get { return this.data; }
set { this.data = value; }
}
public Node<T> Next
{
get { return this.next; }
set { this.next = value; }
}
}
public class LinkedList<T>
{
private Node<T> head;
private int count;
public LinkedList()
{
this.head = null;
this.count = 0;
}
public bool Empty
{
get { return this.count == 0; }
}
public int Count
{
get { return this.count; }
}
public object this[int index]
{
get { return this.Get(index); }
}
public object Add(int index, object o)
{
if (index < 0)
throw new ArgumentOutOfRangeException("Index: " + index);
if (index > count)
index = count;
Node<T> current = this.head;
if (this.Empty || index == 0)
{
this.head = new Node<T>(o, this.head);
}
else
{
for (int i = 0; i < index - 1; i++)
{
current = current.Next;
current.Next = new Node<T>(o, current.Next);
}
}
count++;
return o;
}
public object Add(object o)
{
return this.Add(count, o);
}
public object Remove(int index)
{
if (index < 0)
throw new ArgumentOutOfRangeException("Index: " + index);
if (this.Empty)
return null;
if (index >= this.count)
index = count - 1;
Node<T> current = this.head;
object result = null;
if (index == 0)
{
result = current.Data;
this.head = current.Next;
}
else
{
for (int i = 0; index < index - 1; i++) ;
current = current.Next;
result = current.Next.Data;
current.Next = current.Next.Next;
}
count--;
return result;
}
public void Clear()
{
this.head = null;
this.count = 0;
}
public int IndexOf(object o)
{
Node<T> current = this.head;
for (int i = 0; i < this.count; i++)
{
if (current.Data.Equals(o))
return i;
current = current.Next;
}
return -1;
}
public bool Contains(object o)
{
return this.IndexOf(o) >= 0;
}
public object Get(int index)
{
if (index < 0)
throw new ArgumentOutOfRangeException("Index: " + index);
if (this.Empty)
return null;
if (index >= this.count)
index = this.count - 1;
Node<T> current = this.head;
for (int i = 0; i < index; i++)
current = current.Next;
return current.Data;
}
}
This is my code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LinkedList
{
public class Node
{
public int data;
public Node next;
public Node(int data)
{
this.data = data;
next = null;
}
}
public class MyList
{
public Node head;
public MyList()
{
head = null;
}
public void addNode(int data)
{
if(head == null)
{
head = new Node(data);
}
else
{
Node temp = new Node(data);
Node current = head;
while(current.next != null)
{
current = current.next;
}
current.next = temp;
}
}
public void print()
{
if(head == null)
{
Console.WriteLine("List is already empty!");
}
else
{
Node current = head;
while (current != null)
{
Console.Write("|" + current.data + "|-> ");
current = current.next;
}
Console.WriteLine();
}
}
public void addToStart(int data)
{
if(head == null)
{
head = new Node(data);
}
else
{
Node temp = new Node(data);
temp.next = head;
head = temp;
}
}
public void addSorted(int data)
{
if(head == null)
{
head = new Node(data);
}
else if(data < head.data)
{
addToStart(data);
}
else
{
Node current = head.next;
Node previous = head;
Node temp = new Node(data);
while(current != null)
{
if(data < current.data)
{
previous.next = temp;
temp.next = current;
break;
}
previous = current;
current = current.next;
}
}
}
public void removeLast()
{
if(head == null)
{
Console.WriteLine("List is already empty!");
}
else if(head.next == null)
{
head = null;
}
else
{
Node current = head.next;
Node previous = head;
while(current.next != null)
{
previous = current;
current = current.next;
}
previous.next = null;
}
}
public bool isPalindrome()
{
List<int> arr1 = new List<int>();
int i = 0;
Node current = head;
while (current != null)
{
arr1.Add(current.data);
current = current.next;
i++;
}
int[] arr3 = arr1.ToArray();
int count = i;
int[] arr2 = new int[count];
int j = 0;
for (int x = i - 1; x >= 0; x--)
{
arr2[j] = arr3[x];
}
for (int k = 0; k < count; k++)
{
if (arr3[k] != arr2[k])
{
return false;
}
}
return true;
}
}
class Program
{
static void Main(string[] args)
{
MyList a = new MyList();
a.addNode(1);
a.addNode(2);
a.addNode(5);
a.addNode(2);
a.addNode(1);
a.print();
if(a.isPalindrome())
{
Console.WriteLine("Linked List is Palindrome!");
}
else
{
Console.WriteLine("Linked List is Not Palindrome!");
}
}
}
}
My code returns false for the palindrome function every time except when I enter only one value in the linked list.
Also let me know if my method of List<int> is okay or not because I needed it for the palindrome check.
Thankyou for your comments, This is how i solved it.
public bool isPalindrome()
{
int i = 0;
Node current = head;
Node temp = head;
while (temp != null)
{
temp = temp.next;
i++;
}
int[] arr1 = new int[i];
int count = i;
for (int j = 0; j < count; j++)
{
arr1[j] = current.data;
current = current.next;
}
int[] arr2 = new int[count];
int z = 0;
for (int x = i - 1; x >= 0; x--)
{
arr2[z] = arr1[x];
z++;
}
for (int x = 0; x < count; x++)
{
if (arr1[x] != arr2[x])
{
return false;
}
}
return true;
}
basically I'm having a slight problem. I just cannot seem to get this to work. I've looked everywhere. I am trying to copy the list using my Concat method
public void Concat(LinkListGen<T> list2)
{
LinkGen<T> temp = list2.list;
while (temp != null)
{
AppendItem(temp.Data);
temp = temp.Next;
}
}
Which works fine.
However, I'm just not having any luck with my Copy method:
public void Copy(LinkListGen<T> list2)
{
LinkGen<T> temp = list2.list;
while (temp != null)
{
Concat(list2);
AppendItem(list2.list.Data);
temp = temp.Next;
}
}
I know this code is probably stupid, I've just been changing the coding/experimenting and trying.
When I execute the code, nothing is displayed.
list2.AddItem(56);
list2.AddItem(88);
list2.AddItem(17);
list.AddItem(40);
list.AddItem(11);
list.AddItem(77);
list3.Copy(list2);
list3.Copy(list);
System.Console.WriteLine("Copy List" + list3.DisplayItems());
Essentially I want the output like this (may have typed the numbers in the wrong order):
Copy List 56 88 17 40 11 77
Thank you.
EDIT- I'm an idiot, forgot to the AppendItem method.
public void AppendItem(T item)
{
LinkGen<T> temp = list;
if (list == null)
{
new LinkGen<T>(item, null);
}
else
{
while (temp.Next != null)
{
temp = temp.Next;
}
temp.Next = new LinkGen<T>(item, null);
}
}
EDIT --
class LinkGen<T>
{
private T data;
private LinkGen<T> next;
public LinkGen(T item)
{
data = item;
next = null;
}
public LinkGen(T item, LinkGen<T> list)
{
data = item;
next = list;
}
public LinkGen<T> Next
{
set { this.next = value; }
get { return this.next; }
}
public T Data
{
set { this.data = value; }
get { return this.data; }
}
}
}
class LinkListGen<T> where T : IComparable
{
private LinkGen<T> list;
public LinkListGen()
{
this.list = null;
}
public void AddItem(T item)
{
list = new LinkGen<T>(item, list);
}
public string DisplayItems() //write items to string and return
{
LinkGen<T> temp = list;
string buffer = "";
while (temp != null) // move one link and add head to the buffer
{
buffer += temp.Data + "";
temp = temp.Next;
}
return buffer;
}
public int NumberOfItems() // returns number of items in list
{
LinkGen<T> temp = list;
int count = 0;
while (temp != null) // move one link and add 1 to count
{
count++;
temp = temp.Next;
}
return count;
}
public void RemoveItem(int item)
{
LinkGen<T> current = list;
LinkGen<T> previous = null;
while (current != null)
{
if (current.Data.Equals(item))
{
if (previous != null)
{
previous.Next = current.Next;
current = current.Next;
}
else
{
previous = current;
current = current.Next;
list = current;
}
}
else
previous = current;
current = previous.Next;
}
}
public void InsertInOrder(T item)
{
LinkGen<T> temp = list;
if (list == null || list.Data.CompareTo(item) < 0)
{
list = new LinkGen<T>(item, this.list);
}
else
{
while (temp != null)
{
if (list.Data.CompareTo(item) == 0 || list.Data.CompareTo(item) > 0)
{
temp.Next = new LinkGen<T>(item, temp.Next);
temp = null;
}
else
{
temp = temp.Next;
}
}
}
}
public void AppendItem(T item)
{
LinkGen<T> temp = list;
if (list == null)
{
new LinkGen<T>(item, null);
}
else
{
while (temp.Next != null)
{
temp = temp.Next;
}
temp.Next = new LinkGen<T>(item, null);
}
}
public void Concat(LinkListGen<T> list2)
{
LinkGen<T> temp = list2.list;
while (temp != null)
{
AppendItem(temp.Data);
temp = temp.Next;
}
}
Suggested correction
class LinkListGen<T> where T : IComparable
{
private LinkGen<T> list;
public LinkListGen() { }
private LinkGen<T> LastNode ()
{
var temp = list;
while (temp != null && temp.Next != null)
temp = temp.Next;
return temp;
}
public void AppendItem(T item)
{
if (list == null)
list = new LinkGen<T>(item, null);
else
{
LinkGen<T> temp = LastNode();
temp.Next = new LinkGen<T>(item, null);
}
}
public void Concat(LinkListGen<T> list2)
{
if (list2 == null)
return;
LinkGen<T> temp = list2.list;
while (temp != null)
{
AppendItem(temp.Data);
temp = temp.Next;
}
}
public void Copy(LinkListGen<T> list2)
{
Concat(list2);
}
class LinkGen<T2>
{
public LinkGen(T2 item): this(item, null) { }
public LinkGen(T2 item, LinkGen<T2> list)
{
Data = item;
Next = list;
}
public LinkGen<T2> Next { set; get; }
public T2 Data { set ; get ; }
}
}
Answer-
public void Copy(LinkListGen<T> list2)
{
LinkGen<T> temp = list2.list;
while (temp != null)
{
AppendItem(temp.Data);
temp = temp.Next;
}
}
If anyone ever has the same problem I had. They're finally a solution. Yes, I know.... I'm an idiot!
class IntNode
{
public int value { get; set; }
public IntNode next { get; set; }
public IntNode(int value)
{
this.value = value;
this.next = null;
}
public IntNode(int value, IntNode next)
{
this.value = value;
this.next = next;
}
public bool HasNext()
{
return (next != null);
}
public override string ToString()
{
if (this.HasNext())
return value + "-->" + next;
else
return value + "";
}
}
so if I wanted to remove the 4th node with given list starts with head:
IntNode pos = head.next;
IntNode prev = head;
int counter = 0;
while (pos != null)
{
if (counter == 4) prev.next = pos.next;
prev = pos;
pos = pos.next;
}
But I want to remove the first node (when counter is 0). How can I do this? Thanks.
Something like this should do it for you:
while (pos != null)
{
if ( counter == 0 )
{
head = head.next;
prev = head;
}
else
{
prev.next = pos.next;
}
}
public void Remove(int index) {
if(head != null)
{
if(index == 0)
{
head = head.next;
}
else
{
IntNode pos = head.next;
IntNode prev = head;
while (pos != null)
{
--index;
if (index == 0)
{
prev.next = pos.next;
break;
}
prev = pos;
pos = pos.next;
}
}
}
}
I'm new at this and trying to write this code for a queue but it doesn't work. I'm stuck, I wrote queue for a linked list and I can't find where I'm wrong here, any help is great. Thank you in advance.
class Queue
{
public Node<T> head { get; set; }
public Node<T> tail { get; set; }
public int size { get; set; }
public Queue()
{
head = null;
tail = null;
}
public void Enqueue(T value)
{
if (head == null)
{
head = new Node<T>(value);
tail = head;
}
else
{
tail.sljedeci = new Node<T>(value);
tail = tail.next;
}
size++;
}
public T Dequeue()
{
if (size == 0)
{
throw new IndexOutOfRangeException();
}
else if (size == 1)
{
T value = head.value;
size--;
head = tail = null;
return value;
}
else
{
T value = head.value;
head = head.next;
size--;
return value;
}
}
public void Peek()
{
if (size == 0)
{
Console.WriteLine("List is empty");
}
else
{
Node<T> temp = head;
Console.Write("{ ");
while (temp.next != null)
{
Console.Write("{0}, ", temp.value);
temp = temp.next;
}
Console.Write(temp.valuet + " }");
}
}