I'm trying to create an Equals() method which will check if two Binary search trees are identical.
However, when creating 2 BS Trees and calling the Equals method in main, it always returns False.
Please help.
Node Class
class Node<T> where T : IComparable
{
private T data;
public Node<T> Left, Right;
private int balanceFactor;
public Node(T item)
{
data = item;
Left = null;
Right = null;
}
public T Data
{
set { data = value; }
get { return data; }
}
public int BalanceFactor
{
set { balanceFactor = value; }
get { return balanceFactor; }
}
}
BSTree Class
class BSTree<T> : BinTree<T> where T : IComparable
{ //root declared as protected in Parent Class – Binary Tree
public BSTree()
{
root = null;
}
public void InsertItem(T item)
{
insertItem(item, ref root);
}
private void insertItem(T item, ref Node<T> tree)
{
//stopping condition
//simplet tree - what should we do?
if (tree == null)
{
tree = new Node<T>(item);
}
else if(item.CompareTo(tree.Data) < 0)
{
insertItem(item, ref tree.Left);
}
else if (item.CompareTo(tree.Data) > 0)
{
insertItem(item, ref tree.Right);
}
}
public bool Equals(BSTree<T> tree)
{
return Equals(tree,root);
}
private bool Equals(Node<T> root1, Node<T> root2)
{
if (root1 == null && root2 == null)
return true;
if (root1 == null || root2 == null)
{
return false;
}
if (root1.Data.CompareTo(root2.Data) != 0)
return false;
return Equals(root1.Left, root2.Left) && Equals(root1.Right, root2.Right);
}
}
Main
BSTree<int> firstBSTree = new BSTree<int>();
firstBSTree.InsertItem(23);
firstBSTree.InsertItem(12);
firstBSTree.InsertItem(67);
BSTree<int> secondBSTree = new BSTree<int>();
secondBSTree.InsertItem(23);
secondBSTree.InsertItem(12);
secondBSTree.InsertItem(67);
Console.WriteLine(firstBSTree.Equals(secondBSTree));
You are trying to compare BSTree<T> and Node<T>. It calls bool Equals(Object? objA, Object? objB) method of object class. Just pass node of tree.
public bool Equals(BSTree<T> tree)
{
return Equals(tree.root, root);
}
Related
I have a small problem. When I add value to MyLinkedList, first value gets lost.
I'm not sure what is wrong.
public class MyLinkedList<T> : IEnumerable<T>
{
private Node<T> head;
private Node<T> tail;
public MyLinkedList()
{
head = null;
tail = null;
}
public void Add(T value)
{
Node<T> node = new Node<T>(value);
if (head == null)
{
head = node;
tail = head;
}
tail.Next = node;
tail = node;
}
public IEnumerator<T> GetEnumerator()
{
return new MyLinkedListEnumerator<T>(head);
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
If I do
head = new Node<T>(default);
tail = head;
Then it's working as it should, but that is wrong, LinkedList should be empty on init.
static void Main()
{
var ll = new MyLinkedList<int>();
ll.Add(1);
ll.Add(2);
foreach (var i in ll)
{
Console.WriteLine(i);
}
}
Output is 2.
not 1 ; 2 as it should be.
Here I'm adding IEnumerable implementation, so everything is clear.
public class MyLinkedListEnumerator<T> : IEnumerator<T>
{
private Node<T> current;
public MyLinkedListEnumerator(Node<T> current)
{
this.current = current;
}
public T Current => current.Value;
object IEnumerator.Current => Current;
public bool MoveNext()
{
//if (current == null) return false;
current = current.Next;
return (current != null);
}
public void Dispose() { }
public void Reset()
{
}
}
i tried to fix a code, which is a LinkedList. The task is to Remove the last X elements of the list.
I tried it with RemoveRange, but VS don't accept my solution and says, that RemoveRange doesn't exist.
var list = new DoublyLinkedList<string>();
list.Add("A");
list.Add("B");
list.Add("C");
list.Add("D");
list.Add("E");
list.RemoveLast(2);
This is the Code in the Program (Main).
In a second class there should be the method RemoveLast, but i dont get a working code. Can someone explain me, how i get the RemoveLast?
using System;
using System.Collections;
using System.Collections.Generic;
namespace Test
{
public class DoublyLinkedList<T> : IEnumerable<T>
{
public void RemoveLast(int v)
{
int remove = Math.Max(0, this.Count - v);
this.RemoveRange(v, this.Count - v);
}
}
}
RemoveRange is red underlined
Thank you for your help!
Full DoublyLinkedList:
`using System;
using System.Collections;
using System.Collections.Generic;
namespace Test
{
public class DoublyLinkedList<T> : IEnumerable<T>
{
public void RemoveLast(int v)
{
int remove = Math.Max(0, this.Count - v);
this.RemoveRange(v, this.Count - v);
}
private sealed class Node
{
public T Item { get; set; }
public Node Previous { get; set; }
public Node Next { get; set; }
}
private Node first, last;
public int Count { get; private set; }
public void Add(T item)
{
Node newItem = new Node() { Item = item, Next = null, Previous = null };
if (first == null)
{
first = newItem;
last = newItem;
}
else
{
last.Next = newItem;
newItem.Previous = last;
last = newItem;
}
Count++;
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
Node node = first;
while (node != null)
{
yield return node.Item;
node = node.Next;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable<T>)this).GetEnumerator();
}
public override string ToString()
{
string s = "";
Node node = first;
while (node != null)
{
s += node.Item.ToString() + " -> ";
node = node.Next;
}
s += "Count: " + Count.ToString();
return s;
}
private Node find(T item)
{
Node node = first;
while (node != null)
{
if (node.Item.Equals(item))
return node;
node = node.Next;
}
return null;
}
private Node findPrevious(T item)
{
Node previousNode = null;
Node node = first;
while (node != null)
{
if (node.Item.Equals(item))
return previousNode;
previousNode = node;
node = node.Next;
}
return null;
}
}
}`
You do know there is already a double linked list class, don't you?
System.Collections.Generic.LinkedList? My advice would be to use that class.
If it is too much work to redesign your code, for instance because your DoublyLinkedList is already used a lot, my advice would be to make DoublyLinkedList an adapter for LinkedList:
class DoublyLinkedList<T> : IEnumerable<T>, IEnumerable
{
private readonly LinkedList<T> linkedList = new LinkedList<T>();
public int Count => this.linkedList.Count;
public void Add(T item)
{
this.LinkedList.Add(item);
}
public IEnumerator<T> GetEnumerator()
{
return this.LinkedList.GetEnumerator();
}
... // etc.
}
You need to add a method to remove the last N items from your list. For example
RemoveLast(10) is supposed to remove the last 10 elements from your doubly linked list. If your list has 10 or less elements, this would clear your complete list.
void Clear()
{
this.LinkedList.Clear();
}
void RemoveLast()
{
if (this.LinkedList.Count != 0)
this.linkedList.RemoveLast();
}
void RemoveLast(int removeCount)
{
if (this.Count <= removeCount)
{
this.linkedList.Clear();
}
else
{
for (int i=0; i<removeCount; ++i)
{
this.RemoveLast();
}
}
}
It might be that your supervisor is stubborn and does not follow your advise to reuse fully tested trustworthy .NET classes. In that case you'll have to change the RemoveLast() method.
void Clear()
{
this.first = null;
this.last = null;
this.count = 0;
}
void RemoveLast()
{
switch (this.Count)
{
case 0:
// empty list; do nothing
break;
case 1:
// removing the last element of the list
this.Clear();
break;
default:
var lastNode = this.last;
// because more than one element I'm certain there is a previous node
var previousNode = lastNode.Previous;
var previousNode.Next = null;
this.last = previousNode;
--this.count;
break;
}
}
Here is how you can implement RemoveLast(int n) in your DoublyLinkedList:
// Removes last "n" elements.
public void RemoveLast(int n)
{
for (int i = 0; i < n; i++)
RemoveLast();
}
// Removes the last element.
public void RemoveLast()
{
// List is empty. No need to remove elements.
if (first == null)
{
return;
}
// List contains only one element. Remove it.
else if (first == last)
{
first = null;
last = null;
}
// List contains more than one element. Remove the last.
else
{
// The next two lines make "last" to point to the element before the last.
last = last.Previous;
last.Next = null;
}
Count--;
}
Here is complete sample.
If RemoveRange is not available, you can easiliy roll your own implementation that works on any enumerable without Linq in this way (this code is an idea as I do not have access to all your code).
using System;
using System.Collections;
using System.Collections.Generic;
public void RemoveRange(int count)
{
if (count > this.Count)
throw new ArgumentOutOfRangeException(nameof(count));
while (count > 0)
{
RemoveTail();
count--;
}
}
private void RemoveTail()
{
if (this.Count == 0)
return;
var previous = last.Previous;
if (previous != null)
{
previous.Next = null;
last = previous;
this.Count--;
}
else
{
// this implies count == 1
last = null;
first = null;
this.Count = 0;
}
}
Essentially, you can expose your RemoveRange method and then perform an agnostic removal of the last node (tail) one by one.
This answer has been edited to reflect the code changes.
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;
}
}
Why reason the member variables LEFT and RIGHT never change when i make the recursive call?
Here's the Source Code:
public class C_Nodo
{
int dato;
C_Nodo left;
C_Nodo right;
public int DATO
{
get { return dato; }
set { dato = value; }
}
public C_Nodo LEFT
{
get { return this.left; }
set { this.left= value; }
}
public C_Nodo RIGHT
{
get { return this.right; }
set { this.right = value; }
}
public C_Nodo(int inf)
{
this.dato = inf;
this.left = null;
this.right = null;
}
}
public class C_Arbol_Bin
{
C_Nodo root;
public C_Arbol_Bin()
{
root = null;
}
Simple insertion in the root or make the recursive call
public void inserta(int dat)
{
if (root == null)
{
root = new C_Nodo(dat);
}
else
{
insert_Order(this.root, dat);
}
}
Here i make the recursive insertion in ordered way depending of the value that contains the father node but RIGH and LEFT never change.
public void insert_Order(C_Nodo tree, int inf)
{
if (tree == null)
{
tree = new C_Nodo(inf);
}
else
{
if (tree.DATO > inf)
{
insert_Order(tree.LEFT, inf);
}
else
{
insert_Order(tree.RIGHT, inf);
}
}
}
}
Declare the function like
public void insert_Order( ref C_Nodo tree, int inf );
Also as this function is an auxiliary function for function inserta then it could be declared like private
What Vlad said...
Basically the reason that the LEFT/RIGHT parts are always null is because you are passing a reference-type object by value, and then call new C_Nodo() on it - this creates a pointer to a new location for your object.
So you can either use Vlad's solution and pass it by reference, or you can change your insert and insert_Order methods to return the Node object and save it in the root node:
public void inserta(int dat)
{
if (root == null)
{
root = new C_Nodo(dat);
}
else
{
this.root = insert_Order(this.root, dat);
}
}
private C_Nodo insert_Order(C_Nodo tree, int inf)
{
if (tree == null)
{
tree = new C_Nodo(inf);
}
else
{
if (tree.DATO > inf)
{
tree.LEFT = insert_Order(tree.LEFT, inf);
}
else
{
tree.RIGHT = insert_Order(tree.RIGHT, inf);
}
}
return tree;
}
Check out this article for more info on references: https://msdn.microsoft.com/en-us/library/s6938f28.aspx
Let me start off by saying sorry if the title is wrong.
I am being taught Binary Tree Traversal I've been given some of the code, I am really struggling to understand the logic in using the if/else statements and the boolean logic.
I have to traverse the tree using postorder, preorder and inorder methods.
The preorderTraversal method is all ready done and working.
Any suggestions would be appreciated.
The Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BinaryTree
{
class BinaryTree<T>
{
class BinaryTreeNode
{
public BinaryTreeNode Left;
public BinaryTreeNode Right;
public BinaryTreeNode Parent;
public T Data;
public Boolean processed;
public BinaryTreeNode()
{
Left = null;
Right = null;
Parent = null;
processed = false;
}
}
BinaryTreeNode Root;
Comparison<T> CompareFunction;
public BinaryTree(Comparison<T> theCompareFunction)
{
Root = null;
CompareFunction = theCompareFunction;
}
public static int CompareFunction_Int(int left, int right)
{
return left - right;
}
public void preorderTraversal()
{
if (Root != null)
{
BinaryTreeNode currentNode = Root;
Boolean process = true;
int nodesProcessed = 0;
while (nodesProcessed != 11)
{
if (process)
{
Console.Write(currentNode.Data.ToString());
currentNode.processed = true;
nodesProcessed = nodesProcessed +1;
}
process = true;
if (currentNode.Left != null && currentNode.Left.processed == false)
{
currentNode = currentNode.Left;
}
else if (currentNode.Right != null && currentNode.Right.processed ==
false)
{
currentNode = currentNode.Right;
}
else if (currentNode.Parent != null)
{
currentNode = currentNode.Parent;
process = false;
}
}
}
else
{
Console.WriteLine("There is no tree to process");
}
}
public void postorderTraversal()
{
if (Root != null)
{
}
else
{
Console.WriteLine("There is no tree to process");
}
}
public void inorderTraversal()
{
if (Root != null)
{
}
else
{
Console.WriteLine("There is no tree to process");
}
}
public static int CompareFunction_String(string left, string right)
{
return left.CompareTo(right);
}
public void Add(T Value)
{
BinaryTreeNode child = new BinaryTreeNode();
child.Data = Value;
if (Root == null)
{
Root = child;
}
else
{
BinaryTreeNode Iterator = Root;
while (true)
{
int Compare = CompareFunction(Value, Iterator.Data);
if (Compare <= 0)
if (Iterator.Left != null)
{
Iterator = Iterator.Left;
continue;
}
else
{
Iterator.Left = child;
child.Parent = Iterator;
break;
}
if (Compare > 0)
if (Iterator.Right != null)
{
Iterator = Iterator.Right;
continue;
}
else
{
Iterator.Right = child;
child.Parent = Iterator;
break;
}
}
}
}
public bool Find(T Value)
{
BinaryTreeNode Iterator = Root;
while (Iterator != null)
{
int Compare = CompareFunction(Value, Iterator.Data);
if (Compare == 0) return true;
if (Compare < 0)
{
Iterator = Iterator.Left;
continue;
}
Iterator = Iterator.Right;
}
return false;
}
BinaryTreeNode FindMostLeft(BinaryTreeNode start)
{
BinaryTreeNode node = start;
while (true)
{
if (node.Left != null)
{
node = node.Left;
continue;
}
break;
}
return node;
}
public IEnumerator<T> GetEnumerator()
{
return new BinaryTreeEnumerator(this);
}
class BinaryTreeEnumerator : IEnumerator<T>
{
BinaryTreeNode current;
BinaryTree<T> theTree;
public BinaryTreeEnumerator(BinaryTree<T> tree)
{
theTree = tree;
current = null;
}
public bool MoveNext()
{
if (current == null)
current = theTree.FindMostLeft(theTree.Root);
else
{
if (current.Right != null)
current = theTree.FindMostLeft(current.Right);
else
{
T CurrentValue = current.Data;
while (current != null)
{
current = current.Parent;
if (current != null)
{
int Compare = theTree.CompareFunction(current.Data,
CurrentValue);
if (Compare < 0) continue;
}
break;
}
}
}
return (current != null);
}
public T Current
{
get
{
if (current == null)
throw new InvalidOperationException();
return current.Data;
}
}
object System.Collections.IEnumerator.Current
{
get
{
if (current == null)
throw new InvalidOperationException();
return current.Data;
}
}
public void Dispose() { }
public void Reset() { current = null; }
}
}
class TreeTest
{
static BinaryTree<int> Test = new BinaryTree<int>
(BinaryTree<int>.CompareFunction_Int);
static void Main(string[] args)
{
// Build the tree
Test.Add(5);
Test.Add(2);
Test.Add(1);
Test.Add(3);
Test.Add(3); // Duplicates are OK
Test.Add(4);
Test.Add(6);
Test.Add(10);
Test.Add(7);
Test.Add(8);
Test.Add(9);
// Test if we can find values in the tree
for (int Lp = 1; Lp <= 10; Lp++)
Console.WriteLine("Find ({0}) = {1}", Lp, Test.Find(Lp));
// Test if we can find a non-existing value
Console.WriteLine("Find (999) = {0}", Test.Find(999));
// Iterate over all members in the tree -- values are returned in sorted order
foreach (int value in Test)
{
Console.WriteLine("Value: {0}", value);
}
Console.WriteLine("Preorder traversal");
Test.preorderTraversal();
Console.ReadKey();
}
}
}
Use the Recursion, Luke. (Then it's just a matter in what order you visit (and process) the left subtree, right subtree, or the current node itself.)
Here, maybe some nice animations with option to traverse it the way you like, and add and delete so you can have your own example might help: Look at this site
Or maybe CS animation with voice over ... look here.