Is Valid Generic Binary Search Tree with Recursion - c#

To check the validity of a Binary Search Tree, I use a method. But the method always returns false, when tested against a valid Binary Search Tree.
Online Demo Here
The code
public class Program
{
public static void Main()
{
BinarySearchTree<int> tree = new BinarySearchTree<int>();
tree.Insert(2);
tree.Insert(1);
tree.Insert(3);
Console.WriteLine(tree.IsValidBinarySearchTreeRecursive(tree.root).ToString()); // this is supposed to return true when tested against the simple tree above
}
}
public class Node<T> where T : IComparable
{
public Node<T> left;
public Node<T> right;
public T data;
public Node(T data)
{
this.left = null;
this.right = null;
this.data = data;
}
}
public class BinarySearchTree<T> where T : IComparable
{
public Node<T> root;
public BinarySearchTree()
{
this.root = null;
}
public bool Insert(T data)
{
Node<T> before = null;
Node<T> after = this.root;
while(after != null)
{
before = after;
if(data.CompareTo(after.data) < 0)
after = after.left;
else if(data.CompareTo(after.data) > 0)
after = after.right;
else
return false;
}
Node<T> newNode = new Node<T>(data);
if (this.root == null)
{
this.root = newNode;
}
else
{
if(data.CompareTo(before.data) < 0)
before.left = newNode;
else
before.right = newNode;
}
return true;
}
private bool _HelperForIsValidBinarySearchTreeRecursive(Node<T> node, T lower, T upper)
{
if (node == null)
return true;
T val = node.data;
Type nodeType = typeof(T);
if(nodeType.IsNumeric())
{
if(val.CompareTo(lower) <= 0)
return false;
if(val.CompareTo(upper) >= 0)
return false;
}
else
{
if(lower != null && val.CompareTo(lower) <= 0)
return false;
if(upper != null && val.CompareTo(upper) >= 0)
return false;
}
if(!_HelperForIsValidBinarySearchTreeRecursive(node.right, val, upper))
return false;
if(!_HelperForIsValidBinarySearchTreeRecursive(node.left, lower, val))
return false;
return true;
}
public bool IsValidBinarySearchTreeRecursive(Node<T> root)
{
Type nodeType = typeof(T);
if(nodeType.IsNumeric())
return _HelperForIsValidBinarySearchTreeRecursive(root, root.data, root.data);
return _HelperForIsValidBinarySearchTreeRecursive(root, default(T), default(T));
}
}
public static class StaticUtilities
{
private static readonly HashSet<Type> NumericTypes = new HashSet<Type>
{
typeof(int), typeof(double), typeof(decimal),
typeof(long), typeof(short), typeof(sbyte),
typeof(byte), typeof(ulong), typeof(ushort),
typeof(uint), typeof(float)
};
public static bool IsNumeric(this Type myType)
{
return NumericTypes.Contains(Nullable.GetUnderlyingType(myType) ?? myType);
}
}

Your problem is here:
if(val.CompareTo(lower) <= 0)
return false; // you are always hitting this line
if(val.CompareTo(upper) >= 0)
return false;
Because your T val = node.data; and your lower and even your upper are node.data from your first call.
So most probably the line to fix is
return _HelperForIsValidBinarySearchTreeRecursive(root, root.data, root.data);
as I guess your original intention was to compare the left and right with the root?
Based on this: https://www.geeksforgeeks.org/a-program-to-check-if-a-binary-tree-is-bst-or-not/
for your numeric approach, your solution should be:
/* false if this node violates the min/max constraints */
if (node.data < min || node.data > max)
{
return false;
}
So your code becomes:
if(val.CompareTo(lower) < 0)
return false; // you are always hitting this line
if(val.CompareTo(upper) > 0)
return false;
Then you will hit the next obstacle down the line. My suggestion for a solution, would be to change this:
private bool _HelperForIsValidBinarySearchTreeRecursive(Node<T> node, T lower, T upper)
To
private bool _HelperForIsValidBinarySearchTreeRecursive(Node<T> node, Node<T> leftNode<T> right)
and call like this:
_HelperForIsValidBinarySearchTreeRecursive(root, root.Left, root.Right)

My C# Solution
public bool IsBST()
{
return CheckBST(Root, default(T), default(T));
}
private bool CheckBST(TreeNode<T> root, T Min, T Max)
{
if (root == null)
{
return true;
}
if (!(root.Value.CompareTo(Min) <= 0 || root.Value.CompareTo(Max) >= 1))
{
return false;
}
return CheckBST(root.Left, Min, root.Value) && CheckBST(root.Right, root.Value, Max);
}

Related

Output binary tree (inorder traversal iterative) doesn't work

