c# insert item in order custom linked list - c#

im trying to add the number 8 into my list using the InsertInOrder method
e.g. my current list 5, 10, 12, 14, 26, 45, 52
after inserting new node 5, 8, 10, 12, 14, 26, 45, 52
i know i have to iterate through the list in order to find the correct position for it
but where do i start?
class LinkList
{
private Link list = null; //default value – empty list
public void AddItem(int item) //add item to front of list
{
list = new Link(item, list);
}
public void InsertInOrder(int item)
{
Link temp = list;
while (temp != null)
{
AddItem(item);
Console.WriteLine(temp.Data);
temp = temp.Next;
}
}
public void DisplayItems() // Displays items in list
{
Link temp = list;
while (temp != null)
{
Console.WriteLine(temp.Data);
temp = temp.Next;
}
}
Link class:
class Link
{
private int data;
private Link next;
public Link(int item) //constructor with an item
{
data = item;
next = null;
}
public Link(int item, Link list) //constructor with item and list
{
data = item;
next = list;
}
public int Data //property for data
{
set { this.data = value; }
get { return this.data; }
}
public Link Next //property for next
{
set { this.next = value; }
get { return this.next; }
}
}
}

Your code looks pretty clean. I'm not going to post a full solution for you but I will give you a skeleton out line of how you could implement InsertInOrder. Note that there are many ways to do this. All you have to do is fill in the if conditions.
public void InsertInOrder(int item)
{
Link temp = list;
// check to see if the item goes at the front of the list...
// hint : there are 2 conditions where it needs to go in the front.
if (********* || **********)
{
list = new Link(item, list);
}
else
{
while (temp != null)
{
// you have to look at the next item and see if it's bigger
// which means it goes next.
// if there isn't a next item this item belongs next.
if (*********** || // there is no next item
***********) // this item is bigger than the next item
{
temp.Next = new Link(item, temp.Next);
// we are done so set temp to null so we exit the loop
temp = null;
}
else
{
// move on to the next item
temp = temp.Next;
}
}
}
}

Related

How do I fix this bug: Cant remove object from a list?

