C# Find Specific Node in Binary Search Tree - c#

been noodling around with BST's and I have a pretty good idea of them but I would like to be able to search for a particular node in the BST and have it tell me if it exists. I am using strings in the BST and everything seems to work well but I cannot figure out this Find method. If someone could tell me what I am doing wrong and how to fix it this would be appreciated.
class Node
{
public string number;
public string data;
public Node left;
public Node right;
public string Content;
public Node(string data)
{
this.data = data;
}
}
class BinarySearchTree
{
public Node root, current;
public BinarySearchTree()
{
this.root = null;
}
public void AddNode(string a) // code to insert nodes to the binary search tree
{
Node newNode = new Node(a); //create a new node
if (root == null) // if the tree is empty new node will be the root node
root = newNode;
else
{
Node previous;
current = root;
while (current != null)
{
previous = current;
if (a.CompareTo(current.data) < 1) //if the new node is less than the current node
{
current = current.left;
if (current == null)
previous.left = newNode;
}
else //if the new node is greater than the current node
{
current = current.right;
if (current == null)
previous.right = newNode;
}
}
}
}
public string FindNode(Node node, string s)
{
if (root == null)
return Output = "not found";
else if (s.CompareTo(root.data) < 1)
return FindNode(root.left, s);
else if (s.CompareTo(root.data) > 1)
return FindNode(root.right, s);
return Output = "found";
}
string SearchResult = "";
static string Output = "";
public string Display(Node rootNode)
{
if (rootNode != null)
{
Display(rootNode.left);
Output += rootNode.data;
Display(rootNode.right);
}
return Output;
}
}
private void btnExecute_Click(object sender, EventArgs e)
{
BinarySearchTree btree = new BinarySearchTree();
btree.AddNode("D");
btree.AddNode("B");
btree.AddNode("F");
btree.AddNode("E");
btree.AddNode("A");
btree.AddNode("G");
btree.AddNode("C");
string target;
txtOutput.Text += "The sorted values of the Binary Search Tree are: \r\n \r\n";
txtOutput.Text += btree.Display(btree.root);
txtOutput.Text += btree.FindNode(btree.root, "A");
}

Try to change the following:
1. Use CompareTo method with 0 not 1, so a.CompareTo(current.data) < 1 should be a.CompareTo(current.data) < 0
See documentation IComparable.CompareTo Method
2. As your FindNode is recursive call, change root to node usage
public string FindNode(Node node, string s)
{
if (node == null)
return Output = "not found";
else if (s.CompareTo(node.data) < 0)
return FindNode(node.left, s);
else if (s.CompareTo(node.data) > 0)
return FindNode(node.right, s);
return Output = "found";
}
Good luck!

Related

How to find a path to a specific object from a tree of objects? [duplicate]

I have TreeNode node.
something = treeview.Nodes[1].Nodes[4].Nodes[0];
TreeNode myNode = something;
And wish to know how pany parents it has and what indexes i need to use to find whole path out from this node.
I mean get "treeview.Nodes[1].Nodes[4].Nodes[0]" out from myNode
Something like this should work:
public IList<int> GetNodePathIndexes(TreeNode node)
{
List<int> indexes = new List<int>();
TreeNode currentNode = node;
while (currentNode != null)
{
TreeNode parentNode = currentNode.Parent;
if (parentNode != null)
indexes.Add(parentNode.Nodes.IndexOf(currentNode));
else
indexes.Add(currentNode.TreeView.Nodes.IndexOf(currentNode));
currentNode = parentNode;
}
indexes.Reverse();
return indexes;
}
You can then look at the result of this to get the indexes, and the count, to get the number of parents.
IList<int> path = GetNodePathIndexes(myNode);
StringBuilder fullPath = new StringBuilder("treeview");
foreach (int index in path)
{
fullPath.AppendFormat(".Nodes[{0}]", index);
}
Then fullPath.ToString() should return treeview.Nodes[1].Nodes[4].Nodes[0]
//...
string path = GetPath(treeView1.Nodes[0].Nodes[0].Nodes[1].Nodes[0]);
// now path is "treeView.Nodes[0].Nodes[0].Nodes[1].Nodes[0]"
//...
string GetPath(TreeNode node) {
int index;
Stack<string> stack = new Stack<string>();
while(node != null) {
if(node.Parent != null) {
index = node.Parent.Nodes.IndexOf(node);
stack.Push(string.Format("Nodes[{0}]", index));
}
else {
index = node.TreeView.Nodes.IndexOf(node);
stack.Push(string.Format("treeView.Nodes[{0}]", index));
}
node = node.Parent;
}
return string.Join(".", stack.ToArray());
}

