I am trying to delete a Node from a linked list. Below is the code I have tried.
public class Node : IDisposable
{
public int Value { get; set; }
public Node Next { get; set; }
public Node(int value)
{
this.Value = value;
}
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
Next.Dispose();
}
}
}
public class LinkedList
{
Node head;
public void CreateList()
{
Node node1 = new Node(1);
Node node2 = new Node(2);
Node node3 = new Node(3);
head = node1;
node1.Next = node2;
node2.Next = node3;
}
public void DeleteLastItem()
{
Node prevNode = head;
Node nextNode = head;
while (nextNode.Next != null)
{
prevNode = nextNode;
nextNode = nextNode.Next;
}
prevNode.Next = null;
nextNode.Dispose();
}
}
I wanted to dispose the nextNode (which is nothing but the last node. And it will not be part of the Linked List).
When I try above code, I am getting below exception:
Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object.
How can I proceed here ? How can I dispose a Node object?
In your Dispose(bool) method, you can only dispose the next node if there is one. Check for a null reference before you attempt that:
protected virtual void Dispose(bool disposing) {
if (disposing) {
if (Next != null) {
Next.Dispose();
}
}
}
I guess you should simply check if Next is not null before calling Dispose on it.
When the Dispose method is called on any node, you manually call the next one so one you will reach the last one, the Next property will be null therefore you get this exception.
Considering the code you gave, I don't see why you would need your node to be disposable. It is only necessary if you use non managed resources which is not the case in the code you gave (but maybe you simplified it for the question).
In your Dispose logic, check for NULL:
public class Node : IDisposable
{
public int Value { get; set; }
public Node Next { get; set; }
public Node(int value)
{
this.Value = value;
}
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (Next != null) // <-- new code here
{
Next.Dispose();
}
}
}
}
Related
I am learning Data Structure. Today, I wanted to implement Queue using Linked List. As we have FRONT and REAR first index of the entry point of the Queue. If someone asks me to implement a Queue with Linked List, please confirm my below implementation (I am able to achieve the Queue objective without the REAR object.)
Is this implementation valid?
class Queue
{
Node head;
class Node
{
public int Value;
public Node next;
public Node()
{
next = null;
}
}
public void addElement(int val)
{
if (head == null)
{
Node temp = new Node();
temp.Value = val;
head = temp;
return;
}
Node tempNode = head;
while (tempNode.next != null)
{
tempNode = tempNode.next;
}
Node newElement = new Node();
newElement.Value = val;
tempNode.next = newElement;
}
public void Dequeue()
{
if (head != null)
{
if (head.next != null)
{
head = head.next;
return;
}
head = null;
}
}
}
class Program
{
static void Main(string[] args)
{
Queue queue = new Queue();
queue.addElement(10);
queue.addElement(20);
queue.addElement(30);
queue.addElement(40);
queue.Dequeue();
queue.Dequeue();
queue.Dequeue();
queue.Dequeue();
}
}
Well, if we want to have front and rear ends, let's have them:
private Node m_Head;
private Node m_Tail;
You have just one Node head; field and that's why your implementation at least inefficient: you have O(N) time complexity to addElement:
...
while (tempNode.next != null)
{
tempNode = tempNode.next;
}
...
When you can easily have O(1)
I suggest using typical names like Enqueue instead of addElement and have Try methods (often, we don't want exceptions if queue is empty). Finally, let's use generics: MyQueue<T> where T is item's type.
public class MyQueue<T> {
private class Node {
public Node(Node next, T value) {
Next = next;
Value = value;
}
public Node Next { get; internal set; }
public T Value { get; }
}
private Node m_Head;
private Node m_Tail;
public void Enqueue(T item) {
Node node = new Node(null, item);
if (m_Tail == null) {
m_Head = node;
m_Tail = node;
}
else {
m_Tail.Next = node;
m_Tail = node;
}
}
public bool TryPeek(out T item) {
if (m_Head == null) {
item = default(T);
return false;
}
item = m_Head.Value;
return true;
}
public T Peek() {
if (m_Head == null)
throw new InvalidOperationException("Queue is empty.");
return m_Head.Value;
}
public bool TryDequeue(out T item) {
if (m_Head == null) {
item = default(T);
return false;
}
item = m_Head.Value;
m_Head = m_Head.Next;
return true;
}
public T Dequeue() {
if (m_Head == null)
throw new InvalidOperationException("Queue is empty.");
T item = m_Head.Value;
m_Head = m_Head.Next;
return item;
}
}
This is my code for a binary tree program I am doing for an algorithms class. I keep getting a null exception error thrown, but I have no clue what's causing it.
namespace Tree
{
class CallTree
{
static void Main(string[] args)
{
BNode HE = new BNode(0, "House Entrance");
BNode LowerHallway = new BNode(0, "Lower Hallway");
BNode UpperHallway = new BNode(0, "Upper Hallway");
HE.setLeft(LowerHallway);
HE.setRight(UpperHallway);
BNode Lounge = new BNode(0, "Lounge");
BNode Kitchen = new BNode(0, "Kitchen");
LowerHallway.setLeft(Lounge);
LowerHallway.setRight(Kitchen);
BNode Balcony = new BNode(0, "Balcony");
Kitchen.setRight(Balcony);
BNode Study = new BNode(0, "Study");
BNode MasterBedroom = new BNode(0, "Master Bedroom");
UpperHallway.setLeft(Study);
UpperHallway.setRight(MasterBedroom);
BNode GuestBath = new BNode(0, "Guest Bath");
BNode GuestBedroom = new BNode(0, "Guest Bedroom");
Study.setLeft(GuestBath);
Study.setRight(GuestBedroom);
BNode PrivateBath = new BNode(0, "Private Bath");
BNode Closet = new BNode(0, "Closet");
MasterBedroom.setLeft(PrivateBath);
MasterBedroom.setRight(Closet);
HBinaryTree HBinaryTree = new HBinaryTree(HE);
BNode rootNode = HBinaryTree.GetRoot();
I get an exception for 'rootNode' here V
HBinaryTree.preOrder(rootNode);
//HBinaryTree.inOrder(rootNode);
//HBinaryTree.postOrder(rootNode);
Console.ReadKey();
}
}
//definition of node in a binary tree
public class BNode
{
public string room;
public int treasure;
public BNode left, right;//left child and right child
public BNode(int item, string room)
{
treasure = item;
left = null;
right = null;
}
public BNode(int item, string room, BNode leftNode, BNode rightNode)
{
treasure = item;
left = leftNode;
right = rightNode;
}
public void show()
{
Console.Write(treasure);
}
//Is it interial node?
public bool isInner()
{
return left != null || right != null;
}
//Is it a leaf node?
public bool isLeaf()
{
return left == null && right == null;
}
//Does it have a left child?
public bool hasLeft()
{
return left != null;
}
//Does it have a right child?
public bool hasRight()
{
return right != null;
}
//Set its left child to be newLeft
public void setLeft(BNode newLeft)
{
left = newLeft;
}
//Set its right child to be newRight
public void setRight(BNode newRight)
{
right = newRight;
}
//return data value
public int getValue()
{
return treasure;
}
//set data value
public void setValue(int newValue)
{
treasure = newValue;
}
}
//definition of a proper binary tree
class HBinaryTree
{
public BNode root; //root of the tree
public HBinaryTree()
{
root = null;
}
public BNode GetRoot()
{
return root;
}
public HBinaryTree(BNode rootNode) // constructor
{
root = rootNode;
}
// PreOrder traversal
public void preOrder(BNode root)
{
And more exception errors for 'root' in these 4 lines V
root.show();
if (root.isInner())
{
preOrder(root.left);
preOrder(root.right);
}
}
//// InOrder traversal
//public void inOrder(BNode root)
//{
// if (root.isInner())
// {
// inOrder(root.left);
// }
// root.show();
// if (root.isInner())
// {
// inOrder(root.right);
// }
//}
//PostOrder traversal
//public void postOrder(BNode root)
//{
// if (root.isInner())
// {
// postOrder(root.left);
// postOrder(root.right);
// }
// root.show();
//}
}
}
I would like it if someone could help me deduce what is causing the exceptions for 'root' and 'rootNode' to be thrown. It states they are null but I can't understand why it states that.
Your preOrder function recursively calls itself for the left and right nodes off every node in your tree if isInner returns true. isInner returns true if either of its nodes are non-null, but your kitchen has only a right branch, and its left is null. So when that function reaches the kitchen, it sees isInner is true and it calls itself with the left branch off kitchen which is null. You need to check for null for left and right individually.
I have a class:
public class A
{
private IB link;
public IB Link
{
get { return link; }
set
{
link = value;
b.Link = this;
}
}
...
}
and an interface:
public interface IB
{
A Link { get; set; }
}
I will use it like this:
public class B1 : IB, Button
{
public A Link { get; set; }
...
}
public class B2 : IB, TextBox
{
public A Link { get; set; }
...
}
b1 = new B1();
b2 = new B2();
A a = new A();
a.Link = b1;
...
a.Link = b2;
But I have to encapsulate the IB.Link property, it should changed only in the A class (along with the A.Link property). Is this possible?
Update:
Sorry for ambiguity of this example. My real code is too large and not finished: I have a structure of nodes. Each node has a link to Control. So, visual structure of controls can be constructed. We can manage the controls from nodes, but not get access to node from control, for example, from OnMouseClick method. We need have back reference - the IMyControl.OwnerNode property. IMyControl is interface that contains only this property. So, we can create "MyControl : IMyControl, Control" class and implement into it mouse click logic. When we assign control to node, both references must be created, direct and back, but it take place in code of node class, not in MyControl and IMyControl code. Property field in IMyControl interface must be accessible for write from NodeClass and unaccessible for write from derived classes. That i am trying to accomplish here.
If I understand you correctly, you can use this draft:
class Node
{
public ControlWrapper Link { get; set; }
}
abstract class ControlWrapper
{
private readonly Node _node;
private readonly Control _control;
public Node Node
{
get { return _node; }
}
public Control Control
{
get { return _control; }
}
public ControlWrapper(Node node, Control control)
{
if (node == null)
throw new ArgumentNullException("node");
if (control == null)
throw new ArgumentNullException("control");
_node = node;
_control = control;
}
}
class ControlWrapper<TControl> : ControlWrapper
where TControl : System.Windows.Forms.Control
{
public TControl Control
{
get { return (TControl)base.Control; }
}
public ControlWrapper(Node node, TControl control)
: base (node, control)
{
}
}
class Program
{
static void Main(string[] args)
{
Node n1 = new Node();
n1.Link = new ControlWrapper<TextBox>(n1, new TextBox());
Node n2 = new Node();
n2.Link = new ControlWrapper<Button>(n2, new Button());
}
}
Abstract class ControlWrapper provides you with back-link to node (you can't encapsulate logic in interface, so abstract class goes here), typed derived generic class provides constructor for creating actual implementations of control-wrappers.
If you want this relation automatically force its consistency, you should write code like this:
class Program
{
static void Main(string[] args)
{
Node n1 = new Node();
n1.SetControl(new TextBox());
Node n2 = new Node();
n2.SetControl(new Button());
}
}
class Node
{
private ControlWrapper _link;
public ControlWrapper Link
{
get { return _link; }
}
public void SetControl<TControl>(TControl control)
where TControl : System.Windows.Forms.Control
{
ControlWrapper prevLink = Link;
if (prevLink != null)
prevLink.Dispose();
_link = new ControlWrapper<TControl>(this, control);
}
}
// microsoft basic dispose pattern
// http://msdn.microsoft.com/en-us/library/b1yfkh5e(v=vs.110).aspx#basic_pattern
abstract class ControlWrapper : IDisposable
{
private readonly Node _node;
private readonly Control _control;
public Node Node
{
get { return _node; }
}
public Control Control
{
get { return _control; }
}
public ControlWrapper(Node node, Control control)
{
if (node == null)
throw new ArgumentNullException("node");
if (control == null)
throw new ArgumentNullException("control");
_node = node;
_control = control;
}
#region IDisposable Members
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (_control != null)
_control.Dispose();
}
}
}
class ControlWrapper<TControl> : ControlWrapper
where TControl : System.Windows.Forms.Control
{
public TControl Control
{
get { return (TControl)base.Control; }
}
public ControlWrapper(Node node, TControl control)
: base (node, control)
{
}
}
I'm currently struggling with the implementation of a set of file system classes. I guess this calls for the composite pattern if I'm not mistaken. So I set up the following classes:
An abstract class Node which has a reference to its parent folder and two classes Folder and File that implement Node. A folder contains a collection of all its children and methods to add and remove children.
The thing is, I can't figure out how to implement all the methods properly. In all the examples I have seen there is no reference to the parent in the children. How can the AddChild method ensure that the child's parent reference is set correctly? I solved that by checking whether child.Parent has already been set to the folder or it throws an ArgumentException. The matter is further complicated by the fact that AddChild might also throw an exception like DuplicateNameException or something. So my methods look like this now:
File.AddTo(Folder folder) {
this.Parent = folder;
try {
folder.AddChild(this);
} catch {
this.Parent = null;
throw;
}
}
Folder.AddChild(Node child)
{
if(child.Parent != this)
throw new ArgumentException(...);
...
}
Now I have this ugly AddTo method and cannot do something like someFolder.AddChild(new File(...)). I wonder how it was implemented with ListViewItem for instance. There I can just do someListView.Items.Add(new ListViewItem(...)).
My solution works, but I'm not convinced that it's the right way to do this. Maybe someone has a better solution or can point me to a good example. Thanks in advance.
EDIT: Minimal full class definitions below.
abstract class Node
{
public Folder Parent { get; protected set; }
public string Name { get; private set; }
public Node(string name) {
Parent = null;
Name = name;
}
}
class Folder : Node {
private Dictionary<string, Node> _children;
public Folder(string name) : base(name) {
// Other initializations here...
}
public void AddChild(Node child) {
if(child is Folder)
((Folder)child).Parent = this; // Damn, doesn't work for files!!!
else if(child.Parent != this)
throw new ArgumentException();
if(_children.ContainsKey(child.Name))
throw new DuplicateNameException();
_children[child.Name] = child;
}
}
class File : Node {
public File(string name) : base(name) {
// Other initializations here...
}
public void AddTo(Folder folder) {
Parent = folder;
try {
folder.AddChild(this);
} catch {
Parent = null;
}
}
}
How about doing it the other way around:
Folder.AddChild(Node child)
{
child.Parent = this;
this._children.Add(child); // or what ever your doing to store the children
...
}
If you're adding a child to the parent, that should be done through a method on parent. Parent can then confirm/validate its own state and that its preconditions are satisfied. It's not up to a node to figure out whether its parent is valid -- let the parent do that.
So, by way of code, you have something like:
public class Node
{
public string Name { get; set; }
public abstract void Add(Node child);
protected abstract void CreateOnDisk();
}
public class File
{
public override void Add(Node child)
{
//No op, since you can't add a child to a file
}
protected override void CreateOnDisk()
{
File.Create(this.Name);
}
}
public class Directory
{
public override void Add(Node child)
{
child.Name = Path.Combine(this.Name, child.Name);
child.CreateOnDisk();
}
protected override CreateOnDisk()
{
Directory.Create(this.Name);
}
}
I just freelanced a bit off the top of my head, but that's to give an idea. I really think there's no need to keep track of your parent, and I think that's going to turn out in the end to be a fairly cumbersome solution.
When I implement bidirectional associations, I usually move all association maintenance to one of the sides. In this case, I'd chose Folder.
public abstract class Node
{
public Folder Parent { get; set; }
public string Name { get; set; }
public abstract long Size { get; }
}
public class File : Node
{
private long _size;
public override long Size
{
get { return _size; }
}
public void AddTo(Folder folder)
{
folder.Add(this);
}
public void RemoveFrom(Folder folder)
{
folder.Remove(this);
}
}
public class Folder : Node
{
private List<Node> _children = new List<Node>();
public void Add(Node node)
{
if (node.Parent == this)
return; // already a child of this folder
_children.Add(node);
node.Parent = this;
}
public void Remove(Node node)
{
if (node.Parent != this)
return; // not a child of this folder
_children.Remove(node);
node.Parent = null;
}
public override long Size
{
get { return _children.Sum(node => node.Size); }
}
}
PS try to eliminate bidirectional association, it adds lot of headache.
UPDATE
With unidirectional association you have simple code, without ugly Folder field in Node class (I hate when base class depends on its child). Also no headache with adding/removing files.
public abstract class Node
{
public string Name { get; set; }
public abstract long Size { get; }
}
public class File : Node
{
private long _size;
public override long Size
{
get { return _size; }
}
}
public class Folder : Node
{
private List<Node> _children = new List<Node>();
public void Add(Node node)
{
if (_children.Contains(node))
return;
_children.Add(node);
}
public void Remove(Node node)
{
if (!_children.Contains(node))
return;
_children.Remove(node);
}
public override long Size
{
get { return _children.Sum(node => node.Size); }
}
}
AddChild() is a method on the parent.
Thinking about the purpose of the method, and your desire to maintain a reference to the parent in the child, you need to expose a property on the child that can be set by the parent, presumably in the AddChild method.
public abstract class Node
{
private Node parent;
internal void SetParent(Node parent)
{
this.parent = parent;
}
}
public class Folder : Node
{
void AddChild(Node child)
{
this.children.Add(child);
child.SetParent(this); // or, you could use a C# Property
}
}
public class File : Node
{
}
The child knows how to establish its parent; the parent knows how to adopt a child.
This question already has answers here:
Is there a way to reach a `protected` member of another object from a derived type?
(7 answers)
Closed 9 years ago.
I want to organise a scene graph.
I have general class SceneNode:
public class SceneNode
{
protected SceneNode prev, next;
protected SceneNodeContainer parent;
public SceneNode Parent { get { return parent; } }
public SceneNode PreviousNode { get { return prev; } }
public SceneNode NextNode { get { return next; } }
}
I also have class SceneNodeContainer, which is like this:
public class SceneNodeContainer : SceneNode
{
SceneNode firstChild, lastChild;
public SceneNode FirstChild { get { return firstChild; } }
public SceneNode LastChild { get { return lastChild; } }
public void Add(SceneNode node)
{
Debug.Assert(node != null);
Debug.Assert(node.parent == null);
node.parent = this;
node.prev = lastChild;
node.next = null;
if (lastChild == null)
{
lastChild = node;
firstChild = lastChild;
}
else
{
lastChild.next = node;
lastChild = node;
}
}
public void Remove(SceneNode node)
{
Debug.Assert(node != null);
Debug.Assert(node.parent == this);
//unlink node
if (node.next != null)
node.next.prev = node.prev;
if (node.prev != null)
node.prev.next = node.next;
if (node == firstChild)
firstChild = node.next;
if (node == lastChild)
lastChild = node.prev;
node.parent = null;
node.next = null;
node.prev = null;
}
}
IntelliSense says that node.parent and other protected fields cannot be accessed from SceneNodeContainer. How can I overcome this?
You can't, because of the way protected works - it only allows access to protected fields of objects which are known to be of the child type (or a subtype). So if node were a SceneNodeContainer variable, you'd have access to the fields - but otherwise, you don't.
From section 3.5.3 of the C# 4 spec:
When a protected instance member is accessed outside the program text of the class in which it is declared, and when a protected internal instance member is accessed outside the program text of the program in which it is declared, the access must take place within a class declaration that derives from the class in which it is declared. Furthermore, the access is required to take place through an instance of that derived class type or a class type constructed from it. This restriction prevents one derived class from accessing protected members of other derived classes, even when the members are inherited from the same base class.
(As an aside, I'd personally avoid protected fields anyway. I make non-constant fields private in almost all cases.)
use protected internal instead of protected then you can access from sub classes of same assembly.
public class SceneNode
{
protected internal SceneNode prev, next;
protected internal SceneNodeContainer parent;
public SceneNode Parent { get { return parent; } }
public SceneNode PreviousNode { get { return prev; } }
public SceneNode NextNode { get { return next; } }
}