I have this really weird bug where I cannot seem to delete an object from a list. I am using an Injector class to pass the same object(thus the same list) around into multiple forms. The Delete() function is just a generic delete, really nothing special. However in my unit test it keeps failing and I'm unsure why.
Injector class:
[Serializable]
public class InjectorClass
{
public OrderAdministration Administration { get; private set; }
public WareHouse WareHouse { get; private set; }
public InjectorClass()
{
Administration = new OrderAdministration(this);
WareHouse= new WareHouse();
}
}
Constructor of the WareHouse class:
public List<Part> Catalogus { get; private set; }
public List<Part> PartsInStock { get; private set; }
public WareHouse()
{
PartsInStock = new List<Part>();
AddStandardStockToCatalogus();
AddStockPartsToStock();
}
private void AddStandardStockToCatalogus()
{
Body body1 = new Body("Body7zk", 1, "Ebony", "Blue");
Body body2 = new Body("SuperXtrem368", 2, "Maple", "Red");
Neck neck1 = new Neck("Heavy-Slider", 3, "Juniper", true);
Neck neck2 = new Neck("SlickFingerBoard", 4, "Oak", false);
Fretboard fretboard1 = new Fretboard("PrettySlamFinger", 5, "Oak", false);
Fretboard fretboard2 = new Fretboard("GentleToucher", 6, "Ebony", true);
Pickups pickups1 = new Pickups("TubeScreamers", 7, Pickups.PickupType.P90);
Pickups pickups2 = new Pickups("BluesBrothers", 8, Pickups.PickupType.Humbucker);
Bridge bridge1 = new Bridge("MetalGearRipper", 9, false);
Bridge bridge2 = new Bridge("BridgeOfLove", 10, true);
Catalogus = new List<Part> { body1, body2, neck1, neck2, fretboard1, fretboard2, pickups1, pickups2, bridge1, bridge2};
}
private void AddStockPartsToStock()
{
foreach(Part p in Catalogus)
{
PartsInStock.Add(p);
}
}
The Delete() function in the same Warehouse class:
public int GetStock(Part neededPart)
{
if(neededPart == null)
{
throw new ArgumentNullException();
}
int numberInStock = 0;
foreach(Part p in PartsInStock)
{
if(p.Id == neededPart.Id)
{
numberInStock++;
}
}
return numberInStock;
}
public bool AddToStock(Part arrivedPart)
{
if(arrivedPart == null)
{
throw new ArgumentNullException();
}
if(FindByName(arrivedPart.Name).Name == arrivedPart.Name)
{
PartsInStock.Add(arrivedPart);
return true;
}
return false;
}
public bool RemovePart(Part usedPart)
{
if (GetStock(usedPart) >= 1)
{
PartsInStock.Remove(usedPart);
return true;
}
return false;
}
The unit test I run:
Neck neck1 = new Neck("Heavy-Slider", 3, "Juniper", true);
InjectorClass injector = new InjectorClass();
Assert.AreEqual(10, injector.WareHouse.PartsInStock.Count);
injector.WareHouse.RemovePart(neck1);
Assert.AreEqual(9, injector.WareHouse.PartsInStock.Count);
The output on both the assert functions is 10
Edit:
I have re-written my search and delete function to the following:
Search function:
public Part FindByNameStock(Part neededPart)
{
if (neededPart == null)
{
throw new ArgumentNullException();
}
foreach (Part p in PartsInStock)
{
if (p.Name == neededPart.Name)
{
return p;
}
}
return null;
}
Delete function:
public bool RemovePart(Part usedPart)
{
Part part = FindByNameStock(usedPart);
if (part != null)
{
PartsInStock.Remove(part);
return true;
}
return false;
}
The code now works and the unit test too.
This line PartsInStock.Remove(usedPart); will try to remove the following object
new Neck("Heavy-Slider", 3, "Juniper", true);
which is not in your list. The reason is that reference type equality is not based on the properties, but on the actual reference. Whenever you run new a new reference is created.
var neck1 = new Neck("Heavy-Slider", 3, "Juniper", true);
var neck2 = new Neck("Heavy-Slider", 3, "Juniper", true);
Console.WriteLine(neck1 == neck2); //This is false
Check the code here for an example: https://dotnetfiddle.net/7gAWID
Check here for the IEquatable implementation that will make your code work.
Two separate objects of Neck although having the same ID are different objects and hence the item is never removed.
Moreover, you can return the value of List.Remove as it also returns a bool if an item was actually removed. So if no item was removed, it returns false:
public bool RemovePart(Part usedPart)
=> GetStock(usedPart) >= 1 ?
PartsInStock.Remove(usedPart);
: false;
Use RemoveAll() to remove the item by ID. RemoveAll() returns an int representing the number of items removed:
public bool RemovePart(Part usedPart)
{
if (GetStock(usedPart) >= 1)
{
PartsInStock.RemoveAll(part => part.Id == usedPart.Id);
return true;
}
return false;
}
Also, since your RemovePart returns a bool. You can add a check to ensure if it was removed.
if (injector.WareHouse.RemovePart(neck1))
{
Assert.AreEqual(9, injector.WareHouse.PartsInStock.Count);
}
GetStock uses the Id of the part to find it, whereas PartsInStock.Remove tries to remove the part by reference - and the reference you have is different to the item in the collection you're trying to remove from.
public bool RemovePart(Part usedPart)
{
if (GetStock(usedPart) >= 1) // item is found here
{
PartsInStock.Remove(usedPart); // but usedPart is a different reference - nothing is removed
return true;
}
return false;
}

I'm struggling to get a foreach loop working to loop through each element of a LinkedList

