I am trying to add nodes in a sorted manner to my linked list. My code just keeps adding to the end if the value is less than the end of the linked list. I am not sure how to fix this or if I am not fully checking for the right scenario.
I have tried to increment current until it is greater than the nodeToAdd to place the node between, but it always just places it at the end.
public void AddOrdered(int value)
{
LinkedListNode nodeToAdd = new LinkedListNode(value);
LinkedListNode cur = m_first;
if (m_first == null)
m_first = nodeToAdd;//new LinkedListNode(value);
else if (nodeToAdd.m_data < m_first.m_data)
{
AddAtFront(value);
}
else if (nodeToAdd.m_data < cur.m_next.m_data)
{
LinkedListNode temp = new LinkedListNode(value);
temp = m_first.m_next;
m_first.m_next = nodeToAdd;
nodeToAdd.m_next = temp;
}
else
{
AddAtEnd(value);
}
}
supplement add at end/front methods--which are working fine
public void AddAtEnd(int value)
{
LinkedListNode cur = m_first;
if (m_first == null)
{
LinkedListNode lnl = new LinkedListNode(value);
m_first = lnl;
}
while (cur.m_next != null)
{
cur = cur.m_next;
}
cur.m_next = new LinkedListNode(value);
}
public void AddAtFront(int value)
{
if (m_first == null)
{
LinkedListNode ln = new LinkedListNode(value);
m_first = ln;
}
else
{
LinkedListNode lnl = new LinkedListNode(value);
lnl.m_next = m_first;
m_first = lnl;
}
}
The values should get added in order but the output is placing them at the very end of the linked list unless new min/maxs are entered as values.
First I am assuming that m_first is your first node. With this as an assumption the code would be as follows:
public void AddOrdered(int value)
{
LinkedListNode nodeToAdd = new LinkedListNode(value);
LinkedListNode cur;
if (m_first == null || m_first.data >= nodeToAdd.data)
{
nodeToAdd.next = m_first;
m_first = nodeToAdd;
}
else
{
cur = m_first;
while (cur.next != null &&
cur.next.data < nodeToAdd.data)
cur = cur.next;
nodeToAdd.next = cur.next;
cur.next = nodeToAdd;
}
}
Related
I'm working on SPOJ problem where you have to write an algorithm that based on input string conditions outputs new string, but you can't exceede time limit.
problem link
The fastest i could get was by using two stacks, but time limit was still exceeded, now I tried implementing doubly linked list, but it's twice slower than when I used stack. Do you have any idea on how can I increase performance of implemented linked list, or maybe should I use other data structure for this problem? Thought of implementing Node as a structure but not really sure if you can do that.
using System;
namespace spoj
{
class LinkedList
{
private Node head;
private Node tail;
private int length;
public Node Head { get => head; }
public Node Tail { get => tail; }
public int Length { get => length; }
public LinkedList(Node head = null, Node tail = null, int length = 0)
{
this.head = head;
this.tail = tail;
this.length = length;
}
public void AddFirst(char value)
{
var addFirst = new Node(value);
addFirst.Next = head;
addFirst.Previous = null;
if (head != null)
head.Previous = addFirst;
head = addFirst;
length++;
}
public void Remove(Node node)
{
if (node.Previous == null)
{
head = node.Next;
head.Previous = null;
length--;
}
else if (node.Next == null)
{
tail = node.Previous;
tail.Next = null;
length--;
}
else
{
Node temp1 = node.Previous;
Node temp2 = node.Next;
temp1.Next = temp2;
temp2.Previous = temp1;
length--;
}
}
public void AddAfter(Node node, char input)
{
var newNode = new Node(input);
if (node.Next == null)
{
node.Next = newNode;
newNode.Previous = node;
length++;
}
else
{
Node temp1 = node;
Node temp2 = node.Next;
temp1.Next = newNode;
newNode.Previous = temp1;
newNode.Next = temp2;
temp2.Previous = newNode;
length++;
}
}
public string Print()
{
string temp = "";
if (head == null)
return temp;
for (int i = 0; i < length; i++)
{
temp += head.Value;
head = head.Next;
}
return temp;
}
}
class Node
{
private char value;
private Node next;
private Node previous;
public char Value { get => value; }
public Node Next { get => next; set { next = value; } }
public Node Previous { get => previous; set { previous = value; } }
public Node(char value)
{
this.value = value;
next = null;
previous = null;
}
}
class Program
{
static void Main(string[] args)
{
int testNum = Int32.Parse(Console.ReadLine());
for (int i = 0; i < testNum; i++)
{
var list = new LinkedList();
string input = Console.ReadLine();
var node = list.Head;
for (int j = 0; j < input.Length; j++)
{
if ((input[j] == '<' && node == null) | (input[j] == '>' && (node == null || node.Next == null)) | (input[j] == '-' && (node == null || node.Previous == null)))
continue;
else if (input[j] == '<')
{
node = node.Previous;
}
else if (input[j] == '>')
{
node = node.Next;
}
else if (input[j] == '-')
{
node = node.Previous;
list.Remove(node.Next);
}
else
{
if (node == null)
{
list.AddFirst(input[j]);
node = list.Head;
continue;
}
list.AddAfter(node, input[j]);
node = node.Next;
}
}
Console.WriteLine(list.Print());
}
}
}
}
An implementation using a linked list will not be as fast as one that uses StringBuilder, but assuming you are asking about a linked list based implementation I would suggest not to reimplement LinkedList. Just use the native one.
This means you don't have to change much in your code, just this:
Define the type of the list nodes as char: new LinkedList<char>();
Instead of .Head use .First
Instead of .Print use string.Join("", list)
However, there are these problems in your code:
When the input is >, you should allow the logic to execute when node is null. Currently you continue, but a null may mean that your "cursor" is in front of the non-empty list, so you should still deal with it, and move the "cursor" to list.First
When the input is -, you should still perform the removal even when node.Previous is null, because it is not the previous node that gets removed, but the current node. We should imagine the cursor to be between two consecutive nodes, and your removal logic shows that you took as rule that the cursor is between the current node and node.Next. You could also have taken another approach (with the cursor is just before node), but important is that all your logic is consistent with this choice.
When executing the logic for - -- in line with the previous point -- you should take into account that node.Previous could be null, and in that case you cannot do the removal as you have it. Instead, you could first assign the node reference to a temporary variable, then move the cursor, and then delete the node that is referenced by the temporary reference.
Here is the corrected code, using the native LinkedList implementation. I moved the logic for doing nothing (your continue) inside each separate case, as I find that easier to understand/debug:
using System;
using System.Collections.Generic;
public class Test
{
public static void Main()
{
int testNum = Int32.Parse(Console.ReadLine());
for (int i = 0; i < testNum; i++)
{
var list = new LinkedList<char>();
string input = Console.ReadLine();
var node = list.First;
for (int j = 0; j < input.Length; j++)
{
if (input[j] == '<')
{
if (node != null)
node = node.Previous;
}
else if (input[j] == '>')
{
if (node == null || node.Next != null)
node = node == null ? list.First : node.Next;
}
else if (input[j] == '-')
{
if (node != null) {
var temp = node;
node = node.Previous;
list.Remove(temp);
}
}
else
{
node = node == null ? list.AddFirst(input[j])
: list.AddAfter(node, input[j]);
}
}
Console.WriteLine(string.Join("", list));
}
}
}
I have a program which builds a very large tree from input data and traverses it, both by recursion. I have tested the program on smaller inputs (and thus smaller trees) and it functions as intended. However when the input data is much larger i run into 'Process is terminated due to StackOverflowException'. I assume this is due to the stack running out of space. Is there any way to prevent this or do I have to switch to building the tree via iteration instead? Or perhaps I am missing a case of infinite recursion somewhere?
Here is the code:
class Program
{
static int[] tileColors;
static Color[] colors;
static int totalTiles;
static void Main(string[] args)
{
Stopwatch s = new Stopwatch();
s.Start();
string[] data = File.ReadAllLines("colors.txt");
totalTiles = int.Parse(data[0].Split(' ')[0]);
int totalColors = int.Parse(data[0].Split(' ')[1]);
string[] colorsRaw = data[1].Split(' ');
tileColors = new int[totalTiles];
for (int i = 0; i < totalTiles; i++)
{
tileColors[i] = int.Parse(colorsRaw[i]) - 1;
}
colors = new Color[totalColors];
for (int i = 3; i < data.Length; i++)
{
string[] raw = data[i].Split(' ');
int[] pair = new int[] { int.Parse(raw[0]) - 1, int.Parse(raw[1]) - 1 };
if (colors[pair[0]] == null)
colors[pair[0]] = new Color(pair[1]);
else
colors[pair[0]].pairs.Add(pair[1]);
if (colors[pair[1]] == null)
colors[pair[1]] = new Color(pair[0]);
else
colors[pair[1]].pairs.Add(pair[0]);
}
Tree t = new Tree();
t.root = new Node(0);
PopulateTree(t.root);
long ans = t.CountMatchingLeaves(t.root, totalTiles - 1) % 1000000007;
Console.WriteLine(ans);
s.Stop();
Console.WriteLine(s.ElapsedMilliseconds);
}
static void PopulateTree(Node root)
{
for (int i = root.tile + 1; i < totalTiles; i++)
{
if (colors[tileColors[i]] == null) continue;
if (colors[tileColors[i]].Compatible(tileColors[root.tile]))
{
var node = new Node(i);
root.children.Add(node);
PopulateTree(node);
}
}
}
}
class Color
{
public List<int> pairs = new List<int>();
public Color(int pair)
{
pairs.Add(pair);
}
public bool Compatible(int c)
{
return pairs.Contains(c);
}
}
class Node
{
public List<Node> children = new List<Node>();
public int tile;
public Node(int tile)
{
this.tile = tile;
}
}
class Tree
{
public Node root;
public List<Node> GetMatchingLeaves(Node root, int match)
{
if (root.children.Count == 0)
{
if (root.tile == match)
{
return new List<Node>() { root };
}
return new List<Node>();
}
List<Node> list = new List<Node>();
foreach(var c in root.children)
{
list.AddRange(GetMatchingLeaves(c, match));
}
return list;
}
public long CountMatchingLeaves(Node root, int match)
{
if (root.children.Count == 0)
{
if (root.tile == match)
{
return 1;
}
return 0;
}
long count = 0;
foreach (var c in root.children)
{
count += CountMatchingLeaves(c, match);
}
return count;
}
}
You can always rewrite recursion as iteration, usually by using a stack class rather than rely on your thread's stack. For your code it would look like this:
static void PopulateTree(Node start)
{
var nodes = new Stack<Node>();
nodes.Push(start);
while(nodes.Count != 0)
{
var root = nodes.Pop();
for (int i = root.tile + 1; i < totalTiles; i++)
{
if (colors[tileColors[i]] == null) continue;
if (colors[tileColors[i]].Compatible(tileColors[root.tile]))
{
var node = new Node(i);
root.children.Add(node);
nodes.Push(node);
}
}
}
}
The while loop checking for more items is the equivalent of your terminating condition in recursion.
I want to understand the A* algorithm. I wrote by examples, but often it gets into an infinite loop.
What is the problem?
Please forgive me for the English language.
Path Search Code:
public Node GetPath(Vector2 goal,Vector2 start) {
List<Node> OpenNodes = new List<Node>(); //список с не просмотренными узлами
List<Node> ClosedNodes = new List<Node>(); //список с не просмотренными узлами
OpenNodes.Add(new Node
{
pos = start,
parent = null,
DistStart = 0,
DistOnGoal = GetDistOnGoal(Vector2.zero, goal)
});
while (OpenNodes.Count > 0) {
var FirstNode = OpenNodes.OrderBy(node => node.FullDist).First();
ClosedNodes.Add(FirstNode);
OpenNodes.Remove(FirstNode);
if (FirstNode.pos == goal) {
Debug.Log("путь есть");
return FirstNode;
}
foreach (Node n in NighBours(FirstNode, goal)) {
var chanel = false;
foreach (Node d in ClosedNodes) {
if (n == d) {
chanel = true;
continue;
}
}
if (chanel)
{
chanel = false;
continue;
}
var opennod = OpenNodes.FirstOrDefault(node => node.pos == n.pos);
if (opennod == null)
{
OpenNodes.Add(n);
}
else {
if (opennod.DistStart >n.DistStart) {
opennod.DistStart = n.DistStart;
opennod.parent = FirstNode;
}
}
}
}
return null;
}
public float GetDistOnGoal(Vector2 n, Vector2 goal) {//дистанция до цели
return Mathf.Abs((goal - n).magnitude);
}
public List<Node> NighBours(Node n,Vector2 goal)//соседи
{
var Point = new Vector2[4];
var Nodes = new List<Node>();
Point[0] = new Vector2(n.pos.x - 1, n.pos.y);
Point[1] = new Vector2(n.pos.x + 1, n.pos.y);
Point[2] = new Vector2(n.pos.x, n.pos.y + 1);
Point[3] = new Vector2(n.pos.x, n.pos.y - 1);
for (var i = 0; i < Point.Length; i++)
{
if (Point[i].x > 1 && Point[i].x < map.GetLength(0) - 2 && Point[i].y > 1 && Point[i].y < map.GetLength(1) - 2)
{
if (map[(int)Point[i].x, (int)Point[i].y] == 0)
{
Nodes.Add(
new Node
{
pos = Point[i],
parent = n,
DistStart = n.DistStart + 1,
DistOnGoal = GetDistOnGoal(Point[i],goal),
});
}
}
}
return Nodes;
}
public class Node {
public Vector2 pos;
public Node parent;
public float DistStart;
public float DistOnGoal;
public float FullDist
{
get
{
return DistStart + DistOnGoal;
}
}
}
This is the node code.
The function never returned null, although an example of this implies.
Debug also can't because Unity hangs tight
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
class node
{
public int data;
public node next;
public node(int value)
{
next = null;
data = value;
}
public void addFront(node head, int value)
{
var tempNode = new node(value);
tempNode.next = head;
head = tempNode;
}
public void addBack(node head, int value)
{
var insertNode = new node(value);
var traverseNode = head;
while (traverseNode != null)
{
if (traverseNode.next == null)
{
traverseNode.next = insertNode;
insertNode.data = value;
}
traverseNode = traverseNode.next;
}
}
public void printList(node head)
{
var counter = 0;
var traverseNode = head;
while (traverseNode != null)
{
Console.WriteLine("LL item {0}: {1}", counter, traverseNode.data);
traverseNode = traverseNode.next;
counter++;
}
}
public int deleteFront(node head)
{
//Don't need to delete the memory because the garbage collector handles that in c# (at least by my understanding). If this were C, I'd have to use free, and in C++ I'd use keyword Delete
var returnValue = head.data;
head = head.next;
return returnValue;
}
public int deleteBack(node head)
{
node traverseNode = head;
node traverseNodeTrailer = head;
if (traverseNode == null)
{
return 0;
}
while (traverseNode != null)
{
if (traverseNode.next == null)
{
traverseNodeTrailer.next = null;
break;
}
traverseNodeTrailer = traverseNode;
traverseNode = traverseNode.next;
}
return traverseNode.data;
}
public void deleteMiddle(node middleNode)
{
var traverseNode = middleNode;
while (traverseNode != null)
{
if (traverseNode.next.next == null)
{
traverseNode.data = traverseNode.next.data;
traverseNode.next = null;
break;
}
traverseNode.data = traverseNode.next.data;
traverseNode = traverseNode.next;
}
}
public node search(node head, int value)
{
var traverseNode = head;
while (traverseNode != null)
{
if (traverseNode.data == value)
return traverseNode;
traverseNode = traverseNode.next;
}
return null;//failed to find the value in the linked list
}
}
static void Main(string[] args)
{
Int32 userMenuInput = 0;
var running = true;
int userNodeInput = 0;
node head = null;
while (running)
{
Console.WriteLine("Enter a number depending on the operation you would like to perform.");
Console.WriteLine("1 - Insert node of specified value; 2 - Delete a node and return the value; 3 - Search for a node with a specified value; 4 - Print the list values. *All other values exit");
userMenuInput = Convert.ToInt32(Console.ReadLine());//get user input for what they want to do
switch (userMenuInput)
{
case 1:
Console.WriteLine("Enter a number you'd like to insert into the linked list.");
userNodeInput = Convert.ToInt32(Console.ReadLine());//get user input for value to insert
if (head == null)
{
head = new node(userNodeInput);
break;
}
head.addFront(head, userNodeInput);
break;
case 2:
if (head == null)
{
Console.WriteLine("The list is empty - cannot delete.");
break;
}
userNodeInput = head.deleteFront(head);
Console.WriteLine("{0} is the value that was deleted from the front of the list.", userNodeInput);
break;
case 3:
Console.WriteLine("What is the value you'd like to search for in the list?");
userNodeInput = Convert.ToInt32(Console.ReadLine());
if (head == null)
{
//do nothing
}
else if (head.search(head, userNodeInput) != null)
{
Console.WriteLine("That value was found");
break;
}
Console.WriteLine("That value was not found.");
break;
case 4:
if (head == null)
{
Console.WriteLine("The list has nothing to print.");
break;
}
head.printList(head);
break;
default:
running = false;
break;
}
}
}
}
}
DISCLAIMER: I'm very new to c# - just been using it for the past week or so. I will appreciate any optimization hints you have, but for now, I'm just trying to get this running.
So, this is correctly inserting 1 element, but nothing more. It is finding the element if it is in the first link. The delete doesn't seem to be working at all. It doesn't throw any errors but it also doesn't delete the first link. Note: A few of my functions in there are unused so far so don't worry about mentioning that - I'm aware.
Thanks everyone!
You can use ref if you want to modify argument passed to addFront method:
public void addFront(ref node head, int value)
{
var tempNode = new node(value);
tempNode.next = head;
head = tempNode;
}
.
head.addFront(ref head, userNodeInput);
I have null reference exception unhandled error in my red black tree code. I'm trying to remove it but I couldn't. The error is on this line
if (currentNode.left.color == Color.Red && currentNode.right.color == Color.Red)
Please can you people fix this error
Here is my code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Algo_Project
{
class Program
{
public enum Color
{
Red = 0, Black = 1
}
public enum direction
{
Left, Right
}
public class Node
{
public IComparable data;
public Node left;
public Node right;
public Color color = Color.Black;
public Node(IComparable data): this(data, null, null)
{
}
public Node(IComparable data, Node left, Node right)
{
this.data = data;
this.left = left;
this.right = right;
}
}
public class Tree
{
protected Node root;
protected Node freshNode;
protected Node currentNode;
protected Tree()
{
freshNode = new Node(null);
freshNode.left = freshNode.right = freshNode;
root = new Node(null);
}
protected int Compare(IComparable item, Node node)
{
if (node != root)
return item.CompareTo(node.data);
else
return 1;
}
public IComparable Search(IComparable data)
{
freshNode.data = data;
currentNode = root.right;
while (true)
{
if (Compare(data, currentNode) < 0)
currentNode = currentNode.left;
else if (Compare(data, currentNode) > 0)
currentNode = currentNode.right;
else if (currentNode != freshNode)
return currentNode.data;
else
return null;
}
}
protected void Display(Node temp)
{
if (temp != freshNode)
{
Display(temp.left);
Console.WriteLine(temp.data);
Display(temp.right);
}
}
protected void Display()
{
this.Display(root.right);
}
}
public sealed class RedBlackTree : Tree
{
private Color Black = Color.Black;
private Color Red = Color.Red;
private Node parentNode;
private Node grandParentNode;
private Node tempNode;
public void Insert(IComparable item)
{
currentNode = parentNode = grandParentNode = root;
freshNode.data = item;
int returnValue = 0;
while (Compare(item, currentNode) != 0)
{
tempNode = grandParentNode;
grandParentNode = parentNode;
parentNode = currentNode;
returnValue = Compare(item, currentNode);
if (returnValue < 0)
currentNode = currentNode.left;
else
currentNode = currentNode.right;
if (currentNode.left.color == Color.Red && currentNode.right.color == Color.Red)
{
ReArrange(item);
}
}
if (currentNode == freshNode)
{
currentNode = new Node(item, freshNode, freshNode);
if (Compare(item, parentNode) < 0)
parentNode.left = currentNode;
else
parentNode.right = currentNode;
ReArrange(item);
}
}
private void ReArrange(IComparable item)
{
currentNode.color = Red;
currentNode.left.color = Color.Black;
currentNode.right.color = Color.Black;
if (parentNode.color == Color.Red)
{
grandParentNode.color = Color.Red;
bool compareWithGrandParenrNode = (Compare(item, grandParentNode) < 0);
bool compareWithParentNode = (Compare(item, parentNode) < 0);
if (compareWithGrandParenrNode != compareWithParentNode)
parentNode = Rotate(item, grandParentNode);
currentNode = Rotate(item, tempNode);
currentNode.color = Black;
}
root.right.color = Color.Black;
}
private Node Rotate(IComparable item, Node parentNode)
{
int value;
if (Compare(item, parentNode) < 0)
{
value = Compare(item, parentNode.left);
if (value < 0)
parentNode.left = this.Rotate(parentNode.left, direction.Left);
else
parentNode.left = this.Rotate(parentNode.left, direction.Right);
return parentNode.left;
}
else
{
value = Compare(item, parentNode.right);
if (value < 0)
parentNode.right = this.Rotate(parentNode.right, direction.Right);
else
parentNode.right = this.Rotate(parentNode.right, direction.Right);
return parentNode.right;
}
}
private Node Rotate(Node node, direction direction)
{
Node tempNode;
if (direction == direction.Left)
{
tempNode = node.left;
node.left = tempNode.right;
tempNode.right = node;
return tempNode;
}
else
{
tempNode = node.right;
node.right = tempNode.left;
tempNode.left = node;
return tempNode;
}
}
}
static void Main(string[] args)
{
RedBlackTree redBlackTree = new RedBlackTree();
Random random = new Random();
for (int i = 0; i < 100000; i++)
{
redBlackTree.Insert(random.Next(1, 100000));
random.Next();
}
redBlackTree.Insert(1000001);
DateTime startTime = DateTime.Now;
int p = (int)redBlackTree.Search(1000001);
DateTime endTime = DateTime.Now;
TimeSpan TimeElapsed = (TimeSpan)(endTime - startTime);
Console.WriteLine("The number " + p + "has been found in" + TimeElapsed.Milliseconds.ToString() + "milliseconds.");
Console.ReadLine();
Console.ReadLine();
}
}
}
Please can you tell something about this error I want it fixed up till thursday 6th June 2013
When your Insert method hits a leaf, currentNode.left or currentNode.right will be null. At this point, you're not checking for null, so you'll receive this exception on that line as you try to access the color.
You need to add null checks on insert to handle the leaf condition.