What is the name of this data structure search algorithm?

I have a tree search algorithm that uses multiple keys and each node has a sub tree which is searched with the next key in the list of keys until the keys run out and the data being searched is in that end node.
my code is working but I don't know what to call it. I thought it was a Ternary Tree until I read Wicki page and that doesn't seem to be it. So I just don't know what to call it.
here's my class. works like a binary tree with no limit on the number of keys where the set of keys are sent to the search/Insert functions as a list. Each time one key finds a node, the next key is stripped off the list and that node's "Next key Tree" repeats the process until it runs out of keys and sends back the data. My thinking is I can use it to mark exact searches of categories like "first name", "second name", "occupation", "city". they are entered in the same sequence and any sub-tree can be traversed. still not sure how much better this is than a regular binary-tree for strings. I have another exact version that has Integer keys that might come in more handy.
public class classTernaryTree_StringKey
{
classTernaryTree_StringKey_Node cRoot = null;
public void Insert(ref object data, List<string> lstKeys)
{
classTernaryTree_StringKey cMyRef = this;
_Insert(ref cMyRef, ref data, lstKeys);
}
static void _Insert(ref classTernaryTree_StringKey cTree, ref object data, List<string> lstKeys)
{
if (cTree.cRoot == null)
{
cTree.cRoot = new classTernaryTree_StringKey_Node();
cTree.cRoot.key = lstKeys[0];
lstKeys.RemoveAt(0);
if (lstKeys.Count > 0)
{
cTree.cRoot.NextTree.Insert(ref data, lstKeys);
return;
}
else
{
cTree.cRoot.data = data;
return;
}
}
classTernaryTree_StringKey_Node cNode = cTree.cRoot;
do
{
int intComparison = string.Compare(lstKeys[0], cNode.key);
if (intComparison > 0)
{
if (cNode.Right != null)
cNode = cNode.Right;
else
{
cNode.Right = new classTernaryTree_StringKey_Node();
cNode.Right.key = lstKeys[0];
lstKeys.RemoveAt(0);
if (lstKeys.Count > 0)
{
cNode.Right.NextTree.Insert(ref data, lstKeys);
return;
}
else
{
cNode.Right.data = data;
return;
}
}
}
else if (intComparison < 0)
{
if (cNode.Left != null)
cNode = cNode.Left;
else
{
cNode.Left = new classTernaryTree_StringKey_Node();
cNode.Left.key = lstKeys[0];
lstKeys.RemoveAt(0);
if (lstKeys.Count > 0)
{
cNode.Left.NextTree.Insert(ref data, lstKeys);
return;
}
else
{
cNode.Left.data = data;
return;
}
}
}
else
{
lstKeys.RemoveAt(0);
if (lstKeys.Count > 0)
{
cNode.NextTree.Insert(ref data, lstKeys);
return;
}
else
{
cNode.data = data;
return;
}
}
} while (true);
}
public object Search(List<string> lstKeys)
{
classTernaryTree_StringKey cMyRef = this;
return _Search(ref cMyRef, lstKeys);
}
static object _Search(ref classTernaryTree_StringKey cTree, List<string> lstKeys)
{
if (cTree.cRoot == null) return null;
classTernaryTree_StringKey_Node cNode = cTree.cRoot;
do
{
int intComparison = string.Compare(lstKeys[0], cNode.key);
if (intComparison > 0)
{
if (cNode.Right != null)
cNode = cNode.Right;
else
return null;
}
else if (intComparison < 0)
{
if (cNode.Left != null)
cNode = cNode.Left;
else
return null;
}
else
{
lstKeys.RemoveAt(0);
if (lstKeys.Count > 0)
return cNode.NextTree.Search(lstKeys);
else
return cNode.data;
}
} while (true);
}
}
public class classTernaryTree_StringKey_Node
{
public string key = "";
public classTernaryTree_StringKey_Node Left = null;
public classTernaryTree_StringKey_Node Right = null;
public classTernaryTree_StringKey NextTree = new classTernaryTree_StringKey();
public object data = null;
}
The data structure you have here does actually look pretty similar to a ternary search tree, just with strings labeling the nodes rather than individual characters.
A ternary search tree is a way of encoding a trie data structure. Tries are trees representing sequences of elements. Usually, those elements are individual characters, but they could in principle be anything. Your data structure is essentially a ternary search tree where you store strings rather than characters at each node.