I need to output tree. But this output is incorrect.
My tree is:
`
public class ElTree
{
public int L;
public string inf;
public bool PR;
public ElTree(string inf)
{
this.inf = inf;
this.PR = false;
this.L = -1;
}
}
`
Class Tree is (Here other methods that I do with Tree, the method that output Tree in in the end. I`ve also tried to do output with recursion and it work correctly, so method Add() works correctly. But I have a task to do output in iterative way). For example, when I add tree lake "k"-root, "r"-right elem, "l"-left elem then my recursive method output "lkr" but iterative method output just "ll":
`
public class Tree
{
public ElTree[] T;
public int Coun { get { return _count; } }
private int _count;
public Tree(string inf)
{
ElTree temp = new ElTree(inf);
T = new ElTree[1];
T[T.Length-1] = temp;
}
public int Find(int V, string inf)
{
if (V == T.Length) return -1;
if (V != -1)
{
if (T[V].inf == inf) return V;
int temp = Find(T[V].L, inf);
if (temp != -1)
return temp;
return temp = Find(V + 1, inf);
}
return -1;
}
public bool Empty()
{
if (Coun == 0)
{
return true;
}
else
return false;
}
public bool Add(int i, string inf, char s)
{
ElTree temp = new ElTree(inf);
switch (s)
{
case 'L':
if (T[i].L == -1)
{
Array.Resize(ref T, T.Length + 1);
T[T.Length - 1] = temp;
T[i].L = T.Length - 1;
_count++;
return true;
}
else return false;
case 'R':
if (!T[i].PR)
{
Array.Resize(ref T, T.Length + 1);
T[T.Length - 1] = temp;
T[i].PR = true;
_count++;
return true;
}
else return false;
}
return false;
}
public void TreeInStringit(int i, ref string s)//iterative output
{
Stack<int> stack = new Stack<int>();
//int i = 0;
stack.Push(i);
do
{
while (T[i].L != -1 && i < T.Length)
{
i = T[i].L;
stack.Push(i);
}
s += T[i].inf;
while (T[i].PR && i < T.Length)
{
i++;
stack.Push(i);
}
if (stack.Count != 0) stack.Pop();
} while (stack.Count != 0);
}
public void String(int V, ref string s)//recursive output
{
ElTree temp = T[V];
if (temp.L != -1)
String(temp.L, ref s);
s += temp.inf;
if (temp.PR)
String(V+1, ref s);
}
`
When I add tree like root with two elements (one on left side and one on right) it output left side of tree 2 times. But I need output all tree.

Recursive Search Binary Search Tree with one parameter

I am trying to search through a binary search tree using a recursive method in C#.
So far I am able to successfully execute this method using two parameters:
public bool Search(int value, Node start)
{
if(start == null) {
return false;
}
else if(value == start.value) {
return true;
}
else {
if(value < start.value) {
Search(value, start.LeftChild.value);
}
else {
Search(value, start.RightChild.value);
}
}
}
However I would like to see if there's a way to use only one parameter such as using the following method signature:
public bool Search(int value){}
I also have the following that I can use to access the tree:
public class BinarySearchTree
{
private Node<int> root;
public Node<int> Root { get => root; set => root = value; }
public BinarySearchTree()
{
this.root = null;
}
}
public bool Search(int value)
{
return SearchTree(value, root);
bool SearchTree(int value, Node<int> start)
{
if(start == null)
return false;
else if(value == start.Value)
return true;
else
{
if(value < start.Value)
return SearchTree(value, start.LeftChild);
else
return SearchTree(value, start.RightChild);
}
}
}
if there's a way to use only one parameter such as using the following method signature:
sure. make it a method in Node class.
public class Node
{
public Node LeftChild, RightChild;
public int value;
public bool Search(int value)
{
if (value == this.value)
{
return true;
}
else
{
if (value < this.value)
{
return this.LeftChild?.Search(value) ?? false;
}
else
{
return this.RightChild?.Search(value) ?? false;
}
}
}
}
then for tree call it as tree.Root.Search(0);

How is a C# dictionary implemented? (C++) [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
Hi I'm using C++ to create a C# like dictionary object. I use a similar system of garbage collected ref objects for everything which are moved around in memory as the program runs. I've started off by implementing the dictionary aa a pretty standard hash table which is fine and I have this type of layout:
header + hash table -> storage -> element 0 -> object x
element 1 -> object y
element ... -> object ...
'+': In same allocation
'->': Indirect pointer ie different allocation
So 'header' contains just the table size. 'Hash table' is an array of integer offsets into the storage area.
The storage is implemented as a C# list ie an indirect pointer (ref object) to a self sizing array ie like a C++ vector.
Each element (Dictionary::Element) in the storage holds an id, an indirect pointer (ref object) to the actual object and an integer offset to the next element.
// C++ like pseudo code:
template< typename _Type_, typename _HashType_ = int >
class Dictionary
{
private:
class Element
{
_HashType_ m_id;
_Type_ m_object; // Ref object ie indirect pointer to actual object
int m_next; // Next element
}
int m_tablesize; // Power of 2
int* m_table; // Pointer here but in reality just a continuous block
// of memory after m_tablesize;
List<Element> m_storage; // Like a C++ vector
}
So my question is C#'s dictionary only allows one object at a time for any one hash.
Is there a simpler approach than the above implementation?
For example Dictonary::Add(_HashType_ id, _Type_ object) in the above implementation will bitwise AND the hash with the table size to get an index into the hash table then allocate an element with the id and object passed in and then it will add (push back) that element to the list (m_storage) of elements and fix up the linked list of elements:
template < typename _Type_, typename _HashType_ >
inline bool Dictionary< _Type_, _HashType_ >::Add( _HashType_ id, _Type_ element )
{
Element element = Element::New( id, object );
m_storage->Add( element );
// PushBack here fixes up the offset of the element in the storage array stored in
// the hash table (zero elements for this id) or the next pointer in the element
// (one or more elements exist for this id)
return PushBack( element );
}
Being a bit more explicit: is there a way to just have a header and hash table of objects ie:
header + hash table -> object x
object y
...
I ask this because C# imposes a one item limit on each hash when the more complex implementation above has no such limitations really except Remove would need to pass in both the id and the object and possibly you might want PushFront and PushBack instead of Add.
Thanks in advance and please don't ask why I'm doing this seemingly crazy thing just humor me! :)
You can use a decompiler to see how the dictionary is implemented in mscorlib. It is too long to include, but here is a snippet:
namespace System.Collections.Generic {
using System;
using System.Collections;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Runtime.Serialization;
using System.Security.Permissions;
[DebuggerTypeProxy(typeof(Mscorlib_DictionaryDebugView<,>))]
[DebuggerDisplay("Count = {Count}")]
[Serializable]
[System.Runtime.InteropServices.ComVisible(false)]
public class Dictionary<TKey,TValue>: IDictionary<TKey,TValue>, IDictionary, IReadOnlyDictionary<TKey, TValue>, ISerializable, IDeserializationCallback {
private struct Entry {
public int hashCode; // Lower 31 bits of hash code, -1 if unused
public int next; // Index of next entry, -1 if last
public TKey key; // Key of entry
public TValue value; // Value of entry
}
private int[] buckets;
private Entry[] entries;
private int count;
private int version;
private int freeList;
private int freeCount;
private IEqualityComparer<TKey> comparer;
private KeyCollection keys;
private ValueCollection values;
private Object _syncRoot;
// constants for serialization
private const String VersionName = "Version";
private const String HashSizeName = "HashSize"; // Must save buckets.Length
private const String KeyValuePairsName = "KeyValuePairs";
private const String ComparerName = "Comparer";
public Dictionary(): this(0, null) {}
public Dictionary(int capacity): this(capacity, null) {}
public Dictionary(IEqualityComparer<TKey> comparer): this(0, comparer) {}
public Dictionary(int capacity, IEqualityComparer<TKey> comparer) {
if (capacity < 0) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity);
if (capacity > 0) Initialize(capacity);
this.comparer = comparer ?? EqualityComparer<TKey>.Default;
}
public Dictionary(IDictionary<TKey,TValue> dictionary): this(dictionary, null) {}
public Dictionary(IDictionary<TKey,TValue> dictionary, IEqualityComparer<TKey> comparer):
this(dictionary != null? dictionary.Count: 0, comparer) {
if( dictionary == null) {
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.dictionary);
}
foreach (KeyValuePair<TKey,TValue> pair in dictionary) {
Add(pair.Key, pair.Value);
}
}
protected Dictionary(SerializationInfo info, StreamingContext context) {
//We can't do anything with the keys and values until the entire graph has been deserialized
//and we have a resonable estimate that GetHashCode is not going to fail. For the time being,
//we'll just cache this. The graph is not valid until OnDeserialization has been called.
HashHelpers.SerializationInfoTable.Add(this, info);
}
public IEqualityComparer<TKey> Comparer {
get {
return comparer;
}
}
public int Count {
get { return count - freeCount; }
}
public KeyCollection Keys {
get {
Contract.Ensures(Contract.Result<KeyCollection>() != null);
if (keys == null) keys = new KeyCollection(this);
return keys;
}
}
ICollection<TKey> IDictionary<TKey, TValue>.Keys {
get {
if (keys == null) keys = new KeyCollection(this);
return keys;
}
}
IEnumerable<TKey> IReadOnlyDictionary<TKey, TValue>.Keys {
get {
if (keys == null) keys = new KeyCollection(this);
return keys;
}
}
public ValueCollection Values {
get {
Contract.Ensures(Contract.Result<ValueCollection>() != null);
if (values == null) values = new ValueCollection(this);
return values;
}
}
ICollection<TValue> IDictionary<TKey, TValue>.Values {
get {
if (values == null) values = new ValueCollection(this);
return values;
}
}
IEnumerable<TValue> IReadOnlyDictionary<TKey, TValue>.Values {
get {
if (values == null) values = new ValueCollection(this);
return values;
}
}
public TValue this[TKey key] {
get {
int i = FindEntry(key);
if (i >= 0) return entries[i].value;
ThrowHelper.ThrowKeyNotFoundException();
return default(TValue);
}
set {
Insert(key, value, false);
}
}
public void Add(TKey key, TValue value) {
Insert(key, value, true);
}
void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> keyValuePair) {
Add(keyValuePair.Key, keyValuePair.Value);
}
bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> keyValuePair) {
int i = FindEntry(keyValuePair.Key);
if( i >= 0 && EqualityComparer<TValue>.Default.Equals(entries[i].value, keyValuePair.Value)) {
return true;
}
return false;
}
bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> keyValuePair) {
int i = FindEntry(keyValuePair.Key);
if( i >= 0 && EqualityComparer<TValue>.Default.Equals(entries[i].value, keyValuePair.Value)) {
Remove(keyValuePair.Key);
return true;
}
return false;
}
public void Clear() {
if (count > 0) {
for (int i = 0; i < buckets.Length; i++) buckets[i] = -1;
Array.Clear(entries, 0, count);
freeList = -1;
count = 0;
freeCount = 0;
version++;
}
}
public bool ContainsKey(TKey key) {
return FindEntry(key) >= 0;
}
public bool ContainsValue(TValue value) {
if (value == null) {
for (int i = 0; i < count; i++) {
if (entries[i].hashCode >= 0 && entries[i].value == null) return true;
}
}
else {
EqualityComparer<TValue> c = EqualityComparer<TValue>.Default;
for (int i = 0; i < count; i++) {
if (entries[i].hashCode >= 0 && c.Equals(entries[i].value, value)) return true;
}
}
return false;
}
private void CopyTo(KeyValuePair<TKey,TValue>[] array, int index) {
if (array == null) {
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
}
if (index < 0 || index > array.Length ) {
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
}
if (array.Length - index < Count) {
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
}
int count = this.count;
Entry[] entries = this.entries;
for (int i = 0; i < count; i++) {
if (entries[i].hashCode >= 0) {
array[index++] = new KeyValuePair<TKey,TValue>(entries[i].key, entries[i].value);
}
}
}
public Enumerator GetEnumerator() {
return new Enumerator(this, Enumerator.KeyValuePair);
}
IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator() {
return new Enumerator(this, Enumerator.KeyValuePair);
}
[System.Security.SecurityCritical] // auto-generated_required
public virtual void GetObjectData(SerializationInfo info, StreamingContext context) {
if (info==null) {
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.info);
}
info.AddValue(VersionName, version);
#if FEATURE_RANDOMIZED_STRING_HASHING
info.AddValue(ComparerName, HashHelpers.GetEqualityComparerForSerialization(comparer), typeof(IEqualityComparer<TKey>));
#else
info.AddValue(ComparerName, comparer, typeof(IEqualityComparer<TKey>));
#endif
info.AddValue(HashSizeName, buckets == null ? 0 : buckets.Length); //This is the length of the bucket array.
if( buckets != null) {
KeyValuePair<TKey, TValue>[] array = new KeyValuePair<TKey, TValue>[Count];
CopyTo(array, 0);
info.AddValue(KeyValuePairsName, array, typeof(KeyValuePair<TKey, TValue>[]));
}
}
private int FindEntry(TKey key) {
if( key == null) {
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
}
if (buckets != null) {
int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF;
for (int i = buckets[hashCode % buckets.Length]; i >= 0; i = entries[i].next) {
if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key)) return i;
}
}
return -1;
}
private void Initialize(int capacity) {
int size = HashHelpers.GetPrime(capacity);
buckets = new int[size];
for (int i = 0; i < buckets.Length; i++) buckets[i] = -1;
entries = new Entry[size];
freeList = -1;
}
private void Insert(TKey key, TValue value, bool add) {
if( key == null ) {
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
}
if (buckets == null) Initialize(0);
int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF;
int targetBucket = hashCode % buckets.Length;
#if FEATURE_RANDOMIZED_STRING_HASHING
int collisionCount = 0;
#endif
for (int i = buckets[targetBucket]; i >= 0; i = entries[i].next) {
if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key)) {
if (add) {
ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate);
}
entries[i].value = value;
version++;
return;
}
#if FEATURE_RANDOMIZED_STRING_HASHING
collisionCount++;
#endif
}
int index;
if (freeCount > 0) {
index = freeList;
freeList = entries[index].next;
freeCount--;
}
else {
if (count == entries.Length)
{
Resize();
targetBucket = hashCode % buckets.Length;
}
index = count;
count++;
}
entries[index].hashCode = hashCode;
entries[index].next = buckets[targetBucket];
entries[index].key = key;
entries[index].value = value;
buckets[targetBucket] = index;
version++;
#if FEATURE_RANDOMIZED_STRING_HASHING
if(collisionCount > HashHelpers.HashCollisionThreshold && HashHelpers.IsWellKnownEqualityComparer(comparer))
{
comparer = (IEqualityComparer<TKey>) HashHelpers.GetRandomizedEqualityComparer(comparer);
Resize(entries.Length, true);
}
#endif
}
public virtual void OnDeserialization(Object sender) {
SerializationInfo siInfo;
HashHelpers.SerializationInfoTable.TryGetValue(this, out siInfo);
if (siInfo==null) {
// It might be necessary to call OnDeserialization from a container if the container object also implements
// OnDeserialization. However, remoting will call OnDeserialization again.
// We can return immediately if this function is called twice.
// Note we set remove the serialization info from the table at the end of this method.
return;
}
int realVersion = siInfo.GetInt32(VersionName);
int hashsize = siInfo.GetInt32(HashSizeName);
comparer = (IEqualityComparer<TKey>)siInfo.GetValue(ComparerName, typeof(IEqualityComparer<TKey>));
if( hashsize != 0) {
buckets = new int[hashsize];
for (int i = 0; i < buckets.Length; i++) buckets[i] = -1;
entries = new Entry[hashsize];
freeList = -1;
KeyValuePair<TKey, TValue>[] array = (KeyValuePair<TKey, TValue>[])
siInfo.GetValue(KeyValuePairsName, typeof(KeyValuePair<TKey, TValue>[]));
if (array==null) {
ThrowHelper.ThrowSerializationException(ExceptionResource.Serialization_MissingKeys);
}
for (int i=0; i<array.Length; i++) {
if ( array[i].Key == null) {
ThrowHelper.ThrowSerializationException(ExceptionResource.Serialization_NullKey);
}
Insert(array[i].Key, array[i].Value, true);
}
}
else {
buckets = null;
}
version = realVersion;
HashHelpers.SerializationInfoTable.Remove(this);
}
private void Resize() {
Resize(HashHelpers.ExpandPrime(count), false);
}
private void Resize(int newSize, bool forceNewHashCodes) {
Contract.Assert(newSize >= entries.Length);
int[] newBuckets = new int[newSize];
for (int i = 0; i < newBuckets.Length; i++) newBuckets[i] = -1;
Entry[] newEntries = new Entry[newSize];
Array.Copy(entries, 0, newEntries, 0, count);
if(forceNewHashCodes) {
for (int i = 0; i < count; i++) {
if(newEntries[i].hashCode != -1) {
newEntries[i].hashCode = (comparer.GetHashCode(newEntries[i].key) & 0x7FFFFFFF);
}
}
}
for (int i = 0; i < count; i++) {
int bucket = newEntries[i].hashCode % newSize;
newEntries[i].next = newBuckets[bucket];
newBuckets[bucket] = i;
}
buckets = newBuckets;
entries = newEntries;
}
public bool Remove(TKey key) {
if(key == null) {
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
}
if (buckets != null) {
int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF;
int bucket = hashCode % buckets.Length;
int last = -1;
for (int i = buckets[bucket]; i >= 0; last = i, i = entries[i].next) {
if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key)) {
if (last < 0) {
buckets[bucket] = entries[i].next;
}
else {
entries[last].next = entries[i].next;
}
entries[i].hashCode = -1;
entries[i].next = freeList;
entries[i].key = default(TKey);
entries[i].value = default(TValue);
freeList = i;
freeCount++;
version++;
return true;
}
}
}
return false;
}
public bool TryGetValue(TKey key, out TValue value) {
int i = FindEntry(key);
if (i >= 0) {
value = entries[i].value;
return true;
}
value = default(TValue);
return false;
}
// This is a convenience method for the internal callers that were converted from using Hashtable.
// Many were combining key doesn't exist and key exists but null value (for non-value types) checks.
// This allows them to continue getting that behavior with minimal code delta. This is basically
// TryGetValue without the out param
internal TValue GetValueOrDefault(TKey key) {
int i = FindEntry(key);
if (i >= 0) {
return entries[i].value;
}
return default(TValue);
}
bool ICollection<KeyValuePair<TKey,TValue>>.IsReadOnly {
get { return false; }
}
void ICollection<KeyValuePair<TKey,TValue>>.CopyTo(KeyValuePair<TKey,TValue>[] array, int index) {
CopyTo(array, index);
}
void ICollection.CopyTo(Array array, int index) {
if (array == null) {
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
}
if (array.Rank != 1) {
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
}
if( array.GetLowerBound(0) != 0 ) {
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound);
}
if (index < 0 || index > array.Length) {
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
}
if (array.Length - index < Count) {
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
}
KeyValuePair<TKey,TValue>[] pairs = array as KeyValuePair<TKey,TValue>[];
if (pairs != null) {
CopyTo(pairs, index);
}
else if( array is DictionaryEntry[]) {
DictionaryEntry[] dictEntryArray = array as DictionaryEntry[];
Entry[] entries = this.entries;
for (int i = 0; i < count; i++) {
if (entries[i].hashCode >= 0) {
dictEntryArray[index++] = new DictionaryEntry(entries[i].key, entries[i].value);
}
}
}
else {
object[] objects = array as object[];
if (objects == null) {
ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
}
try {
int count = this.count;
Entry[] entries = this.entries;
for (int i = 0; i < count; i++) {
if (entries[i].hashCode >= 0) {
objects[index++] = new KeyValuePair<TKey,TValue>(entries[i].key, entries[i].value);
}
}
}
catch(ArrayTypeMismatchException) {
ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
}
}
}
IEnumerator IEnumerable.GetEnumerator() {
return new Enumerator(this, Enumerator.KeyValuePair);
}
bool ICollection.IsSynchronized {
get { return false; }
}
object ICollection.SyncRoot {
get {
if( _syncRoot == null) {
System.Threading.Interlocked.CompareExchange<Object>(ref _syncRoot, new Object(), null);
}
return _syncRoot;
}
}
bool IDictionary.IsFixedSize {
get { return false; }
}
bool IDictionary.IsReadOnly {
get { return false; }
}
< The rest of the code ommited...>
Its pretty similar to a std::map though a std::map doesn't require you to add an entry to it first ... you can add by just using the map's entry
ie.
std::map< int, int > m;
m[78]++;
will create and increment the int value represented by the key "78" ...

Creating a very simple linked list

I am trying to create a linked list just to see if I can, and I am having trouble getting my head around it. Does anyone have an example of a very simple implementation of Linked list using C#? All the examples I have found so far are quite overdone.
A Linked List, at its core is a bunch of Nodes linked together.
So, you need to start with a simple Node class:
public class Node {
public Node next;
public Object data;
}
Then your linked list will have as a member one node representing the head (start) of the list:
public class LinkedList {
private Node head;
}
Then you need to add functionality to the list by adding methods. They usually involve some sort of traversal along all of the nodes.
public void printAllNodes() {
Node current = head;
while (current != null)
{
Console.WriteLine(current.data);
current = current.next;
}
}
Also, inserting new data is another common operation:
public void Add(Object data) {
Node toAdd = new Node();
toAdd.data = data;
Node current = head;
// traverse all nodes (see the print all nodes method for an example)
current.next = toAdd;
}
This should provide a good starting point.
Based on what #jjnguy said, here's the full Console App example:
public class Node
{
public Node next;
public Object data;
}
public class LinkedList
{
private Node head;
public void printAllNodes()
{
Node current = head;
while (current != null)
{
Console.WriteLine(current.data);
current = current.next;
}
}
public void AddFirst(Object data)
{
Node toAdd = new Node();
toAdd.data = data;
toAdd.next = head;
head = toAdd;
}
public void AddLast(Object data)
{
if (head == null)
{
head = new Node();
head.data = data;
head.next = null;
}
else
{
Node toAdd = new Node();
toAdd.data = data;
Node current = head;
while (current.next != null)
{
current = current.next;
}
current.next = toAdd;
}
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Add First:");
LinkedList myList1 = new LinkedList();
myList1.AddFirst("Hello");
myList1.AddFirst("Magical");
myList1.AddFirst("World");
myList1.printAllNodes();
Console.WriteLine();
Console.WriteLine("Add Last:");
LinkedList myList2 = new LinkedList();
myList2.AddLast("Hello");
myList2.AddLast("Magical");
myList2.AddLast("World");
myList2.printAllNodes();
Console.ReadLine();
}
}
This one is nice:
namespace ConsoleApplication1
{
// T is the type of data stored in a particular instance of GenericList.
public class GenericList<T>
{
private class Node
{
// Each node has a reference to the next node in the list.
public Node Next;
// Each node holds a value of type T.
public T Data;
}
// The list is initially empty.
private Node head = null;
// Add a node at the beginning of the list with t as its data value.
public void AddNode(T t)
{
Node newNode = new Node();
newNode.Next = head;
newNode.Data = t;
head = newNode;
}
// The following method returns the data value stored in the last node in
// the list. If the list is empty, the default value for type T is
// returned.
public T GetFirstAdded()
{
// The value of temp is returned as the value of the method.
// The following declaration initializes temp to the appropriate
// default value for type T. The default value is returned if the
// list is empty.
T temp = default(T);
Node current = head;
while (current != null)
{
temp = current.Data;
current = current.Next;
}
return temp;
}
}
}
Test code:
static void Main(string[] args)
{
// Test with a non-empty list of integers.
GenericList<int> gll = new GenericList<int>();
gll.AddNode(5);
gll.AddNode(4);
gll.AddNode(3);
int intVal = gll.GetFirstAdded();
// The following line displays 5.
System.Console.WriteLine(intVal);
}
I encountered it on msdn here
Here is one with IEnumerable and a Recursive Reverse method though it is no faster than the while loop in the Reverse method both are O(n):
public class LinkedList<T> : IEnumerable
{
private Node<T> _head = null;
public Node<T> Add(T value)
{
var node = new Node<T> {Value = value};
if (_head == null)
{
_head = node;
}
else
{
var current = _head;
while (current.Next != null)
{
current = current.Next;
}
current.Next = node; //new head
}
return node;
}
public T Remove(Node<T> node)
{
if (_head == null)
return node.Value;
if (_head == node)
{
_head = _head.Next;
node.Next = null;
return node.Value;
}
var current = _head;
while (current.Next != null)
{
if (current.Next == node)
{
current.Next = node.Next;
return node.Value;
}
current = current.Next;
}
return node.Value;
}
public void Reverse()
{
Node<T> prev = null;
var current = _head;
if (current == null)
return;
while (current != null)
{
var next = current.Next;
current.Next = prev;
prev = current;
current = next;
}
_head = prev;
}
public void ReverseRecursive()
{
reverseRecursive(_head, null);
}
private void reverseRecursive(Node<T> current, Node<T> prev)
{
if (current.Next == null)
{
_head = current;
_head.Next = prev;
return;
}
var next = current.Next;
current.Next = prev;
reverseRecursive(next, current);
}
public IEnumerator<T> Enumerator()
{
var current = _head;
while (current != null)
{
yield return current.Value;
current = current.Next;
}
}
public IEnumerator GetEnumerator()
{
return Enumerator();
}
}
public class Node<T>
{
public T Value { get; set; }
public Node<T> Next { get; set; }
}
I am a beginner and this helped me:
class List
{
private Element Root;
}
First you create the class List which will contain all the methods.
Then you create the Node-Class, I will call it Element
class Element
{
public int Value;
public Element Next;
}
Then you can start adding methods to your List class. Here is a 'add' method for example.
public void Add(int value)
{
Element newElement = new Element();
newElement.Value = value;
Element rootCopy = Root;
Root = newElement;
newElement.Next = rootCopy;
Console.WriteLine(newElement.Value);
}
public class Node
{
private Object data;
public Node next {get;set;}
public Node(Object data)
{
this.data = data;
}
}
public class Linkedlist
{
Node head;
public void Add(Node n)
{
n.Next = this.Head;
this.Head = n;
}
}
using:
LinkedList sample = new LinkedList();
sample.add(new Node("first"));
sample.Add(new Node("second"))
I am giving an extract from the book "C# 6.0 in a Nutshell by Joseph Albahari and Ben Albahari"
Here’s a demonstration on the use of LinkedList:
var tune = new LinkedList<string>();
tune.AddFirst ("do"); // do
tune.AddLast ("so"); // do - so
tune.AddAfter (tune.First, "re"); // do - re- so
tune.AddAfter (tune.First.Next, "mi"); // do - re - mi- so
tune.AddBefore (tune.Last, "fa"); // do - re - mi - fa- so
tune.RemoveFirst(); // re - mi - fa - so
tune.RemoveLast(); // re - mi - fa
LinkedListNode<string> miNode = tune.Find ("mi");
tune.Remove (miNode); // re - fa
tune.AddFirst (miNode); // mi- re - fa
foreach (string s in tune) Console.WriteLine (s);
Here is a good implementation.
It is short, but implemented Add(x), Delete(x), Contain(x) and Print().
It avoid special process when add to empty list or delete the first element.
While most of other examples did special process when delete the first element.
The list can contain any data type.
using System;
class Node<Type> : LinkedList<Type>
{ // Why inherit from LinkedList? A: We need to use polymorphism.
public Type value;
public Node(Type value) { this.value = value; }
}
class LinkedList<Type>
{
Node<Type> next; // This member is treated as head in class LinkedList, but treated as next element in class Node.
/// <summary> if x is in list, return previos pointer of x. (We can see any class variable as a pointer.)
/// if not found, return the tail of the list. </summary>
protected LinkedList<Type> Previos(Type x)
{
LinkedList<Type> p = this; // point to head
for (; p.next != null; p = p.next)
if (p.next.value.Equals(x))
return p; // find x, return the previos pointer.
return p; // not found, p is the tail.
}
/// <summary> return value: true = success ; false = x not exist </summary>
public bool Contain(Type x) { return Previos(x).next != null ? true : false; }
/// <summary> return value: true = success ; false = fail to add. Because x already exist.
/// </summary> // why return value? If caller want to know the result, they don't need to call Contain(x) before, the action waste time.
public bool Add(Type x)
{
LinkedList<Type> p = Previos(x);
if (p.next != null) // Find x already in list
return false;
p.next = new Node<Type>(x);
return true;
}
/// <summary> return value: true = success ; false = x not exist </summary>
public bool Delete(Type x)
{
LinkedList<Type> p = Previos(x);
if (p.next == null)
return false;
//Node<Type> node = p.next;
p.next = p.next.next;
//node.Dispose(); // GC dispose automatically.
return true;
}
public void Print()
{
Console.Write("List: ");
for (Node<Type> node = next; node != null; node = node.next)
Console.Write(node.value.ToString() + " ");
Console.WriteLine();
}
}
class Test
{
static void Main()
{
LinkedList<int> LL = new LinkedList<int>();
if (!LL.Contain(0)) // Empty list
Console.WriteLine("0 is not exist.");
LL.Print();
LL.Add(0); // Add to empty list
LL.Add(1); LL.Add(2); // attach to tail
LL.Add(2); // duplicate add, 2 is tail.
if (LL.Contain(0))// Find existed element which is head
Console.WriteLine("0 is exist.");
LL.Print();
LL.Delete(0); // Delete head
LL.Delete(2); // Delete tail
if (!LL.Delete(0)) // Delete non-exist element
Console.WriteLine("0 is not exist.");
LL.Print();
Console.ReadLine();
}
}
By the way, the implementation in
http://www.functionx.com/csharp1/examples/linkedlist.htm
have some problem:
Delete() will fail when there is only 1 element.
(Throw exception at line "Head.Next = Current.Next;" because Current is null.)
Delete(position) will fail when deleting first element,
In other words, call Delete(0) will fail.
Dmytro did a good job, but here is a more concise version.
class Program
{
static void Main(string[] args)
{
LinkedList linkedList = new LinkedList(1);
linkedList.Add(2);
linkedList.Add(3);
linkedList.Add(4);
linkedList.AddFirst(0);
linkedList.Print();
}
}
public class Node
{
public Node(Node next, Object value)
{
this.next = next;
this.value = value;
}
public Node next;
public Object value;
}
public class LinkedList
{
public Node head;
public LinkedList(Object initial)
{
head = new Node(null, initial);
}
public void AddFirst(Object value)
{
head = new Node(head, value);
}
public void Add(Object value)
{
Node current = head;
while (current.next != null)
{
current = current.next;
}
current.next = new Node(null, value);
}
public void Print()
{
Node current = head;
while (current != null)
{
Console.WriteLine(current.value);
current = current.next;
}
}
}
public class DynamicLinkedList
{
private class Node
{
private object element;
private Node next;
public object Element
{
get { return this.element; }
set { this.element = value; }
}
public Node Next
{
get { return this.next; }
set { this.next = value; }
}
public Node(object element, Node prevNode)
{
this.element = element;
prevNode.next = this;
}
public Node(object element)
{
this.element = element;
next = null;
}
}
private Node head;
private Node tail;
private int count;
public DynamicLinkedList()
{
this.head = null;
this.tail = null;
this.count = 0;
}
public void AddAtLastPosition(object element)
{
if (head == null)
{
head = new Node(element);
tail = head;
}
else
{
Node newNode = new Node(element, tail);
tail = newNode;
}
count++;
}
public object GetLastElement()
{
object lastElement = null;
Node currentNode = head;
while (currentNode != null)
{
lastElement = currentNode.Element;
currentNode = currentNode.Next;
}
return lastElement;
}
}
Testing with:
static void Main(string[] args)
{
DynamicLinkedList list = new DynamicLinkedList();
list.AddAtLastPosition(1);
list.AddAtLastPosition(2);
list.AddAtLastPosition(3);
list.AddAtLastPosition(4);
list.AddAtLastPosition(5);
object lastElement = list.GetLastElement();
Console.WriteLine(lastElement);
}
public class Node<T>
{
public T item;
public Node<T> next;
public Node()
{
this.next = null;
}
}
class LinkList<T>
{
public Node<T> head { get; set; }
public LinkList()
{
this.head = null;
}
public void AddAtHead(T item)
{
Node<T> newNode = new Node<T>();
newNode.item = item;
if (this.head == null)
{
this.head = newNode;
}
else
{
newNode.next = head;
this.head = newNode;
}
}
public void AddAtTail(T item)
{
Node<T> newNode = new Node<T>();
newNode.item = item;
if (this.head == null)
{
this.head = newNode;
}
else
{
Node<T> temp = this.head;
while (temp.next != null)
{
temp = temp.next;
}
temp.next = newNode;
}
}
public void DeleteNode(T item)
{
if (this.head.item.Equals(item))
{
head = head.next;
}
else
{
Node<T> temp = head;
Node<T> tempPre = head;
bool matched = false;
while (!(matched = temp.item.Equals(item)) && temp.next != null)
{
tempPre = temp;
temp = temp.next;
}
if (matched)
{
tempPre.next = temp.next;
}
else
{
Console.WriteLine("Value not found!");
}
}
}
public bool searchNode(T item)
{
Node<T> temp = this.head;
bool matched = false;
while (!(matched = temp.item.Equals(item)) && temp.next != null)
{
temp = temp.next;
}
return matched;
}
public void DisplayList()
{
Console.WriteLine("Displaying List!");
Node<T> temp = this.head;
while (temp != null)
{
Console.WriteLine(temp.item);
temp = temp.next;
}
}
}
Add a Node class.
Then add a LinkedList class to implement the linked list
Add a test class to execute the linked list
namespace LinkedListProject
{
public class Node
{
public Node next;
public object data;
}
public class MyLinkedList
{
Node head;
public Node AddNodes(Object data)
{
Node node = new Node();
if (node.next == null)
{
node.data = data;
node.next = head;
head = node;
}
else
{
while (node.next != null)
node = node.next;
node.data = data;
node.next = null;
}
return node;
}
public void printnodes()
{
Node current = head;
while (current.next != null)
{
Console.WriteLine(current.data);
current = current.next;
}
Console.WriteLine(current.data);
}
}
[TestClass]
public class LinkedListExample
{
MyLinkedList linkedlist = new MyLinkedList();
[TestMethod]
public void linkedlisttest()
{
linkedlist.AddNodes("hello");
linkedlist.AddNodes("world");
linkedlist.AddNodes("now");
linkedlist.printnodes();
}
}
}
simple c# program to implement Single Link List with operations AddItemStart, AddItemEnd, RemoveItemStart, RemoveItemEnd and DisplayAllItems
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SingleLinkedList
{
class Program
{
Node head;
Node current;
int counter = 0;
public Program()
{
head = new Node();
current = head;
}
public void AddStart(object data)
{
Node newnode = new Node();
newnode.next = head.next;
newnode.data = data;
head.next = newnode;
counter++;
}
public void AddEnd(object data)
{
Node newnode = new Node();
newnode.data = data;
current.next = newnode;
current = newnode;
counter++;
}
public void RemoveStart()
{
if (counter > 0)
{
head.next = head.next.next;
counter--;
}
else
{
Console.WriteLine("No element exist in this linked list.");
}
}
public void RemoveEnd()
{
if (counter > 0)
{
Node prevNode = new Node();
Node cur = head;
while (cur.next != null)
{
prevNode = cur;
cur = cur.next;
}
prevNode.next = null;
}
else
{
Console.WriteLine("No element exist in this linked list.");
}
}
public void Display()
{
Console.Write("Head ->");
Node curr = head;
while (curr.next != null)
{
curr = curr.next;
Console.WriteLine(curr.data.ToString());
}
}
public class Node
{
public object data;
public Node next;
}
static void Main(string[] args)
{
Program p = new Program();
p.AddEnd(2);
p.AddStart(1);
p.AddStart(0);
p.AddEnd(3);
p.Display();
p.RemoveStart();
Console.WriteLine("Removed node from Start");
p.Display();
Console.WriteLine("Removed node from End");
p.RemoveEnd();
p.Display();
Console.ReadKey();
}
}
}
The selected answer doesn't have an iterator; it is more basic, but perhaps not as useful.
Here is one with an iterator/enumerator. My implementation is based on Sedgewick's bag; see http://algs4.cs.princeton.edu/13stacks/Bag.java.html
void Main()
{
var b = new Bag<string>();
b.Add("bike");
b.Add("erasmus");
b.Add("kumquat");
b.Add("beaver");
b.Add("racecar");
b.Add("barnacle");
foreach (var thing in b)
{
Console.WriteLine(thing);
}
}
// Define other methods and classes here
public class Bag<T> : IEnumerable<T>
{
public Node<T> first;// first node in list
public class Node<T>
{
public T item;
public Node<T> next;
public Node(T item)
{
this.item = item;
}
}
public void Add(T item)
{
Node<T> oldFirst = first;
first = new Node<T>(item);
first.next = oldFirst;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public IEnumerator<T> GetEnumerator()
{
return new BagEnumerator<T>(this);
}
public class BagEnumerator<V> : IEnumerator<T>
{
private Node<T> _head;
private Bag<T> _bag;
private Node<T> _curNode;
public BagEnumerator(Bag<T> bag)
{
_bag = bag;
_head = bag.first;
_curNode = default(Node<T>);
}
public T Current
{
get { return _curNode.item; }
}
object IEnumerator.Current
{
get { return Current; }
}
public bool MoveNext()
{
if (_curNode == null)
{
_curNode = _head;
if (_curNode == null)
return false;
return true;
}
if (_curNode.next == null)
return false;
else
{
_curNode = _curNode.next;
return true;
}
}
public void Reset()
{
_curNode = default(Node<T>); ;
}
public void Dispose()
{
}
}
}
I've created the following LinkedList code with many features. It is available for public under the CodeBase github public repo.
Classes:
Node and LinkedList
Getters and Setters: First and Last
Functions:
AddFirst(data), AddFirst(node), AddLast(data), RemoveLast(), AddAfter(node, data), RemoveBefore(node), Find(node), Remove(foundNode), Print(LinkedList)
using System;
using System.Collections.Generic;
namespace Codebase
{
public class Node
{
public object Data { get; set; }
public Node Next { get; set; }
public Node()
{
}
public Node(object Data, Node Next = null)
{
this.Data = Data;
this.Next = Next;
}
}
public class LinkedList
{
private Node Head;
public Node First
{
get => Head;
set
{
First.Data = value.Data;
First.Next = value.Next;
}
}
public Node Last
{
get
{
Node p = Head;
//Based partially on https://en.wikipedia.org/wiki/Linked_list
while (p.Next != null)
p = p.Next; //traverse the list until p is the last node.The last node always points to NULL.
return p;
}
set
{
Last.Data = value.Data;
Last.Next = value.Next;
}
}
public void AddFirst(Object data, bool verbose = true)
{
Head = new Node(data, Head);
if (verbose) Print();
}
public void AddFirst(Node node, bool verbose = true)
{
node.Next = Head;
Head = node;
if (verbose) Print();
}
public void AddLast(Object data, bool Verbose = true)
{
Last.Next = new Node(data);
if (Verbose) Print();
}
public Node RemoveFirst(bool verbose = true)
{
Node temp = First;
Head = First.Next;
if (verbose) Print();
return temp;
}
public Node RemoveLast(bool verbose = true)
{
Node p = Head;
Node temp = Last;
while (p.Next != temp)
p = p.Next;
p.Next = null;
if (verbose) Print();
return temp;
}
public void AddAfter(Node node, object data, bool verbose = true)
{
Node temp = new Node(data);
temp.Next = node.Next;
node.Next = temp;
if (verbose) Print();
}
public void AddBefore(Node node, object data, bool verbose = true)
{
Node temp = new Node(data);
Node p = Head;
while (p.Next != node) //Finding the node before
{
p = p.Next;
}
temp.Next = p.Next; //same as = node
p.Next = temp;
if (verbose) Print();
}
public Node Find(object data)
{
Node p = Head;
while (p != null)
{
if (p.Data == data)
return p;
p = p.Next;
}
return null;
}
public void Remove(Node node, bool verbose = true)
{
Node p = Head;
while (p.Next != node)
{
p = p.Next;
}
p.Next = node.Next;
if (verbose) Print();
}
public void Print()
{
Node p = Head;
while (p != null) //LinkedList iterator
{
Console.Write(p.Data + " ");
p = p.Next; //traverse the list until p is the last node.The last node always points to NULL.
}
Console.WriteLine();
}
}
}
Using #yogihosting answer when she used the Microsoft built-in LinkedList and LinkedListNode to answer the question, you can achieve the same results:
using System;
using System.Collections.Generic;
using Codebase;
namespace Cmd
{
static class Program
{
static void Main(string[] args)
{
var tune = new LinkedList(); //Using custom code instead of the built-in LinkedList<T>
tune.AddFirst("do"); // do
tune.AddLast("so"); // do - so
tune.AddAfter(tune.First, "re"); // do - re- so
tune.AddAfter(tune.First.Next, "mi"); // do - re - mi- so
tune.AddBefore(tune.Last, "fa"); // do - re - mi - fa- so
tune.RemoveFirst(); // re - mi - fa - so
tune.RemoveLast(); // re - mi - fa
Node miNode = tune.Find("mi"); //Using custom code instead of the built in LinkedListNode
tune.Remove(miNode); // re - fa
tune.AddFirst(miNode); // mi- re - fa
}
}
I have a doubly Linked List which can be used as a stack or a queue. If you look at the code and think about what it does and how it does it I bet you will understand everything about it. I am sorry but somehow I couldn't pate the full code here so I here is the link for the linkedlist(also I got the binary tree in the solution): https://github.com/szabeast/LinkedList_and_BinaryTree
A linked list is a node-based data structure. Each node designed with two portions (Data & Node Reference).Actually, data is always stored in Data portion (Maybe primitive data types eg Int, Float .etc or we can store user-defined data type also eg. Object reference) and similarly Node Reference should also contain the reference to next node, if there is no next node then the chain will end.
This chain will continue up to any node doesn't have a reference point to the next node.
Please find the source code from my tech blog - http://www.algonuts.info/linked-list-program-in-java.html
package info.algonuts;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
class LLNode {
int nodeValue;
LLNode childNode;
public LLNode(int nodeValue) {
this.nodeValue = nodeValue;
this.childNode = null;
}
}
class LLCompute {
private static LLNode temp;
private static LLNode previousNode;
private static LLNode newNode;
private static LLNode headNode;
public static void add(int nodeValue) {
newNode = new LLNode(nodeValue);
temp = headNode;
previousNode = temp;
if(temp != null)
{ compute(); }
else
{ headNode = newNode; } //Set headNode
}
private static void compute() {
if(newNode.nodeValue < temp.nodeValue) { //Sorting - Ascending Order
newNode.childNode = temp;
if(temp == headNode)
{ headNode = newNode; }
else if(previousNode != null)
{ previousNode.childNode = newNode; }
}
else
{
if(temp.childNode == null)
{ temp.childNode = newNode; }
else
{
previousNode = temp;
temp = temp.childNode;
compute();
}
}
}
public static void display() {
temp = headNode;
while(temp != null) {
System.out.print(temp.nodeValue+" ");
temp = temp.childNode;
}
}
}
public class LinkedList {
//Entry Point
public static void main(String[] args) {
//First Set Input Values
List <Integer> firstIntList = new ArrayList <Integer>(Arrays.asList(50,20,59,78,90,3,20,40,98));
Iterator<Integer> ptr = firstIntList.iterator();
while(ptr.hasNext())
{ LLCompute.add(ptr.next()); }
System.out.println("Sort with first Set Values");
LLCompute.display();
System.out.println("\n");
//Second Set Input Values
List <Integer> secondIntList = new ArrayList <Integer>(Arrays.asList(1,5,8,100,91));
ptr = secondIntList.iterator();
while(ptr.hasNext())
{ LLCompute.add(ptr.next()); }
System.out.println("Sort with first & Second Set Values");
LLCompute.display();
System.out.println();
}
}

Is there a .NET data structure with the following characteristics of a Binary Search Tree?

I know that SortedDictionary is a binary search tree (and it can almost do what I need to do!) but I can't figure out how to do everything I need in the correct complexity.
So here are the constraints (and the data structure which I know has it)
Inserting and Deletion in O(log n) (SortedDictionary)
Search in O(log n) (SortedDictionary & SortedList)
Iteration from one searched element to another in O(log n) + O(m) (where m is the number of elements in between) (SortedList)
As you can see, I don't know how to get SortedDictionary to do number 3. Basically what I need to do is get all the elements with a range without iterating the set.
Please tell me if my question isn't clear.
This seems to describe a B+ tree perfectly: http://en.wikipedia.org/wiki/B%2B_tree :
Inserting a record requires O(log(n)) operations in the worst case
Finding a record requires O(log(n)) operations in the worst case
Performing a range query with k elements occurring within the range requires O(log(n) + k) operations in the worst case.
A C# implementation seems to exist here: http://bplusdotnet.sourceforge.net/
I don't think there is a collection in the framework that does what you describe, although I could be wrong.
What you are looking for is a linked list that is indexed with a binary tree. This would provide you O(log n) insertion, deletion and search using the binary tree, with O(m) traversal using the linked list.
You might want to have a look at the C5 Generic Collections Library. Although there doesn't appear to be a collection that fits your description there, you might be able to marry together their TreeSet<T> and LinkedList<T> objects, creating a new SortedLinkedList<T> object.
Some of the suggestions were pretty good, but I decided to implement the collection myself (it sounded fun). I started with the .NET implementation of SortedDictionary, and heavily modified it to do what I needed it to do
Just so other people can benefit from my work, here is the class:
internal delegate void TreeWalkAction<Key, Value>(BinaryTreeSearch<Key, Value>.Node node);
internal delegate bool TreeWalkTerminationPredicate<Key, Value>(BinaryTreeSearch<Key, Value>.Node node);
internal class BinaryTreeSearch<Key, Value>
{
// Fields
private IComparer<Key> comparer;
private int count;
private Node root;
private int version;
// Methods
public BinaryTreeSearch(IComparer<Key> comparer)
{
if (comparer == null)
{
this.comparer = Comparer<Key>.Default;
}
else
{
this.comparer = comparer;
}
}
private Node First
{
get
{
if (root == null) return null;
Node n = root;
while (n.Left != null)
{
n = n.Left;
}
return n;
}
}
public Key Min
{
get
{
Node first = First;
return first == null ? default(Key) : first.Key;
}
}
public Key Max
{
get
{
if (root == null) return default(Key);
Node n = root;
while (n.Right != null)
{
n = n.Right;
}
return n.Key;
}
}
public List<Value> this[Key key]
{
get
{
Node n = FindNode(key);
return n == null ? new List<Value>() : n.Values;
}
}
public List<Value> GetRange(Key start, Key end)
{
Node node = FindNextNode(start);
List<Value> ret = new List<Value>();
InOrderTreeWalk(node,
aNode => ret.AddRange(aNode.Values),
aNode => comparer.Compare(end, aNode.Key) < 0);
return ret;
}
public void Add(Key key, Value value)
{
if (this.root == null)
{
this.root = new Node(null, key, value, false);
this.count = 1;
}
else
{
Node root = this.root;
Node node = null;
Node grandParent = null;
Node greatGrandParent = null;
int num = 0;
while (root != null)
{
num = this.comparer.Compare(key, root.Key);
if (num == 0)
{
root.Values.Add(value);
count++;
return;
}
if (Is4Node(root))
{
Split4Node(root);
if (IsRed(node))
{
this.InsertionBalance(root, ref node, grandParent, greatGrandParent);
}
}
greatGrandParent = grandParent;
grandParent = node;
node = root;
root = (num < 0) ? root.Left : root.Right;
}
Node current = new Node(node, key, value);
if (num > 0)
{
node.Right = current;
}
else
{
node.Left = current;
}
if (node.IsRed)
{
this.InsertionBalance(current, ref node, grandParent, greatGrandParent);
}
this.root.IsRed = false;
this.count++;
this.version++;
}
}
public void Clear()
{
this.root = null;
this.count = 0;
this.version++;
}
public bool Contains(Key key)
{
return (this.FindNode(key) != null);
}
internal Node FindNode(Key item)
{
int num;
for (Node node = this.root; node != null; node = (num < 0) ? node.Left : node.Right)
{
num = this.comparer.Compare(item, node.Key);
if (num == 0)
{
return node;
}
}
return null;
}
internal Node FindNextNode(Key key)
{
int num;
Node node = root;
while (true)
{
num = comparer.Compare(key, node.Key);
if (num == 0)
{
return node;
}
else if (num < 0)
{
if (node.Left == null) return node;
node = node.Left;
}
else
{
node = node.Right;
}
}
}
private static Node GetSibling(Node node, Node parent)
{
if (parent.Left == node)
{
return parent.Right;
}
return parent.Left;
}
internal void InOrderTreeWalk(Node start, TreeWalkAction<Key, Value> action, TreeWalkTerminationPredicate<Key, Value> terminationPredicate)
{
Node node = start;
while (node != null && !terminationPredicate(node))
{
action(node);
node = node.Next;
}
}
private void InsertionBalance(Node current, ref Node parent, Node grandParent, Node greatGrandParent)
{
Node node;
bool flag = grandParent.Right == parent;
bool flag2 = parent.Right == current;
if (flag == flag2)
{
node = flag2 ? RotateLeft(grandParent) : RotateRight(grandParent);
}
else
{
node = flag2 ? RotateLeftRight(grandParent) : RotateRightLeft(grandParent);
parent = greatGrandParent;
}
grandParent.IsRed = true;
node.IsRed = false;
this.ReplaceChildOfNodeOrRoot(greatGrandParent, grandParent, node);
}
private static bool Is2Node(Node node)
{
return ((IsBlack(node) && IsNullOrBlack(node.Left)) && IsNullOrBlack(node.Right));
}
private static bool Is4Node(Node node)
{
return (IsRed(node.Left) && IsRed(node.Right));
}
private static bool IsBlack(Node node)
{
return ((node != null) && !node.IsRed);
}
private static bool IsNullOrBlack(Node node)
{
if (node != null)
{
return !node.IsRed;
}
return true;
}
private static bool IsRed(Node node)
{
return ((node != null) && node.IsRed);
}
private static void Merge2Nodes(Node parent, Node child1, Node child2)
{
parent.IsRed = false;
child1.IsRed = true;
child2.IsRed = true;
}
public bool Remove(Key key, Value value)
{
if (this.root == null)
{
return false;
}
Node root = this.root;
Node parent = null;
Node node3 = null;
Node match = null;
Node parentOfMatch = null;
bool flag = false;
while (root != null)
{
if (Is2Node(root))
{
if (parent == null)
{
root.IsRed = true;
}
else
{
Node sibling = GetSibling(root, parent);
if (sibling.IsRed)
{
if (parent.Right == sibling)
{
RotateLeft(parent);
}
else
{
RotateRight(parent);
}
parent.IsRed = true;
sibling.IsRed = false;
this.ReplaceChildOfNodeOrRoot(node3, parent, sibling);
node3 = sibling;
if (parent == match)
{
parentOfMatch = sibling;
}
sibling = (parent.Left == root) ? parent.Right : parent.Left;
}
if (Is2Node(sibling))
{
Merge2Nodes(parent, root, sibling);
}
else
{
TreeRotation rotation = RotationNeeded(parent, root, sibling);
Node newChild = null;
switch (rotation)
{
case TreeRotation.LeftRotation:
sibling.Right.IsRed = false;
newChild = RotateLeft(parent);
break;
case TreeRotation.RightRotation:
sibling.Left.IsRed = false;
newChild = RotateRight(parent);
break;
case TreeRotation.RightLeftRotation:
newChild = RotateRightLeft(parent);
break;
case TreeRotation.LeftRightRotation:
newChild = RotateLeftRight(parent);
break;
}
newChild.IsRed = parent.IsRed;
parent.IsRed = false;
root.IsRed = true;
this.ReplaceChildOfNodeOrRoot(node3, parent, newChild);
if (parent == match)
{
parentOfMatch = newChild;
}
node3 = newChild;
}
}
}
int num = flag ? -1 : this.comparer.Compare(key, root.Key);
if (num == 0)
{
flag = true;
match = root;
parentOfMatch = parent;
}
node3 = parent;
parent = root;
if (num < 0)
{
root = root.Left;
}
else
{
root = root.Right;
}
}
if (match != null)
{
if (match.Values.Remove(value))
{
this.count--;
}
if (match.Values.Count == 0)
{
this.ReplaceNode(match, parentOfMatch, parent, node3);
}
}
if (this.root != null)
{
this.root.IsRed = false;
}
this.version++;
return flag;
}
private void ReplaceChildOfNodeOrRoot(Node parent, Node child, Node newChild)
{
if (parent != null)
{
if (parent.Left == child)
{
parent.Left = newChild;
}
else
{
parent.Right = newChild;
}
if (newChild != null) newChild.Parent = parent;
}
else
{
this.root = newChild;
}
}
private void ReplaceNode(Node match, Node parentOfMatch, Node succesor, Node parentOfSuccesor)
{
if (succesor == match)
{
succesor = match.Left;
}
else
{
if (succesor.Right != null)
{
succesor.Right.IsRed = false;
}
if (parentOfSuccesor != match)
{
parentOfSuccesor.Left = succesor.Right; if (succesor.Right != null) succesor.Right.Parent = parentOfSuccesor;
succesor.Right = match.Right; if (match.Right != null) match.Right.Parent = succesor;
}
succesor.Left = match.Left; if (match.Left != null) match.Left.Parent = succesor;
}
if (succesor != null)
{
succesor.IsRed = match.IsRed;
}
this.ReplaceChildOfNodeOrRoot(parentOfMatch, match, succesor);
}
private static Node RotateLeft(Node node)
{
Node right = node.Right;
node.Right = right.Left; if (right.Left != null) right.Left.Parent = node;
right.Left = node; if (node != null) node.Parent = right;
return right;
}
private static Node RotateLeftRight(Node node)
{
Node left = node.Left;
Node right = left.Right;
node.Left = right.Right; if (right.Right != null) right.Right.Parent = node;
right.Right = node; if (node != null) node.Parent = right;
left.Right = right.Left; if (right.Left != null) right.Left.Parent = left;
right.Left = left; if (left != null) left.Parent = right;
return right;
}
private static Node RotateRight(Node node)
{
Node left = node.Left;
node.Left = left.Right; if (left.Right != null) left.Right.Parent = node;
left.Right = node; if (node != null) node.Parent = left;
return left;
}
private static Node RotateRightLeft(Node node)
{
Node right = node.Right;
Node left = right.Left;
node.Right = left.Left; if (left.Left != null) left.Left.Parent = node;
left.Left = node; if (node != null) node.Parent = left;
right.Left = left.Right; if (left.Right != null) left.Right.Parent = right;
left.Right = right; if (right != null) right.Parent = left;
return left;
}
private static TreeRotation RotationNeeded(Node parent, Node current, Node sibling)
{
if (IsRed(sibling.Left))
{
if (parent.Left == current)
{
return TreeRotation.RightLeftRotation;
}
return TreeRotation.RightRotation;
}
if (parent.Left == current)
{
return TreeRotation.LeftRotation;
}
return TreeRotation.LeftRightRotation;
}
private static void Split4Node(Node node)
{
node.IsRed = true;
node.Left.IsRed = false;
node.Right.IsRed = false;
}
// Properties
public IComparer<Key> Comparer
{
get
{
return this.comparer;
}
}
public int Count
{
get
{
return this.count;
}
}
internal class Node
{
// Fields
private bool isRed;
private Node left, right, parent;
private Key key;
private List<Value> values;
// Methods
public Node(Node parent, Key item, Value value) : this(parent, item, value, true)
{
}
public Node(Node parent, Key key, Value value, bool isRed)
{
this.key = key;
this.parent = parent;
this.values = new List<Value>(new Value[] { value });
this.isRed = isRed;
}
// Properties
public bool IsRed
{
get
{
return this.isRed;
}
set
{
this.isRed = value;
}
}
public Key Key
{
get
{
return this.key;
}
set
{
this.key = value;
}
}
public List<Value> Values { get { return values; } }
public Node Left
{
get
{
return this.left;
}
set
{
this.left = value;
}
}
public Node Right
{
get
{
return this.right;
}
set
{
this.right = value;
}
}
public Node Parent
{
get
{
return this.parent;
}
set
{
this.parent = value;
}
}
public Node Next
{
get
{
if (right == null)
{
if (parent == null)
{
return null; // this puppy must be lonely
}
else if (parent.Left == this) // this is a left child
{
return parent;
}
else
{
//this is a right child, we need to go up the tree
//until we find a left child. Then the parent will be the next
Node n = this;
do
{
n = n.parent;
if (n.parent == null)
{
return null; // this must have been a node along the right edge of the tree
}
} while (n.parent.right == n);
return n.parent;
}
}
else // there is a right child.
{
Node go = right;
while (go.left != null)
{
go = go.left;
}
return go;
}
}
}
public override string ToString()
{
return key.ToString() + " - [" + string.Join(", ", new List<string>(values.Select<Value, string>(o => o.ToString())).ToArray()) + "]";
}
}
internal enum TreeRotation
{
LeftRightRotation = 4,
LeftRotation = 1,
RightLeftRotation = 3,
RightRotation = 2
}
}
and a quick unit test (which doesn't actually cover all the code, so there might still be some bugs):
[TestFixture]
public class BTSTest
{
private class iC : IComparer<int>{public int Compare(int x, int y){return x.CompareTo(y);}}
[Test]
public void Test()
{
BinaryTreeSearch<int, int> bts = new BinaryTreeSearch<int, int>(new iC());
bts.Add(5, 1);
bts.Add(5, 2);
bts.Add(6, 2);
bts.Add(2, 3);
bts.Add(8, 2);
bts.Add(10, 11);
bts.Add(9, 4);
bts.Add(3, 32);
bts.Add(12, 32);
bts.Add(8, 32);
bts.Add(9, 32);
Assert.AreEqual(11, bts.Count);
Assert.AreEqual(2, bts.Min);
Assert.AreEqual(12, bts.Max);
List<int> val = bts[5];
Assert.AreEqual(2, val.Count);
Assert.IsTrue(val.Contains(1));
Assert.IsTrue(val.Contains(2));
val = bts[6];
Assert.AreEqual(1, val.Count);
Assert.IsTrue(val.Contains(2));
Assert.IsTrue(bts.Contains(5));
Assert.IsFalse(bts.Contains(-1));
val = bts.GetRange(5, 8);
Assert.AreEqual(5, val.Count);
Assert.IsTrue(val.Contains(1));
Assert.IsTrue(val.Contains(32));
Assert.AreEqual(3, val.Count<int>(num => num == 2));
bts.Remove(8, 32);
bts.Remove(5, 2);
Assert.AreEqual(9, bts.Count);
val = bts.GetRange(5, 8);
Assert.AreEqual(3, val.Count);
Assert.IsTrue(val.Contains(1));
Assert.AreEqual(2, val.Count<int>(num => num == 2));
bts.Remove(2, 3);
Assert.IsNull(bts.FindNode(2));
bts.Remove(12, 32);
Assert.IsNull(bts.FindNode(12));
Assert.AreEqual(3, bts.Min);
Assert.AreEqual(10, bts.Max);
bts.Remove(9, 4);
bts.Remove(5, 1);
bts.Remove(6, 2);
}
}
Check out System.Collections.ObjectModel.KeyedCollection<TKey, TItem> - it might not suit your requirements but it seems like a good fit, as it provides an internal lookup dictionary that enables O(1) retrieval of items by index and approaching O(1) by key.
The caveat is that it is intended to store objects where the key is defined as a property on the object, so unless you can mash your input data to fit, it won't be appropriate.
I would include some more information on what data you are intending to store and the volume, as this might help provide alternatives.

Categories

Resources