I have written a code in C# for the implementation of AVL_trees. I am having some problems with nodes that's why I am unable to insert data in the nodes. Below is my code.
public class avl_node
{
public int Data;
public avl_node Left;
public avl_node Right;
public int height;
public void DisplayNode()
{
Console.Write("{0}", Data);
}
}
public class avl_tree
{
public avl_node root;
public avl_tree()
{
root = null;
}
public void Insert(int i)
{
avl_node newNode = new avl_node();
newNode.Data = i;
newNode.height = newNode.height + 1;
if (root == null)
{
root = newNode;
}
else
{
avl_node current = root;
avl_node parent;
while (true)
{
parent = current;
if (i < current.Data)
{
current = current.Left;
if (current == null)
{
parent.Left = newNode;
break;
}
else
{
current = current.Right;
if (current == null)
{
parent.Right = newNode;
break;
}
}
}
}
}
}
public void InOrder(avl_node node)
{
if (!(node == null))
{
InOrder(node.Left);
node.DisplayNode();
InOrder(node.Right);
}
}
}
class Program
{
static void Main(string[] args)
{
avl_tree nums = new avl_tree();
nums.Insert(23);
nums.Insert(45);
nums.Insert(16);
nums.Insert(37);
nums.Insert(3);
nums.Insert(99);
nums.Insert(22);
avl_node nd = new avl_node();
nd = nums.Search(37);
Console.WriteLine("Inorder traversal: ");
nums.InOrder(nums.root);
}
}
All I get is a black console screen. I am very confused.
Hoping for a better response.
Regards
Umer
"All I get is a black console screen"
After 23 is inserted, your Insert() method gets stuck in the while loop because 45 is never less than 23:
while (true)
{
parent = current;
if (i < current.Data)
// you never get in here, so we just loop around in "while (true)"
Take a look at that loop in the insert method, you will get stuck in the loop everytime you try to insert any value greater than existing values already in the tree.
It will happen because of this conditional: if(i < current.data).
Where is the else statement? You put it inside the scope of the mentioned conditional. So it will never be reached, thus the program will run the infinite loop.
You should put an "}" before the else statement, so that else will be outside the scope of the first if statement. And Remove one of the "}" at the end of the method.
That way it should run just fine.
Related
I have a class Program which is a list of Nodes that contain a method IEnumerator Invoke() and the Program class iterates through each Node invoking it. I want to be able to provide methods to Start, Pause, Resume, and Stop execution. Starting would cause the invocation to start at the top of the list, Pausing would effectively 'Stop' the execution and allow Resume to be able to pick up wherever execution was when Pause was called, and Stop would cease all function and would require Start to be called to begin again. With Unity's built-in Coroutines is this even possible, and if it is how do I Pause/Resume a coroutine?
EDIT
what I'm looking for is how to essentially pause an instance of Program and be able to resume it at the same step.
If I understand one of the comments correctly the suggestion it makes would be something similar to this?
public abstract class Node {
public abstract IEnumerator Invoke(ProgramCaller caller);
}
public class Program : Node {
private List<Node> nodes;
public override IEnumerator Invoke(ProgramCaller caller) {
int index = 0;
while(index < nodes.Count) {
if(caller.Paused) {
yield return null;
}
else {
yield return nodes[index].Invoke(caller);
index++;
}
}
}
}
So from what I read is you have e.g.
public class Node
{
public IEnumerator Invoke()
{
yield return null;
}
}
Then a Unity Coroutine is basically using the IEnumerator and invoking MoveNext on certain intervals (Update by default except using the special ones like e.g. WaitForFixedUpdate etc).
So you could simply make Program implement that like e.g.
public class Program : IEnumerator
{
public Node[] nodes;
private int index = -1;
private IEnumerator currentNode;
public bool MoveNext()
{
if (nodes == null || nodes.Length == 0)
{
return false;
}
while (currentNode == null)
{
index++;
if (index >= nodes.Length)
{
return false;
}
currentNode = nodes[index]?.Invoke();
}
if (currentNode.MoveNext())
{
return true;
}
currentNode = null;
return true;
}
public void Reset()
{
index = -1;
currentNode = null;
}
public object Current => null;
}
and then you can link this up to a Coroutine from a MonoBehaviour like e.g.
public class Example : MonoBehaviour
{
public Program program;
private Coroutine currentRoutine;
// just a name alias
public void StartProgram() => RestartProgram();
public void RestartProgram()
{
StopProgram();
ResumeProgram();
}
public void ResumeProgram()
{
currentRoutine = StartCoroutine(program);
}
public void PauseProgram()
{
if (currentRoutine != null)
{
StopCoroutine(currentRoutine);
}
}
public void StopProgram()
{
PauseProgram();
program.Reset();
}
}
as you see the only difference between Start/Stop and Pause/Resume is resetting or not resetting the Program.
Alternatively and maybe even more simple: A Coroutine is paused automatically when disabling according MonoBehaviour and resumed when enabling it again.
=> If it is an option for you to have a dedicated runner component for each program then all you need really is the resetting part and you could simply do
public class Program
{
public Node[] nodes;
public IEnumerator Run()
{
foreach (var node in nodes)
{
yield return node.Invoke();
}
}
}
This way you can run them all as a single IEnumerator and then
public class Example : MonoBehaviour
{
public Program program;
private Coroutine currentRoutine;
// just a name alias
public void StartProgram() => RestartProgram();
public void RestartProgram()
{
StopProgram();
currentRoutine = StartCoroutine(program.Run());
}
public void ResumeProgram()
{
enabled = true;
}
public void PauseProgram()
{
enabled = false;
}
public void StopProgram()
{
if (currentRoutine != null)
{
StopCoroutine(currentRoutine);
}
}
}
im beginner and still learning please don't hate.
So my script is located in Canvas, (Canvas -> inv -> invslot) but I need to get currentSlot int from a script in invslot gameobj., how would I do that the right way? I've tried this so far but doesn't seem to work at all.
void UpdateUI () {
for (int i = 0; i < slots.Length; i++)
{
if (i < inventory.items.Count) {
currentSlot = GetComponentsInChildren<InventoryScroll>();
slots[i] = currentSlot;
currentSlot.AddItem(inventory.items[i]);
Debug.Log ("Updating UI");
} else
{
slots[i].ClearSlot();
}
}
}
EDIT!
Here is the top of my InventoryUI, where I want to bring the int currentSlot
public Transform itemsParent;
Inventory inventory;
InventorySlot[] slots;
// Start is called before the first frame update
void Start()
{
inventory = Inventory.instance;
inventory.onItemChangedCallback += UpdateUI;
slots = itemsParent.GetComponentsInChildren<InventorySlot>();
}
But the Inventoryscroll goes this way
List<GameObject> slots = new List<GameObject>();
public int currentSlot=0;
int slotsToScroll=3;
void Start() {
foreach(Transform child in this.transform) {
slots.Add(child.gameObject);
}
}
void Update () {
if (Input.GetKeyDown(KeyCode.Alpha1)) {
currentSlot=0;
UpdateDisplay();
}
if (Input.GetAxis("Mouse ScrollWheel") >0){
if (currentSlot<slotsToScroll) {
currentSlot++;
} else {
currentSlot=0;
}
UpdateDisplay();
}
}
void UpdateDisplay() {
for (int i = 0; i < slots.Count; i++)
{
if (i==currentSlot) {
slots[i].transform.GetChild(0).gameObject.SetActive(true);
} else {
slots[i].transform.GetChild(0).gameObject.SetActive(false);
}
}
}
Inventory script
#region Singleton
public static Inventory instance;
void Awake () {
if (instance != null) {
Debug.LogWarning("More than one instance of inventory found!");
return;
}
instance = this;
}
#endregion
public delegate void OnItemChanged();
public OnItemChanged onItemChangedCallback;
public int space = 6;
public List items = new List();
public bool Add (Item item) {
if (!item.isDefaultItem) {
if(items.Count >= space) {
Debug.Log("Not enough inventory space.");
return false;
}
items.Add(item);
if (onItemChangedCallback != null)
onItemChangedCallback.Invoke();
}
return true;
public void Remove (Item item) {
items.Remove(item);
if (onItemChangedCallback != null)
onItemChangedCallback.Invoke();
Careful, Unity has two methods:
GetComponentsInChildren
Returns all components of Type type in the GameObject or any of its children.
this returns a InventoryScroll []!
and GetComponentInChildren
Returns the component of Type type in the GameObject or any of its children using depth first search.
This returns one single InventoryScroll reference, the first one found!
Note the s!
From your description and how you use it in your code it seems like you wanted to use the latter but have an s too much.
The second mistake: From the variable name it sounds like you rather wanted to get an InventorySlot not an InventoryScroll!
So you should use
currentSlot = GetComponentInChildren<InventorySlot>();
Though it is hard to tell what your actual goal is with this code without seeing the types of slots and currentSlot.
It also appears really strange to me that you already get all slots in Start but here you overwrite
slots[i] = currentSlot;
for each i that is i < inventory.items.Coun. Also you iterate through slots.Length but you pass in inventory.izems[i] .. I don't understand what is supposed to happen here exactly.
I am attempting to write a program for an assignment that Pops and adds the first 2 items in a Stack. The program has a Pop method, but I would like to know how to call the method within the Add method. This Add is supposed to Pop the top two items in a stack, get their sum, and Push that sum to the stack. In my code below I call the Pop method twice inside the Add method, but when I display the stack, the stack still has all of the original values. Is there something more/else I need to go to get the Pop method to work?
class StackEmptyException : ApplicationException
{
public StackEmptyException(String message) : base(message)
{
}
}
class MathStack
{
private int[] dataStack;
private int size;
private int top = -1;
public bool IsEmpty()
{
return top == -1;
}
public bool IsFull()
{
return top == size - 1;
}
public void Push(int i)
{
dataStack[++top] = i;
}
public int Pop()
{
if (IsEmpty())
throw new StackEmptyException
("Stack empty -- cannot pop");
else
return dataStack[top--];
}
public int Top()
{
if (IsEmpty())
throw new StackEmptyException
("Stack empty -- top undefined");
else
return dataStack[top];
}
public MathStack()
{
dataStack = new int[10];
}
public MathStack(int s)
{
size = 10;
dataStack = new int[size];
}
public void LoadStack(int v)
{
dataStack[++top] = v;
}
public void Display()
{
int[] display = new int[dataStack.Length];
for (int i = 0; i < dataStack.Length; i++)
{
display[i] = dataStack[i];
Console.WriteLine("{0}", display[i]);
}
}
public void Add()
{
int add1 = dataStack[0];
int add2 = dataStack[1];
Pop();
Pop();
int sum = add1 + add2;
Console.WriteLine("Sum: {0}", sum);
}
}
class Program
{
static void Main(string[] args)
{
MathStack stack1 = new MathStack();
stack1.Push(9);
stack1.Push(8);
stack1.Push(7);
stack1.Push(6);
stack1.Push(5);
stack1.Push(4);
stack1.Push(3);
stack1.Push(2);
stack1.Push(1);
stack1.Push(0);
stack1.Display();
stack1.Add();
stack1.Display();
Console.ReadLine();
}
}
There are two things wrong with your code.
First, the Display method displays the whole array. Except that since you're not physically removing the items from the array, you need to stop at the index top:
public void Display()
{
if (IsEmpty())
{
Console.WriteLine("Empty");
return;
}
for (int i = 0; i <= top; i++)
{
Console.WriteLine(dataStack[i]);
}
}
The second issue is your Add. From what I understand, you want to pop the last two items, sum them, and push the result. In your implementation, you are actually summing the first two items (not the last two). A better version would be:
public void Add()
{
int add1 = Pop();
int add2 = Pop();
int sum = add1 + add2;
Console.WriteLine("Sum: {0}", sum);
Push(sum);
}
Notice how I do not directly access dataStack. If your API is correctly implemented, it should not be needed.
I have a project that requires us to use linked list stacks(NodeStack) and queues(NodeQueue). I have this sample code to work with:
class Node
{
object value;
Node next;
public void setValue(object o)
{
value = o;
}
public object getValue()
{
return value;
}
public void setNext(Node o)
{
next = o;
}
public Node getNext()
{
return next;
}
}
class NodeStack
{
Node top;
int count;
public void Push(object o)
{
Node newTop = new Node();
newTop.setValue(o);
newTop.setNext(top);
top = newTop;
count = count + 1;
}
public object Pop()
{
object value = top.getValue();
top = top.getNext();
return value;
}
public object Peek()
{
return top.getValue();
}
public void Clear()
{
top = null;
count = 0;
}
public int Count()
{
return count;
}
}
From this code I should be able to derive the NodeStack to a NodeQueuebut I have trouble understanding the syntax for the Enqueue and Dequeue methods. When I run a simple enqueue and dequeue program I get a Null reference exception on the 1st line of the dequeue method. Really appreciate the help.
Code I have so far:
class NodeQueue
{
Node tail;
Node head;
int count;
public void Enqueue(object o)
{
if (head == null)
{
Node newHead = new Node();
newHead.setValue(o);
head = tail = newHead;
newHead.setNext(tail);
}
else
{
Node newTail = new Node();
newTail.setValue(o);
newTail.setNext(tail);
tail = newTail;
}
count++;
}
public object Dequeue()
{
object value = head.getValue();
head = head.getNext();
return value;
}
public void Clear()
{
head = null;
tail = null;
count = 0;
}
public int Count()
{
return count;
}
}
EDIT:
The problem with the NullException has been handled but now I have a problem with dequeue. I am using this program to test the queue
NodeQueue nq = new NodeQueue();
nq.Enqueue(1);
nq.Enqueue(2);
nq.Enqueue(3);
nq.Enqueue(4);
nq.Enqueue(5);
Console.WriteLine(nq.Dequeue());
Console.WriteLine(nq.Dequeue());
Console.WriteLine(nq.Dequeue());
Console.WriteLine(nq.Dequeue());
Console.WriteLine(nq.Dequeue());
Console.ReadLine();
The expected output would be 1..5. The output that happens though is that 1 keeps getting printed.
Your Enqueuemethod is not correct thats why your are getting exception in 'Dequeue`
Also in Dequeue you should reduce count by one.
In your Enqueue head is not set.
class NodeQueue
{
Node tail;
Node head;
int count;
public void Enqueue(object o)
{
if (head == null)
{
Node newHead = new Node();
newHead.setValue(o);
head = tail = newHead;
}
else
{
Node newTail = new Node();
newTail.setValue(o);
tail.setNext(newTail);
tail = newTail;
}
count++;
}
public object Dequeue()
{
if (null != head)
{
object value = head.getValue();
head = head.getNext();
count--;
return value;
}
return null;
}
public void Clear()
{
head = null;
tail = null;
count = 0;
}
public int Count()
{
return count;
}
}
I'm making a basic LinkedList following this tutorial. However, when I'm done the list only contains two elements, "first" and "fourth". I put some break points in the code and found that the Add function of the LinkedList class only runs once. Each succesive Add goes into the Node(object data) method of the Node class. Any idea what I'm doing wrong?
public class Node
{
public object data;
public Node next;
public Node(object data)
{
this.data = data;
}
}
public class LinkedList
{
private Node head;
private Node current;
public void Add(Node n)
{
if (head == null)
{
head = n;
current = head;
}
else
{
current.next = n;
current = current.next;
}
}
}
class Program
{
static void Main(string[] args)
{
LinkedList list = new LinkedList();
list.Add(new Node("first"));
list.Add(new Node("second"));
list.Add(new Node("third"));
list.Add(new Node("fourth"));
}
}
Using this basic print method with your code :
public void Print()
{
Node curr = head;
while(true)
{
if(curr == null)
return;
Console.WriteLine(curr.data.ToString());
curr = curr.next;
}
}
Return the correct result : live example.
first
second
third
fourth
Your error must be with your printing routine.
There is no problem with your code, i guess you are checking only the LinkedList nodes while debugging, which will only shows the head and the current values.
Just try this,
class Program
{
static void Main(string[] args)
{
LinkedList list = new LinkedList();
list.Add(new Node("first"));
list.Add(new Node("second"));
list.Add(new Node("third"));
list.Add(new Node("fourth"));
list.PrintNodes();
}
}
public class Node
{
public object data;
public Node next;
public Node(object data)
{
this.data = data;
}
}
public class LinkedList
{
private Node head;
private Node current;
public void Add(Node n)
{
if (head == null)
{
head = n;
current = head;
}
else
{
current.next = n;
current = current.next;
}
}
public void PrintNodes()
{
while (head != null)
{
Console.WriteLine(head.data);
head = head.next;
}
Console.ReadLine();
}
}