Linked list first and last element can't be deleted

I made big research in this forum and found many "solutions" but none of them work.
Maybe my situation is a little bit different and I maybe someone can see where is the problem. I need to delete each Node element which is has "value" less than given(kruvis).
public void Delete()
{
if (Start == null) return;
if (Start.Next == null)
{
Start = null;
return;
}
if (Current.Next == null)
{
Current = null;
}
Node temp = Start;
while (temp.Next.Next != null)
{
if (temp.Next == Current)
{
temp.Next = Current.Next;
Current = temp;
return;
}
temp = temp.Next;
}
}
There is another function(loop in function) in diferent class
for (MenesioAgentai.Pradzia(); MenesioAgentai.ArYra(); MenesioAgentai.Sekantis())
{
if (MenesioAgentai.GautiT().Kruvis <= kruvis)
{
kruvioSuma += MenesioAgentai.GautiT().Kruvis;
PasalintiAgentoPrenumeratorius(pren, MenesioAgentai.GautiT());
MenesioAgentai.Delete();
}
}
The problem is that the first and last element is not deleted
in NodeList class I have 3 nodes Start, End, Current. (and sealed class Node with T data and Node Next)
Deleting node from a linked list is a bit tricky when the head node also needs to be deleted. An easier way is to add a sentinel node at the beginning. The following Java code explains how to delete nodes that have a smaller value than a given value. I used a value of type int for simplicity.
/*
// Node definition
class Node {
Node next;
int val;
Node(int val) {
this.val = val;
}
}
*/
public Node delete(Node head, int k) {
Node sentinel = new Node(Integer.MIN_VALUE);
sentinel.next = head;
Node prev = sentinel, curr = sentinel.next;
while(curr != null) {
while(curr != null && curr.val < k) {
curr = curr.next;
}
prev.next = curr;
prev = curr;
if(curr != null) {
curr = curr.next;
}
}
return sentinel.next;
}

Singly Linked List Implementation using C# - RemoveLast Method

