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;
}
}
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 am looking for a job. Periodically I come across the requirement to perform some kind of test task. Recently, I received a reject (which in itself is not critical for me) based on a test solution. Unfortunately, they did not provide feedback to me, so I decided to write here in an attempt to figure out the reason for the rejection and the correctness of the formulation of the tasks themselves. Personally, I have suspicions regarding part 3. Task text:
Original task text
Написать функцию, которая преобразует строку с римским числом в целое (иными словами, написать тело функции public int RomanToInt(string s)). Римское число не больше 3000.
Проверить сбалансированность скобочной структуры в произвольном выражении ((1+3)()(4+(3-5)))
Реализовать двусвязный список и написать функцию, переворачивающую его, т.е. изменяющую порядок элементов на обратный.
public interface DoubleLinkedListNode<T>
{
T Value { get; set; }
DoubleLinkedNode<T> Next { get; set; }
DoubleLinkedNode<T> Prev { get; set; }
}
public interface DoubleLinkedList<T>
{
DoubleLinkedNode<T> First { get; set; }
DoubleLinkedNode<T> Last { get; set; }
void Reverse();
//insert new DoubleLinkedListNode with given value at the start of the list
void AddFirst(T value);
//insert new DoubleLinkedListNode with given value at the end of the list
void AddLast(T value);
}
Все решения должны быть сопровождены юнит-тестами.
Task translation
Write a function that converts a string with a Roman number to an integer (in other words, write the body of a function public int RomanToInt (string s)). Roman number no more than 3000.
Check the balance of the bracket structure in an arbitrary expression ((1 + 3) () (4+ (3-5)))
Implement a doubly linked list and write a function that reverses it, i.e. reverse the order of elements.
The third part caused me dissonance, first of all, by non-compliance with the convention. In addition, in the text of the assignment there are no points that would regulate the use of these interfaces in the required solution. Just a piece of code and that’s it.
I have a question for you how these interfaces can be used in the implementation of doubly linked lists and what advantages this can give (in comparison with more common solutions). Maybe I'm not so strong in OOD, but I personally only think of circumventing the limitations of lack of multiple inheritance in C#.
My solution
public class DoublyNode<T>
{
public DoublyNode()
{}
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>
{
private DoublyNode<T> head;
private DoublyNode<T> tail;
private int count;
public void AddLast(T data)
{
DoublyNode<T> node = new DoublyNode<T>(data);
if (head == null)
{
head = node;
}
else
{
tail.Next = node;
node.Previous = tail;
}
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;
}
count++;
}
public bool Remove(T data)
{
DoublyNode<T> current = head;
while (current != null)
{
if (current.Data.Equals(data))
{
break;
}
current = current.Next;
}
if (current != null)
{
if (current.Next != null)
{
current.Next.Previous = current.Previous;
}
else
{
tail = current.Previous;
}
if (current.Previous != null)
{
current.Previous.Next = current.Next;
}
else
{
head = current.Next;
}
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;
while (current != null)
{
if (current.Data.Equals(data))
{
return true;
}
current = current.Next;
}
return false;
}
public void Reverse()
{
var buffer = head;
head = tail;
tail = buffer;
DoublyNode<T> current;
current = head;
while (current != null)
{
current.Next = buffer;
current.Next = current.Previous;
current.Previous = buffer;
current = current.Next;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)this).GetEnumerator();
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
DoublyNode<T> current = head;
while (current != null)
{
yield return current.Data;
current = current.Next;
}
}
public IEnumerable<T> BackEnumerator()
{
DoublyNode<T> current = tail;
while (current != null)
{
yield return current.Data;
current = current.Previous;
}
}
}
I made a Binary Tree for searching a best prefix for a phone number but when i have a largest list of prefixes, the follow code sometimes generate a StackOverflowException on StartsWith() function.
BTreeNode.cs
public class BTreeNode<T>
{
public BTreeNode(T item)
{
this.Item = item;
}
public T Item { get; set; }
public BTreeNode<T> Left { get; set; }
public BTreeNode<T> Right { get; set; }
}
BTree.cs
public class BTree
{
public BTreeNode<string> Root { get; set; }
public BTree(IEnumerable<string> enumerable)
{
if (enumerable == null)
{
throw new ArgumentNullException(nameof(enumerable));
}
using (IEnumerator<string> enumerator = enumerable.GetEnumerator())
{
while (enumerator.MoveNext())
{
AddNode(enumerator.Current);
}
}
}
public void AddNode(string key)
{
if (Root == null)
{
Root = new BTreeNode<string>(key);
}
else
{
AddNode(key, Root);
}
}
private void AddNode(string key, BTreeNode<string> current)
{
if (key.StartsWith(current.Item))
{
if (current.Left == null)
{
current.Left = new BTreeNode<string>(key);
}
else
{
AddNode(key, current.Left);
}
}
else
{
if (current.Right == null)
{
current.Right = new BTreeNode<string>(key);
}
else
{
AddNode(key, current.Right);
}
}
}
public string Search(string key)
{
if (Root == null)
{
return null;
}
return Search(key, Root, null);
}
private string Search(string key, BTreeNode<string> current, BTreeNode<string> match)
{
if (current != null)
{
if (current.Left != null)
{
if (key.StartsWith(current.Left.Item))
{
return Search(key, current.Left, current.Left);
}
}
if (current.Right != null)
{
if (key.StartsWith(current.Item))
{
return Search(key, current.Left, current);
}
if (key.Length >= current.Right.Item.Length)
{
if (long.Parse(key) >= long.Parse(current.Right.Item))
{
return Search(key, current.Right, match);
}
}
}
else
{
if (key.StartsWith(current.Item))
{
return Search(key, current.Left, current);
}
}
}
return match?.Item;
}
}
Sample data
StackOverflowException occurred for example if i'm searching on loop the all sample data that i load to Binary Tree.
Any solution?
I see no mechanism to balance this tree, so when you import a lot of data, some sub-branches can become very long. It is even possible that the whole tree is one linear branch, and doesn't split in multiple branches, especially when your list with sample data is ordered.
Some more advances trees, like a red-black tree, have a built-in mechanism to keep the tree balanced.
You have 35000 elements, which means a perfectly balanced tree should be not deeper than something around 15. (2^15 = 32768). But when the tree is completely unbalanced, you have one very long branch, which is almost the same as a single-linked list of 35000 elements, which are accessed recursively.
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;
}
}
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?