Im trying to do a Depth first traversal on graph node but I cant get my for each loop to loop correctly
Here is the code for doing the search
The foreach line is the problem
public void DepthFirstTraverse(T startID, ref List<T> visited)
{
LinkedList<T> adj;
Stack<T> toVisit = new Stack<T>();
GraphNode<T> current = new GraphNode<T>(startID);
toVisit.Push(startID);
while (toVisit.Count != 0)
{
current.ID = toVisit.Peek();
toVisit.Pop();
visited.Add(current.ID);
Console.WriteLine(current.GetAdjList());
foreach(T n in current.GetAdjList())
{
Console.WriteLine("Loop working");
if(toVisit.Contains(n)==false && visited.Contains(n)==true)
{
toVisit.Push(n);
}
}
}
}
Here is the graphnode code, it calls the getadjlist and should loop through for each element in that list, currently it doesnt loop at all
public class GraphNode
{
private T id; // data stored in the node (“id” of the node).
private LinkedList adjList; // adjacent list of the node
// constructor
public GraphNode(T id)
{
this.id = id;
adjList = new LinkedList<T>();
}
// set and get the data stored in the node
public T ID
{
set { id = value; }
get { return id; }
}
//add a directed edge from “this” node to the node "to”
public void AddEdge(GraphNode<T> to)
{
adjList.AddFirst(to.ID);
}
// returns the adjacent list of the node
public LinkedList<T> GetAdjList()
{
return adjList;
}
}

Simple List Merge C# (Without Generics)