I've implemented Singly linked list using C# . Can anyone please look into the following code and suggest where I'm wrong?
public int RemoveLast()
{
if (Head != null)
{
var curNode = Head;
while (curNode.Next != null)
{
curNode = curNode.Next;
}
var lastNodeValue = curNode.Value;
curNode = null;
Size--;
return lastNodeValue;
}
return -1;
}
This function does not remove the last node. I'm unable to figure out what's wrong. When while loop ends, we have the reference of node in curNode whose next is null. It means this is the last node. At the end, I'm setting this node to null. But when I use Display function. It displays the last node as well. This is not deleting the last node.
Here is my display function:
public string Display()
{
if (Head == null)
{
return string.Empty;
}
var curNode = Head;
var builder = new StringBuilder();
while (curNode.Next != null)
{
builder.Append($"{curNode.Value} ");
curNode = curNode.Next;
}
builder.Append($"{curNode.Value} ");
return builder.ToString();
}
You need to go to the last-but-one node, and change its Next to null:
public int RemoveLast()
{
if (Head != null)
{
var curNode = Head;
while (curNode.Next?.Next != null)
{
curNode = curNode.Next;
}
var lastNodeValue = curNode.Next?.Value ?? -1;
curNode.Next = null;
Size--;
return lastNodeValue;
}
return -1;
}
Note that if you also want Head to be set to null if its the only node, then you can do that like so:
public int RemoveLast()
{
if (Head != null)
{
var curNode = Head;
while (curNode.Next?.Next != null)
{
curNode = curNode.Next;
}
int lastNodeValue;
if (Head.Next == null)
{
lastNodeValue = Head.Value;
Head = null;
}
else
{
lastNodeValue = curNode.Next?.Value ?? -1;
}
curNode.Next = null;
Size--;
return lastNodeValue;
}
return -1;
}
I have to say though, this Head property looks a bit dubious - it should perhaps belong to a different class.
[x] -> [x] -> [x] -> null
^
curNode (becomes null)
^
this reference still exists
When doing curNode = null you do not change any reference in the list. curNode variable is changed only, it is pointing to the last element before operation and becomes null afterwards.
Try always keep reference to the node before last:
public int RemoveLast()
{
if (Head != null)
{
var curNode = Head;
// Corner case when there is only one node in the list
if (Head.Next == null)
{
Head = null;
Size--;
return curNode.value;
}
var beforeLastNode = curNode;
curNode = curNode.Next;
while (curNode.Next != null)
{
beforeLastNode = curNode;
curNode = curNode.Next;
}
var lastNodeValue = curNode.Value;
beforeLastNode.Next = null;
Size--;
return lastNodeValue;
}
return -1;
}
You need to make the curNode.Next value null on the previous node.
'curNode' is a local variable, setting it null doesn't do anything except maybe extend its GC life.
public int RemoveLast()
{
if (Head != null)
{
var curNode = Head;
var previousNode = null;
while (curNode.Next != null)
{
previousNode = curNode;
curNode = curNode.Next;
}
var lastNodeValue = curNode.Value;
if (previousNode == null)
Head = null;
else
previousNode.Next = null;
Size--;
return lastNodeValue;
}
return -1;
}
okay guys, after your help, I've rewritten this method that meets all the requirements and set to HeadNode null if there is only one node in linked list. So here we go:
public int RemoveLast()
{
if (HeadNode != null)
{
var currNode = HeadNode;
var prevNode = HeadNode;
if (HeadNode.Next == null)
{
HeadNode = null;
Size--;
return currNode.Value;
}
while (currNode.Next != null)
{
prevNode = currNode;
currNode = currNode.Next;
}
prevNode.Next = null;
Size--;
return currNode.Value;
}
return -1;
}
Thank you everyone who contributed in this thread. Happy Coding :)

Single Linked List : remove method

