I need a circular linked list, so I am wondering if LinkedList is a circular linked list?
A quick solution to using it in a circular fashion, whenever you want to move the "next" piece in the list:
current = current.Next ?? current.List.First;
Where current is LinkedListNode<T>.
No. It is a doubly linked list, but not a circular linked list. See MSDN for details on this.
LinkedList<T> makes a good foundation for your own circular linked list, however. But it does have a definite First and Last property, and will not enumerate around these, which a proper circular linked list will.
While the public API of the LinkedList is not circular, internally it actually is. Consulting the reference source, you can see how it's implemented:
// This LinkedList is a doubly-Linked circular list.
internal LinkedListNode<T> head;
Of course, to hide the fact that it's circular, properties and methods that traverse the list make checks to prevent wrapping back to the head.
LinkedListNode:
public LinkedListNode<T> Next {
get { return next == null || next == list.head? null: next;}
}
public LinkedListNode<T> Previous {
get { return prev == null || this == list.head? null: prev;}
}
LinkedList.Enumerator:
public bool MoveNext() {
if (version != list.version) {
throw new InvalidOperationException(SR.GetString(SR.InvalidOperation_EnumFailedVersion));
}
if (node == null) {
index = list.Count + 1;
return false;
}
++index;
current = node.item;
node = node.next;
if (node == list.head) {
node = null;
}
return true;
}
If you need a circular data structure, have a look at the C5 generic collections library. They have any collection that's imaginably useful in there, including a circular queue (which might help you).
No, its not. See MSDN
Related
I'm building my own linked list in C#. I'm not asking for you to do my homework. Hopefully something can be cleared up for me though.
The simple answer may be to this sub-question:
Should a linked list contain only unique values? It's not explained anywhere, so it's odd to me that methods like Remove() and Find() exist since they search by the Node's key/value. It will always only find/remove the first instance.
e.g.,
// linkedList = {1, 1, 1, 2, 3, 4 };
linkedList.Remove(1);
// linkedList = {1, 1, 2, 3, 4 };
The Meat:
So far, all of my methods that create nodes don't return anything (per the homework). So whenever I create a node, I can't access it directly except for by value. Yet, the homework says that the InsertAfter() and InsertBefore() methods should accept a node and a key(value).
InsertAfter(node, key);
The only workaround I can think of is to use the Find() method to find a node and pass that in as the first param. It seems hacky though, and it would have to return type Node.
Should I be returning values to store nodes? Should I actually be passing in two Node.Values to the methods and not actually a whole node and a key for another one?
Here's some of my code:
Node Class
public class Node
{
public Node Next;
public object Value;
}
AddToEnd
public void AddToEnd(object value)
{
Node temp = new Node();
temp.Value = value;
if (Head.Value == null)
{
Head.Value = value;
}
else
{
Node currentNode = Head;
while (currentNode.Next != null)
{
currentNode = currentNode.Next;
}
currentNode.Next = temp;
}
}
Should a linked list contain only unique values?
No. To make it more clear you can rename Find to FindFirst or FindLast or FindAfterIndex, etc.
The only workaround I can think of is to use the Find() method to find a node and pass that in as the first param.
I would do exactly the same. However the users of the linked-list don't have to be aware of implementation details, such as there's a class called Node that carries data, and so on. Therefore, I would make a method called FindNode and make it private. Therefore the publicly accessible Find method only returns the index of (first) value found, and internally I will use the other FindNode private method to deal with insertion, and other optimised operations.
Also to avoid repeated code, I'd rewrite the Find method to call FindNode internally as well.
I'm creating a special tree algorithm and I need a bit of help with the code that I currently have, but before you take a look on it please let me explain what it really is meant to do.
I have a tree structure and I'm interacting with a node (any of the nodes in the tree(these nodes are Umbraco CMS classes)) so upon interaction I render the tree up to the top (to the root) and obtain these values in a global collection (List<Node> in this particular case). So far, it's ok, but then upon other interaction with another node I must check the list if it already contains the parents of the clicked node if it does contain every parent and it doesn't contain this node then the interaction is on the lowest level (I hope you are still with me?).
Unfortunately calling the Contains() function in Umbraco CMS doesn't check if the list already contains the values which makes the list add the same values all over again even through I added the Contains() function for the check.
Can anyone give me hand here if he has already met such a problem? I exchanged the Contains() function for the Except and Union functions, and they yield the same result - they do contain duplicates.
var currentValue = (string)CurrentPage.technologies;
List<Node> globalNodeList = new List<Node>();
string[] result = currentValue.Split(',');
foreach (var item in result)
{
var node = new Node(int.Parse(item));
if (globalNodeList.Count > 0)
{
List<Node> nodeParents = new List<Node>();
if (node.Parent != null)
{
while (node != null)
{
if (!nodeParents.Contains(node))
{
nodeParents.Add(node);
}
node = (Node)node.Parent;
}
}
else { globalNodeList.Add(node); }
if (nodeParents.Count > 0)
{
var differences = globalNodeList.Except<Node>(globalNodeList);
globalNodeList = globalNodeList.Union<Node>(differences).ToList<Node>();
}
}
else
{
if (node.Parent != null)
{
while (node != null)
{
globalNodeList.Add(node);
node = (Node)node.Parent;
}
}
else
{
globalNodeList.Add(node);
}
}
}
}
If I understand your question, you only want to see if a particular node is an ancestor of an other node. If so, just (string) check the Path property of the node. The path property is a comma separated string. No need to build the list yourself.
Just myNode.Path.Contains(",1001") will work.
Small remarks.
If you are using Umbraco 6, use the IPublishedContent instead of Node.
If you would build a list like you do, I would rather take you can provide the Umbraco helper with multiple Id's and let umbraco build the list (from cache).
For the second remark, you are able to do this:
var myList = Umbraco.Content(1001,1002,1003);
or with a array/list
var myList = Umbraco.Content(someNode.Path.Split(','));
and because you are crawling up to the root, you might need to add a .Reverse()
More information about the UmbracoHelper can be found in the documentation: http://our.umbraco.org/documentation/Reference/Querying/UmbracoHelper/
If you are using Umbraco 4 you can use #Library.NodesById(...)
I'm trying to delete a node, if x currently matches a int in my linked list.
I tried this, but once it removes the node it throws an error when examining foreach loop
public void DeleteNode(int x, LinkedList<name> myLinkedList) {
foreach (name item in myLinkedList) {
if (item.num.equals(x)) mylinkedList.Remove(x);
}
}
Hope that makes sense.
Yes, you can't iterate over a collection and modify it at the same time. However, LinkedList<T> lets you do the iteration explicitly pretty easily:
public void DeleteNode(int x, LinkedList<name> myLinkedList) {
var node = myLinkedList.First;
while (node != null) {
var nextNode = node.Next;
if (node.Value.num == x) {
myLinkedList.Remove(node);
}
node = nextNode;
}
}
Note that you can't get away with just taking node = node.Next; as the last line; the node is invalidated when it's removed.
This approach allows a single traversal of the list in O(n), and is likely to be the most efficient approach you'll find. It doesn't require any copying, or working with a collection (say List<T>) with less efficient removal complexity.
If you call remove during a foreach it will invalidate the enumerator, so this is not allowed.
Change your foreach to a simple for loop.
In this situation, I usually create a temporary collection and add it to it if it needs to be deleted. Then I loop through that list removing it from the original.
The way I write that, without invalidating the iterator, is:
foreach(var item in list.Where(w=>w.num.Equals(x)).ToArray())
list.Remove(item);
I remove Items from list in the following way:
for (int j = lst.Count - 1; j >= 0; j--)
{
var elem= lst[j];
lst.Remove(elem);
}
It looks very close to regular "foreach var elem in lst", which is the reason I like it.
I go from the end to the beginning cause otherwise you'll loose your indexing, and will need to track number of removed items.
info is a class.
This will find through linkedlist and delete the first item who's no property value is 1
LinkedList<info> infolist = new LinkedList<info>();
string todelete = "1";
info tmpitem = new info();
foreach (var item in infolist)
{
if (item.no == todelete)
tmpitem = item;
}
infolist.Remove(tmpitem);
public ListNode RemoveElements(ListNode head, int val)
{
if (head == null) return null;
head.next = RemoveElements(head.next, val);
return head.val == val ? head.next : head;
}
I have made my own single chained/linked list.
Now, if I want to delete/remove a node/item from my list, I'd have to do something like this:
public void Delete(PARAMETERS)
{
Node previousNode = null,
currentNode = f;
while (currentNode != null)
{
if (SOMECONDITION)
{
if (previousNode == null)
{
f = currentNode.Next;
}
else
{
previousNode.Next = currentNode.Next;
}
}
else
{
previousNode = currentNode;
}
currentNode = currentNode.Next;
}
}
If SOMECONDITION is true, you simply skip the currentNode and therefor effectively "deleting" the node, as nothing points to it anymore.
But, I am really wondering, why can I not do something like this:
(...)
while ()
{
if (SOMECONDITION)
{
currentNode = currentNode.Next;
}
currentNode = currentNode.Next;
}
(...)
OR perhaps:
(...)
while ()
{
if (SOMECONDITION)
{
currentNode = currentNode.Next.Next;
}
else
{
currentNode = currentNode.Next;
}
}
(...)
What fundamental understanding do I lack?
Doing:
currentNode = currentNode.Next.Next;
Is a prime candidate for a NullReferenceException
EDIT:
Here's a list implementation with some pictures that may help you understand.
http://www.csharpfriends.com/Articles/getArticle.aspx?articleID=176
There is nothing to say you can't do Next.Next.
The only issue is what if currentNode.Next is null? Then you would get an error.
PreviousNode works because you are doing a NULL check before using it.
currentNode is just a temporary pointer variable (reference) that ceases to exist at the end of the scope (that is by the next closing brace). When you change what that reference points to, you don't change any other references; changing currentNode doesn't magically change what the previous node's Next reference points to.
currentNode = currentNode.Next // only changes the temporary reference
You have to actually reach into the linked list and change a referende inside the list, which is what you do when you change previousNode.Next - you change what node the previous node considers its next node. You basically tell it "This is your new Next node, forget about the old one".
Also, as the others have stated, you should check for null references throughout. if currentNode.Next is the last node in the list, its Next will point at nothing, and you'll get a NullReferenceException.
Perhaps if you re-write the original a bit you would see better what you are really doing to the list.
public void Delete(PARAMETERS)
{
var previous = FindPreviousNode(PARAMETERS);
if( previous == null && Matches(f, PARAMETERS)) {
f = f.Next;
} else if(previous != null ) {
previous.Next = previous.Next.Next;
} // u could add "else { throw new NodeNotFound() }" if that's appropiate
}
private Node FindPreviousNode(PARAMETERS) {
Node currentNode = f;
while (currentNode != null) {
if (Matches(currentNode.Next, PARAMETERS)) {
return currentNode;
}
currentNode = currentNode.Next;
}
return null;
}
You have asked around in the comments to understand more what's up with the list and the Next's properties, so here it goes:
Lets say the list is: 1|3|5|7, first points to 1, 1's Next property points to 3, 5's Next points to 7, and 7's Next points to null. That's all you keep track of to store the list. If you set the 5's Next property to null, you are deleting the 7. If instead you set 3's Next property to 7, you are deleting the 5 from the list. If you set first to 3, you are deleting the 1.
Its all about the first and the Next properties. That's what makes the list.
The assignments to currentNode and previousNode do not alter the structure of the linked list. They're merely used to step through the structure.
The assignment to previousNode.Next is what changes the structure. Doing currentNode = currentNode.Next.Next will skip over the next node (if currentNode.Next is not null) but it won't alter the structure of the list.
You should really sketch a picture of the linked list if you're wondering about problems like this. It's far easier to see what needs to be done to accomplish some linked list mutation, than it is to reason it out.
Honestly, I don't follow the posted code at all.
If this is a standard linked list (each node has a Next, but that's it), follow these steps to run a deletion of a single item:
Step 1: Find the target node you want to delete, but keep track of the previous node visited.
Step 2: prevNode.Next = targetNode.Next
Note: special checks for deleting the head of the list need to be done.
How do you know in both cases that currentNode.Next is not null and thus that you can apply .Next on it? You are only checking for the != null in the loop condition.
I need to iterate through a LinkedList<T> (in .NET 2.0) and remove all the items according to a given criteria.
It was easy way under Java, since I could do the following:
Iterator<E> i = list.iterator();
while (i.hasNext()) {
E e = i.next();
if (e == x) {
// Found, so move it to the front,
i.remove();
list.addFirst(x);
// Return it
return x;
}
}
Unfortunately, in the .NET behavior of IEnumerator<T> (the equivalent of Iterator<E>) there's no remove method to remove the current element from the collection.
Also, in the LinkedList<T> there's no way to access an element at a given index, to accomplish the task by iterating back from the last to the first.
Have you got any idea on how to do it? Thank you very much!
This will remove all nodes that match a criteria, in one loop through the linked list.
LinkedListNode<E> node = list.First;
while (node != null)
{
var next = node.Next;
if (node.Value == x) {
list.Remove(e);
}
node = next;
}
I believe that's what you're attempting... You also added back in the node at the beginning of the list (so your java code didn't remove all of the nodes, but rather moved the first matching to the beginning of the list). That would be easy to do with this approach, as well.
It's actually a lot easier in C#.
function PlaceAtHead(<T> x)
{
list.Remove(x);
list.AddFirst(x);
return x;
}
One ugly option is to iterate through your list, find all the items that apply and store them in a list. Then iterate through your second list and call remove on your LinkedList...
I'm hoping someone else has a more elegant solution :)
Just a little addition to Reed Copsey's answer with a predicate:
public static T MoveAheadAndReturn<T>(LinkedList<T> ll, Predicate<T> pred)
{
if (ll == null)
throw new ArgumentNullException("ll");
if (pred == null)
throw new ArgumentNullException("pred");
LinkedListNode<T> node = ll.First;
T value = default(T);
while (node != null)
{
value = node.Value;
if (pred(value))
{
ll.Remove(node);
ll.AddFirst(node);
break;
}
node = node.Next;
}
return value;
}