I have created a simple list class from scratch. This is for a class assignment that I have been working on for about a week - very new to lists. We can not use generics so trying to research my question below has not been fruitful. Although I did get to watch 7 tutorials on youtube by BetterCoder and I found some stuff in my book but nothing with an example of "merging".
I have three classes - my node, my list, and my program. In my list class, I am working on building a Merge() method which eventually will compare the data in the two lists and merge them into an ordered list.
Right now for some reason my Merge method - which is very basic to help me understand what is happening - is not working correctly. It has both lists passed to it, and is adding the data from listTwo to listOne BUT for some reason when it's printing to the console the second Node's Data shows twice :
EX: 1 -> 2 -> 2
instead of printing the head (1), the next (2) and then the next (3) which it should be.
EX: 1 -> 2 -> 3
In the program class I have proven with a write line that (listOne.firstNode.Next.Next.Data) = 3 . Which it should be.
Can someone help me figure out if the nodes in list one aren't pointing to each other correctly or whatever is going on?
My Merge Method must be passed both list objects (listOne and listTwo) and eventually I need to make those passed as references but I haven't figured that out quite yet and will focus on that later I suppose.
namespace LinkedList
{
//This is my Node Class
class Node
{
public object Data { get; set; }
public Node Next { get; set; }
public Node(object dataValue) : this(dataValue, null) { }
public Node(object dataValue, Node nextNode)
{
Data = dataValue;
Next = nextNode;
}
}
//This is my List Class
class List
{
public Node firstNode;
public int count;
public List()
{
firstNode = null;
}
public bool Empty
{
get { return this.count == 0; }
}
public int Count
{
get { return this.count; }
}
public object Add(int index, object o)
{
if (index < 0)
throw new ArgumentOutOfRangeException("Index: " + index);
if (index > count)
index = count;
Node current = this.firstNode;
if (this.Empty || index == 0)
{
this.firstNode = new Node(o, this.firstNode);
}
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 Merge(List a, List b)
{
a.Add(b.firstNode.Data);
return a;
}
public void Print()
{
while (this.count > 0)
{
Console.Write(firstNode.Data + "->");
if(firstNode.Next != null)
firstNode.Data = firstNode.Next.Data;
count--;
}
}
}
//And here is my Program
class Program
{
static void Main(string[] args)
{
List listOne = new List();
List listTwo = new List();
listOne.Add(1);
listOne.Add(2);
listTwo.Add(3);
listTwo.Print();
Console.WriteLine("");
listOne.Merge(listOne, listTwo);
Console.WriteLine("");
listOne.Print();
//This line below shows that the data "3" from listTwo is being added to listOne in the list Merge Method
//Console.WriteLine(listOne.firstNode.Next.Next.Data);
Console.ReadKey();
}
}
}
Actual problem in your print method
public void Print()
{
Node node = firstNode;
for (int i = 0; i < this.count; i++)
{
Console.Write(node.Data + "->");
if (node.Next != null)
node = node.Next;
}
}
Alex Sikilinda , you are right the merge method is incomplete.
public object Merge(List a, List b)
{
Node bNode = b.firstNode;
while (bNode != null)
{
a.Add(bNode.Data);
bNode = bNode.Next;
}
return a;
}
I would write it this way:
public void Merge(List b)
{
Node lastNode = GetLastNode();
if (lastNode != null)
{
lastNode.Next = b.firstNode;
}
else
{
this.firstNode = b.firstNode;
}
}
// this method is used to find the last node in current list
private Node GetLastNode()
{
if (this.firstNode == null)
{
return null;
}
Node current = this.firstNode;
while (current.Next != null)
{
current = current.Next;
}
return current;
}
First of all, I changed signature of Merge from public object Merge(List a, List b) to public void Merge(List b). Now we can use it like this:
listOne.Merge(listTwo);
This will link listOne's last element with the first element of listTwo and thus they are merged.
Now we need to change Print method since current version modifies the list, which shouldn't happen:
public void Print()
{
Node currentNode = this.firstNode;
while(currentNode != null)
{
Console.Write(currentNode.Data + ' ');
currentNode = currentNode.Next;
}
}
Instead of assigning the data back to first node I assign the
firstNode = firstNode.Next;
Please check the below Print Code
public void Print()
{
while (this.count > 0)
{
Console.Write(firstNode.Data + "->");
if (firstNode.Next != null)
firstNode = firstNode.Next;
count--;
}
}

Why does the method List.Add isn't working?

I have a game developed with unity, this is the code of a button. It should take the public List of the script "BoardScript" and add a number to this list, but, for some reason it isn't working.
I have checked that the Button click is working (as you can see, in the code the debug.log yes prints), but clicking it is not adding the number to my list.
In the "BoardScript" I added some numbers just to try, and the value adds to the list successfully, so, I guess that the error is somewhere in this script, but I can't figure what can be wrong.
Can you please help me?
private Button B;
void Start()
{
B = GetComponent<Button>();
B.onClick.AddListener(Clicker);
}
void Clicker()
{
BoardScript boardScript = new BoardScript();
int Two = 2;
boardScript.UserList.Add(Two);
Debug.Log("Added);
}
// Update is called once
EDIT
I almost forgot to tell a detail. I have write Debug.Log(UserList.Count) and The value is 1, even if I added 1 several times as the button script suggests (Its the same script but with different object).
So, As Steve Said This is the BoardScript code, it is a little long.
private int[] PreList = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
private List<int> ButtonList = new List<int>();
public List<int> UserList = new List<int>();
private System.Random Rnd = new System.Random();
public List<int> EndList = new List<int>();
void Randomizer()
{
PreList = PreList.OrderBy(C => Rnd.Next()).ToArray();
foreach (var item in PreList)
{
Debug.Log(item.ToString());
if (item == 1)
{
OneMethod();
}
if (item == 2)
{
TwoMethod();
}
if (item == 3)
{
ThreeMethod();
}
if (item == 4)
{
FourMethod();
}
if (item == 5)
{
FiveMethod();
}
if (item == 6)
{
SixMethod();
}
if (item == 7)
{
SevenMethod();
}
if (item == 8)
{
EightMethod();
}
if (item == 9)
{
NineMethod();
}
}
EndList = PreList.ToList();
}
void OneMethod()
{
//yield return new WaitForSeconds(1);
ButtonList.Add(1);
}
void TwoMethod()
{
ButtonList.Add(2);
}
void ThreeMethod()
{
ButtonList.Add(3);
}
void FourMethod()
{
ButtonList.Add(4);
}
void FiveMethod()
{
ButtonList.Add(5);
}
void SixMethod()
{
ButtonList.Add(6);
}
void SevenMethod()
{
ButtonList.Add(7);
}
void EightMethod()
{
ButtonList.Add(8);
}
void NineMethod()
{
ButtonList.Add(9);
}
void Start ()
{
Randomizer();
string[] the_array = ButtonList.Select(i => i.ToString()).ToArray();
string OrderString = string.Join(", ", the_array);
GameObject.Find("Order").GetComponent<Text>().text = OrderString;
UserList.Add(1);
UserList.Add(5);
}
IEnumerator Waiter()
{
yield return new WaitForSeconds(10);
}
// Update is called once per frame
void Update()
{
string[] the_array = UserList.Select(i => i.ToString()).ToArray();
string OrderString = string.Join(", ", the_array);
Debug.Log(OrderString);
if (UserList.Count == 8)
{
if (UserList == ButtonList)
{
//Sound
BehaviourModel B = new BehaviourModel();
B.Counter++;
if (B.Counter < 10)
{
SceneManager.LoadScene(B.SceneArray[B.Counter]);
}
else if (B.Counter > 10)
{
SceneManager.LoadScene("MainMenuScene");
}
}
else if (UserList != ButtonList)
{
UserList.Clear();
Debug.Log("Fail");
}
}
}
Each time you click the button you create a new instance of BoardScript. You should store the boardScript variable as a variable in your class or separate component to ensure the data will persist.
You can do either create only one Instance, like:
private Button B;
BoardScript boardScript = new BoardScript();
then in your void Clicker() method:
add item to UserList.
Or:
You can create a static variable in your BoardScript class and check for null. If its null, then create a new instance else return an old instance.
The following code will help:
private static BoardScript _uniqueBoardScript;
private BoardScript()
{}
public static BoardScript GetInstance()
{
if(_uniqueBoardScript==null)
{
_uniqueBoardScript = new BoardScript();
}
return _uniqueBoardScript;
}
and from your void Clicker()
{
BoardScript boardScript = BoardScript.GetInstance();
int Two = 2;
boardScript.UserList.Add(Two);
Debug.Log("Added);
}

Linked List remove item

Ive got to remove an item from my list using the 'RemoveItem' method. However, im a little stuck, can anyone give me a prod in the right direction :D
any help would be highly appreciated
main:
class Program
{
static void Main(string[] args)
{
LinkList testList = new LinkList();
testList.AddItem(5);
testList.AddItem(10);
testList.AddItem(12);
testList.AddItem(14);
testList.DisplayItems();
Console.WriteLine(testlist.RemoveItem(5));/// remove the item 5 from list
Console.ReadKey();
}
}
link class:
class Link
{
private int data;
private Link next;
public Link(int item) //constructor with an item
{
data = item;
next = null;
}
public Link(int item, Link list) //constructor with item and list
{
data = item;
next = list;
}
public int Data //property for data
{
set { this.data = value; }
get { return this.data; }
}
public Link Next //property for next
{
set { this.next = value; }
get { return this.next; }
}
}
}
linklist class:
class LinkList
{
private Link list = null; //default value – empty list
public void AddItem(int item) //add item to front of list
{
list = new Link(item, list);
}
public void RemoveItem(int item)// remove chosen item from list
{
Link temp = list;
while (temp != null)
{
//
}
public void DisplayItems() // Displays items in list
{
Link temp = list;
while (temp != null)
{
Console.WriteLine(temp.Data);
temp = temp.Next;
}
}
There are two ways:
To take value and delete it
Just delete it
First decide what you need.
Describe idea with words for yourself. What does it mean to delete item?
find item
delete item
correct links: item before deleted item have to be linked with item after deleted
Example
A->B->C->D->E
Delete C: find C, make link between B and D to get
A->B->D->E
Before trying to connect nodes, first check if they exists :)

Categories