I am writing a single linked list in C#, could you please suggest to me if there any way to write a better remove method than the one I have:
using System;
class Node
{
public int data = int.MinValue;
public Node m_NextNode;
public Node(int data_in)
{
data = data_in;
}
public Node()
{
}
}
class LinkedList
{
private Node m_HeadNode;
public void InsertData(int data)
{
Node aCurrentNode = m_HeadNode;
if(m_HeadNode == null)
{
m_HeadNode = new Node();
m_HeadNode.data = data;
}
else
{
while(aCurrentNode.m_NextNode != null)
aCurrentNode = aCurrentNode.m_NextNode;
aCurrentNode.m_NextNode = new Node();
aCurrentNode.m_NextNode.data = data;
}
}
public void DisplayData()
{
Node aCurrentNode = m_HeadNode;
while (aCurrentNode != null)
{
Console.WriteLine("the value is {0}", aCurrentNode.data);
aCurrentNode = aCurrentNode.m_NextNode;
}
}
public void RemoveData(int data)
{
Node aCurrentNode = m_HeadNode;
while (aCurrentNode != null)
{
//if the data is present in head
//remove the head and reset the head
if (m_HeadNode.data == data)
{
m_HeadNode = null;
m_HeadNode = aCurrentNode.m_NextNode;
}
else
{
//else save the previous node
Node previousNode = aCurrentNode;
if (aCurrentNode != null)
{
//store the current node
Node NextNode = aCurrentNode.m_NextNode;
if (NextNode != null)
{
//store the next node
Node tempNode = NextNode.m_NextNode;
if (NextNode.data == data)
{
previousNode.m_NextNode = tempNode;
NextNode = null;
}
}
aCurrentNode = aCurrentNode.m_NextNode;
}
}
}
}
}
class Program
{
static void Main(string[] args)
{
LinkedList aLinkedList = new LinkedList();
aLinkedList.InsertData(10);
aLinkedList.InsertData(20);
aLinkedList.InsertData(30);
aLinkedList.InsertData(40);
aLinkedList.DisplayData();
aLinkedList.RemoveData(10);
aLinkedList.RemoveData(40);
aLinkedList.RemoveData(20);
aLinkedList.RemoveData(30);
aLinkedList.DisplayData();
Console.Read();
}
}
I would pull the 'if removing the head node' out of the while loop, and make the while loop simpler. Just keep track of the current and previous nodes, and switch the reference when you find the node to remove.
public void RemoveData(int data)
{
if (m_HeadNode == null)
return;
if (m_HeadNode.data == data)
{
m_HeadNode = m_HeadNode.m_NextNode;
}
else
{
Node previous = m_HeadNode;
Node current = m_HeadNode.m_NextNode;
while (current != null)
{
if (current.data == data)
{
// If we're removing the last entry in the list, current.Next
// will be null. That's OK, because setting previous.Next to
// null is the proper way to set the end of the list.
previous.m_NextNode = current.m_NextNode;
break;
}
previous = current;
current = current.m_NextNode;
}
}
}
Is RemoveData supposed to remove one instance of that integer from the list, or all instances? The previous method removes just the first one, here's one that removes all of them.
public void RemoveAllData(int data)
{
while (m_HeadNode != null && m_HeadNode.data == data)
{
m_HeadNode = m_HeadNode.m_NextNode;
}
if(m_HeadNode != null)
{
Node previous = m_HeadNode;
Node current = m_HeadNode.m_NextNode;
while (current != null)
{
if (current.data == data)
{
// If we're removing the last entry in the list, current.Next
// will be null. That's OK, because setting previous.Next to
// null is the proper way to set the end of the list.
previous.m_NextNode = current.m_NextNode;
// If we remove the current node, then we don't need to move
// forward in the list. The reference to previous.Next, below,
// will now point one element forward than it did before.
}
else
{
// Only move forward in the list if we actually need to,
// if we didn't remove an item.
previous = current;
}
current = previous.m_NextNode;
}
}
}
You have a line you do not need:
m_HeadNode = null;
m_HeadNode = aCurrentNode.m_NextNode;
You don't need to set m_HeadNode to null before you set it to something else.
public bool RemoveNode(int data) {
Node prev = null;
for (Node node = head; node != null; node = node.next) {
if (node.data == data) {
if (prev == null) head = node.next;
else prev.next = node.next;
return true;
}
prev = node;
}
return false;
}
public void RemoveData(int data)
{
if(null == m_HeadNode) return;
if(m_HeadNode.data == data)
{
// remove first node
}
else
{
Node current = m_HeadNode;
while((null != current.m_NextNode) && (current.m_NextNode.data != data))
current = current.m_NextNode;
if(null != current.m_NextNode)
{
// do remove node (since this sounds like homework, I'll leave that to you)
}
}
}
with only one local variable.
There is a bug in you code, imagine you have list that has 3 elements with data = 5 and you want to remove 5, you codes stores the head in aCurrentNode and starts the loop. There the condition is true so you move the head to the next. but aCurrentNode is not updated so in the next iteration it's pointing to the previous Head and aCurrentNode.m_NextNod would be your current Head, Hence you got yourself in a never ending loop!
public void Remove(int data)
{
for(var cur = new Node {Next = Head}; cur.Next != null; cur = cur.Next)
{
if (cur.Next.Data != data) continue;
if (cur.Next == Head)
Head = Head.Next;
else
cur.Next = cur.Next.Next;
}
}
a trick to make you loop simpler is to start with a fake node that points to head. This way you don't need to place an If to check head differently, however you need an if to set the head. the other trick is to check for next nodes data. that way you don't need to keep a previous Node.
public SLElement Remove(int index)
{
SLElement prev = _root;
if (prev == null) return null;
SLElement curr = _root._next;
for (int i = 1; i < index; i++)
{
if (curr == null) return null;
prev = curr;
curr = curr._next;
}
prev._next = curr._next;
curr._next = null;
return curr;
}
This deletes the element with a specific index, not with a specific value.
To Make really simple. Please follow the link. Below is a code snippet to remove item from a single link list.
public void DeleteNode(int nodeIndex)
{
int indexCounter = 0;
Node TempNode = StartNode;
Node PreviousNode = null;
while (TempNode.AddressHolder != null)
{
if (indexCounter == nodeIndex)
{
PreviousNode.AddressHolder = TempNode.AddressHolder;
break;
}
indexCounter++;
PreviousNode = TempNode;
TempNode = TempNode.AddressHolder;
}
}

Categories