I have a custom queue class that is implemented via linked list, but I can't figure out how ot implement IEnumerable for something that is not array.
It's easy to implement it using Dequeue(), but I don't want enumeration to mutate my collection.
Here is my code for DQueue class:
class DQueue<Item> : IEnumerable<Item>
{
private Node<Item> startNode;
private Node<Item> lastNode;
private int _size;
public DQueue()
{
_size = 0;
}
public void Enqueue(Item item)
{
_size++;
if (startNode == null) {
startNode = new Node<Item>();
startNode.data = item;
lastNode = startNode;
} else {
Node<Item> temp = new Node<Item>();
temp.data = item;
lastNode.next = temp;
lastNode = temp;
}
}
public Item Dequeue()
{
Item temp = startNode.data;
startNode = startNode.next;
_size--;
return temp;
}
public bool IsEmpty()
{
return startNode == null;
}
public int Size()
{
return _size;
}
private class Node<InnerItem>
{
public InnerItem data;
public Node<InnerItem> next;
public Node()
{
next = null;
}
}
// IEnumerable
public IEnumerator<Item> GetEnumerator()
{
Node<Item> current;
for (int i = 0; i < _size; i++) {
//yield return values[i];
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
Suggest next solve, iteration from start node:
public IEnumerator<Item> GetEnumerator()
{
for (Node<Item> item = startNode; item != null; item = item.next)
{
yield return item.data;
}
}
Related
I am writing a term paper and am having trouble checking it. The point of this work is to create a circular two-way array of Client class objects. I sent it to the manager, and he said that some aspects of the program are not correct. He said:
Why does the Сlient class use an array of references private Operation[] operations; instead of an array of objects of the Operation class?
Why is the Bank class using an address list private DoublyLinkedList<Client> arrayClient; instead of an array-queue?
// Operation class
using System;
namespace DepositLibrary
{
// Класс операции
public class Operation
{
// Дата операции
public DateTime date;
// Депозит операции
public decimal deposit;
public Operation(DateTime dateIn, decimal depositIn)
{
date = dateIn;
deposit = depositIn;
}
// Получение даты операции
public DateTime GetDateTime { get => date; }
// Получение депозита операции
public decimal GetDeposit { get => deposit; }
}
}
// Client class
using System;
using System.Collections.Generic;
namespace DepositLibrary
{
//Класс клиент
public class Client
{
//Фамилия клиента
public string surname;
//Текущий депозит лицевого счета
public decimal currentDeposit;
// Совершенные операции клиента
private Operation[] operations;
public Client(string surnameIn)
{
surname = surnameIn;
operations = new Operation[0];
}
//Получить фамилию
public string GetSurname { get => surname; }
//Получить все совершенные операции
public Operation[] Operations { get => operations; }
//Получить текущий депозит лицевого счета
public decimal GetDeposit { get => currentDeposit; }
}
}
// Bank class
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace DepositLibrary
{
// Класс банк
public class Bank
{
// Наименование банка
private string nameBank;
// Клиентские банковские книги
private DoublyLinkedList<Client> arrayClient;
public Bank(string _nameBank)
{
nameBank = _nameBank;
arrayClient = new DoublyLinkedList<Client>();
}
//Получить наименование банка
public string GetBankName { get => nameBank; }
//Получить клиентские банковские книги
public DoublyLinkedList<Client> GetListClients { get => arrayClient; }
}
public class DoublyNode<T>
{
public DoublyNode(T data)
{
Data = data;
}
public T Data { get; set; }
public DoublyNode<T> Previous { get; set; }
public DoublyNode<T> Next { get; set; }
}
public class DoublyLinkedList<T> : IEnumerable<T> // двусвязный список
{
public DoublyNode<T> head; // головной/первый элемент
public DoublyNode<T> tail; // последний/хвостовой элемент
int count; // количество элементов в списке
// добавление элемента
public void Add(T data)
{
DoublyNode<T> node = new DoublyNode<T>(data);
if (head == null)
head = node;
else
{
tail.Next = node;
node.Previous = tail;
// for looped array
node.Next = head;
head.Previous = node;
}
tail = node;
count++;
}
public void AddFirst(T data)
{
DoublyNode<T> node = new DoublyNode<T>(data);
DoublyNode<T> temp = head;
node.Next = temp;
head = node;
if (count == 0)
tail = head;
else
{
temp.Previous = node;
// for looped
tail.Next = node;
node.Previous = tail;
}
count++;
}
// удаление
public bool Remove(T data)
{
DoublyNode<T> current = head;
// поиск удаляемого узла
do
{
if (current.Data.Equals(data))
{
break;
}
current = current.Next;
} while (!current.Data.Equals(head.Data));
if (current != null)
{
// если узел не последний
if (!current.Next.Data.Equals(head.Data))
{
current.Next.Previous = current.Previous;
}
else
{
// если последний, переустанавливаем tail
tail = current.Previous;
// for looped
tail.Next = head;
}
// если узел не первый
if (!current.Previous.Data.Equals(tail.Data))
{
current.Previous.Next = current.Next;
}
else
{
// если первый, переустанавливаем head
head = current.Next;
// for looped
head.Previous = tail;
}
count--;
return true;
}
return false;
}
public int Count { get { return count; } }
public bool IsEmpty { get { return count == 0; } }
public void Clear()
{
head = null;
tail = null;
count = 0;
}
public bool Contains(T data)
{
DoublyNode<T> current = head;
do
{
if (current.Data.Equals(data))
return true;
current = current.Next;
} while (!current.Data.Equals(head.Data));
return false;
}
IEnumerator GetEnumerator()
{
return ((IEnumerable)this).GetEnumerator();
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
DoublyNode<T> current = head;
do
{
yield return current.Data;
current = current.Next;
} while (!current.Data.Equals(head.Data));
}
public IEnumerable<T> BackEnumerator()
{
DoublyNode<T> current = tail;
do
{
yield return current.Data;
current = current.Previous;
} while (!current.Data.Equals(tail.Data));
}
IEnumerator IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
}
}
I tried for a very long time to understand what he wants from me, but didn't come to a normal result. I would be grateful for any help and advice. Thank you!
I have my own template class, how to make the foreach loop work for it. I understand how to do this for a template class with one template type, but for two - I do not understand. I understand that you need to inherit from IEnumerable and IEnumerator, but I can't find a suitable example and don't understand what to do.
using System;
using System.Collections;
using System.Collections.Generic;
namespace CCS8
{
public class Node<KEY, VALUE>
{
public Node(KEY k, VALUE v)
{
this.k = k;
this.v = v;
}
public KEY k { get; set; }
public VALUE v { get; set; }
public Node<KEY, VALUE> Next { get; set; }
}
public class MyList<K, V>
{
Node<K, V> head;
Node<K, V> tail;
int count;
int possition = -1;
public bool MoveNext()
{
if (possition < count - 1)
{
possition++;
return true;
}
else
{
return false;
}
}
public void Reset()
{
possition = -1;
}
public void Add(K k, V v)
{
Node<K, V> node = new Node<K, V>(k, v);
if (head == null)
head = node;
else
tail.Next = node;
tail = node;
count++;
}
public int Count { get { return count; } }
public V ValueByIndex(int i)
{
int j = 0;
Node<K, V> current = head;
while (j != i)
{
current = current.Next;
j++;
}
return current.v;
}
}
class Program
{
static void Main(string[] args)
{
MyList<int, String> l = new MyList<int, String>();
// добавление элементов
l.Add(1, "Line1");
l.Add(2, "Line2");
l.Add(3, "Line3");
l.Add(4, "Line4");
Console.WriteLine("3th elemnt: " + l.ValueByIndex(2));
Console.WriteLine("Elements count: " + l.Count);
foreach (var i in l)
{
Console.WriteLine(i);
}
}
}
}
Hi guys help me please.
I wrote the code for a binary search tree, but for some reason I'm wildly stupid in post-traverse and searching. Can someone help with writing a postorder and search.
Thank you and sorry for bad english. Thank you very much again.
I don't show you my Remove and Contains method because it does not important. If you want to see them , i can show it.
My BinaryTreeNode class
public class BinaryTreeNode<T> : IComparable<T>
where T : IComparable
{
public BinaryTreeNode(T value)
{
Value = value;
}
public BinaryTreeNode<T> Left { get; set; }
public BinaryTreeNode<T> Right { get; set; }
public T Value { get; }
public int CompareTo(T other)
{
return Value.CompareTo(other);
}
public IEnumerator<T> GetEnumerator()
{
var leftEnumerable = (IEnumerable<T>) Left ?? new T[0];
var rightEnumerable = (IEnumerable<T>) Right ?? new T[0];
return leftEnumerable.Concat(new[] {Value})
.Concat(rightEnumerable)
.GetEnumerator();
}
}
My BinaryTree class :
public class BinaryTree<T>
where T : IComparable
{
private BinaryTreeNode<T> _head;
public int Count { get; private set; }
public void Add(T value)
{
if (_head == null)
_head = new BinaryTreeNode<T>(value);
else
AddTo(_head, value);
Count++;
}
private void AddTo(BinaryTreeNode<T> node, T value)
{
if (value.CompareTo(node.Value) < 0)
{
if (node.Left == null)
node.Left = new BinaryTreeNode<T>(value);
else
AddTo(node.Left, value);
}
else
{
if (node.Right == null)
node.Right = new BinaryTreeNode<T>(value);
else
AddTo(node.Right, value);
}
}
public IEnumerable<T> Preorder(BinaryTreeNode<T> root)
{
var stack = new Stack<BinaryTreeNode<T>>();
stack.Push(root);
while (stack.Count > 0)
{
var node = stack.Pop();
yield return node.Value;
if (node.Right != null)
stack.Push(node.Right);
if (node.Left != null)
stack.Push(node.Left);
}
}
public IEnumerable<T> InOrder(BinaryTreeNode<T> root)
{
var stack = new Stack<BinaryTreeNode<T>>();
while (root != null)
{
while (root.Left != null)
{
stack.Push(root);
root = root.Left;
}
yield return root.Value;
while (root.Right == null && stack.Count > 0)
{
root = stack.Pop();
yield return root.Value;
}
root = root.Right;
}
}
public IEnumerator<T> GetEnumerator()
{
return _head.GetEnumerator();
}
public void Clear()
{
_head = null;
Count = 0;
}
}
I have implemented a generic custom collection class which only takes a Person type object.
While providing support for the Enumerator to iterate through the collection it shows an error
Cannot apply indexing with [] to an expression of type 'CustomCollection.CustomCollection'
Below is the code snippet for the class I created.
public class CustomCollection<T> : ICollection<T> where T : Person
{
private IList<T> lst = null;
public CustomCollection()
{
lst = new List<T>();
}
public void Add(T item)
{
this.lst.Add(item);
}
public void Clear()
{
this.lst.Clear();
}
public bool Contains(T item)
{
bool result = false;
foreach (T obj in this.lst)
{
if (obj.Id.Equals(item.Id))
{
result = true;
break;
}
}
return result;
}
public void CopyTo(T[] array, int arrayIndex)
{
throw new NotImplementedException();
}
public int Count
{
get { return this.lst.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
public bool Remove(T item)
{
bool result = false;
foreach (T obj in this.lst)
{
if (obj.Id.Equals(item.Id))
{
this.lst.Remove(item);
}
}
return result;
}
public IEnumerator<T> GetEnumerator()
{
return new PersonEnumerator<T>(this);
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
The Enumerator class as below:
public class PersonEnumerator<T> : IEnumerator<T> where T : Person
{
private CustomCollection<T> collection = null;
private int index;
private T current;
public PersonEnumerator(CustomCollection<T> collection)
{
this.collection = collection;
this.index = -1;
current = default(T);
}
public T Current
{
get { return this.current; }
}
public void Dispose()
{
throw new NotImplementedException();
}
object IEnumerator.Current
{
get { return this.Current; }
}
public bool MoveNext()
{
if (++this.index >= collection.Count)
{
return false;
}
else
{
this.current = collection[this.index];
}
return true;
}
public void Reset()
{
this.index = -1;
current = default(T);
}
}
Person Class only contains FirstName, LastName & Id as properties in it.
ICollection doesn't implements an indexer. If you want to use indexing, you should implement IList instead.
You can use Linq with ICollection:
var result = Items.ElementAt(index);
Or you can add your own indexer:
public T this[int i]
{
return Items[i];
}
To make your code build, you need to add an indexer, to your CustomCollection<T> class, e.g.
public T this[int index]
{
return lst [index];
}
Then you can say use collection[n] to get the nth element in the MoveNext() method.
Or
Instead of having your PersonEnumerator<T> class you could just expose lst.GetEnumerator() which returns an IEnumerator<T>, i.e.
public IEnumerator<T> GetEnumerator()
{
return lst.GetEnumerator();
}
Unless you're planning on doing anything fancy with your enumerator, you might as well use the one for lst.
I'm trying to remove a Node from LinkedList by it's value however it doesn't seem to work.
LinkedList class (with node):
public class Node<T>
{
private T info;
private Node<T> next;
public Node(T x, Node<T> next)
{
this.info = x;
this.next = next;
}
public Node<T> GetNext()
{
return this.next;
}
public void SetNext(Node<T> next)
{
this.next = next;
}
public T GetInfo()
{
return this.info;
}
public void SetInfo(T x)
{
this.info = x;
}
public override string ToString()
{
return this.info.ToString();
}
}
public class List<T>
{
private Node<T> first;
public List()
{
this.first = null;
}
public Node<T> GetFirst()
{
return this.first;
}
public Node<T> Add(Node<T> pos, T x)
{
Node<T> temp = new Node<T>(x, null);
if (pos == null)
{
temp.SetNext(this.first);
this.first = temp;
}
else
{
temp.SetNext(pos.GetNext());
pos.SetNext(temp);
}
return temp;
}
public Node<T> Remove(Node<T> pos)
{
if (this.first == pos)
this.first = pos.GetNext();
else
{
Node<T> prevPos = this.GetFirst();
while (prevPos.GetNext() != pos)
prevPos = prevPos.GetNext();
prevPos.SetNext(pos.GetNext());
}
Node<T> nextPos = pos.GetNext();
pos.SetNext(null);
return nextPos;
}
public override string ToString()
{
string str = "[";
Node<T> pos = this.first;
while (pos != null)
{
str += pos.GetInfo().ToString();
if (pos.GetNext() != null)
str += ", ";
pos = pos.GetNext();
}
str += "]";
return str;
}
}
That's the function:
public void Del(string info)
{
Node<T> previousNode = null, obsoleteNode = null, nextNode = null;
Node<T> pos = this.first;
while (pos != null)
{
if (pos == this.first && this.first.GetInfo().ToString() == info)
{
Node<T> temp = pos;
this.first = this.first.GetNext();
temp = null;
}
else
{
previousNode = pos;
if (previousNode != null)
obsoleteNode = previousNode.GetNext();
if (nextNode == null)
nextNode = pos.GetNext().GetNext();
if (obsoleteNode != null)
{
if (obsoleteNode.GetInfo().ToString() == info)
previousNode.SetNext(nextNode);
}
}
pos = pos.GetNext();
}
}
In VS autos it shows that obsoleteNode is actually null but i can't understand why.
All other values are okay, except pos, it gets somehow the last node in the list instead of first but the this.first himself is okay.
What can be the problem?