how to write billions of data into a trie with less memory
I want to extract some infomation from news like company names,so I write billions of company names into a trie,but it needs much memory and throw out of memory exception,I don't know how to solve it,so anyone can help,thanks in advance.
public class Node
{
public char Value { get; set; }
public List<Node> Children { get; set; }
public int Depth { get; set; }
public string Code { get; set; }
public bool Terminal { get; set; }
public Node(char value, int depth)
{
Value = value;
Depth = depth;
Children = new List<Node>();
}
public Node FindChildNode(char c)
{
foreach (var child in Children)
if (child.Value == c)
return child;
return null;
}
}
public class Trie
{
private Node _root;
public Trie()
{
_root = new Node('^',0);
}
public Node Prefix(string s)
{
var currentNode = _root;
var result = currentNode;
foreach (var c in s)
{
currentNode = currentNode.FindChildNode(c);
if (currentNode == null)
break;
result = currentNode;
}
return result;
}
public void Insert(string randomLength,string code)
{
var commonPrefix = Prefix(randomLength);
var current = commonPrefix;
for (var i = current.Depth; i < s.Length; i++)
{
var newNode = new Node(s[i], current.Depth + 1);
if (i+1==s.Length)
{
newNode.Terminal = true;
newNode.Code = code;
}
current.Children.Add(newNode);
current = newNode;
}
}
}
Trie t=new Trie();
t.Insert("C","ABCG00DFD");
The aboved statement run 1000000000 Loops and the "C" can be replaced with different string with different length,as the loops increasing,it throw out of memory exception,so how to avoid or change it?
Have a go at this Trie and see if you can get it to work for what you need:
public class Trie : Dictionary<char, Trie>
{
public void Add(string value)
{
var c = String.IsNullOrEmpty(value) ? '\0' : value[0];
if (!this.ContainsKey(c))
{
this[c] = new Trie();
}
if (c != '\0')
{
this[c].Add(value.Substring(1));
}
}
}
before showing the issue, look at the IntNode class:
class IntNode
{
public int value { get; set; }
public IntNode next { get; set; }
public IntNode(int value)
{
this.value = value;
this.next = null;
}
public IntNode(int value, IntNode next)
{
this.value = value;
this.next = next;
}
public bool HasNext ()
{
return (this.next != null);
}
public override string ToString()
{
if (this.HasNext())
return this.value + " --> " + this.next;
else
return this.value + ". [end]";
}
}
I have the following function:
static IntNode Sort (IntNode head)
{
IntNode pos = head.next;
IntNode current = head;
IntNode prev = head;
bool changed = false;
while (current != null)
{
while (pos != null)
{
if (current.value > pos.value)
{
if (pos.HasNext()) current.next = pos.next;
else prev.next = pos;
pos.next = current;
changed = true;
if (current.next.HasNext())
pos = current.next.next;
break;
}
pos = pos.next;
}
if (!changed)
{
current.next = head;
head = current;
}
prev = current;
current = current.next;
changed = false;
}
return head;
}
But when I am launching the program (with given parameters) it is not responding (a "-" appears and disappears) I dont know why it is like that and I am sitting on this a hour...
The purpose of the program is to a list and sort it from smaller to bigger and than return the edited list (dont create another list).
For Example:
Given list:
6,-4,5,0
Output:
-4,0,5,6
Thanks!
I can see several issues with how your bubble sort is written. If you don't have a debugger it will be difficult to debug manually. Here is an insertion sort that may do the trick for you and be easier to trace mentally. It finds the lowest value and moves it to a different list.
static IntNode Sort (IntNode head)
{
IntNode resultTail = null;
IntNode resultHead = null;
IntNode current = head;
IntNode lowestPrev = null;
IntNode lowest = head;
while (head != null)
{
lowestPrev = null;
current = head;
while (current != null)
{
if (current.value < lowest.value)
{
lowest = current;
lowestPrev = prev;
}
prev = current
current = current.next;
}
if (resultHead = null)
{
resultHead = lowest;
resultTail = lowest;
}
else
resultTail.next = lowest;
if (lowest == head)
head = head.next;
else
lowestPrev.next = lowest.next;
}
return resultHead;
}
I am working on a multi-level marketing (binary) which looks like this:
(but the binary tree is not required to be perfect. A node can have 0-2 child)
My problem is the data that I fetch from the database is flat list.
Notice that I am using hierarchyid (sql server 2014)
Basically the TextNode column is like a breadcrumb.
every slash / represents a level.
If I have TextNode of /1/ as root. then every node that starts with /1/ belongs to that root which are /1/, /1/1/ and /1/1/1/ (the root node is included which will be the level 0)
I've tried the accepted answer in this question but its not working.
How can I transform the flatlist to a Binary Tree so that I can easily traverse and display it on a screen?
Im using C#, ASP MVC 5, SQL Server 2014 if it matters.
I implement exactly this code According to Alex implementation but as is mentioned in some case it didn't work correctly .. have a look to my Image and my code (which copied from Alex post) [data in the database are correct but in tree view seems some problems ]
public class Row : IRow<string>
{
public string TextNode { get; }
public string Value { get; }
public long Id { get; }
public string FIN { get; }
public Row(string textNode, string userName, long id, string fin)
{
FIN = fin;
Id = id;
TextNode = textNode;
Value = userName;
}
}
public interface IRow<out T>
{
string TextNode { get; }
long Id { get; }
string FIN { get; }
T Value { get; }
}
public class TreeNode<T>
{
private struct NodeDescriptor
{
public int Level { get; }
public int ParentIndex { get; }
public NodeDescriptor(IRow<T> row)
{
var split = row.TextNode.Split(new[] { "/" }, StringSplitOptions.RemoveEmptyEntries);
Level = split.Length;
ParentIndex = split.Length > 1 ? int.Parse(split[split.Length - 2]) - 1 : 0;
}
}
public T title { get; }
public long Id { get; }
public string FIN { get; }
public List<TreeNode<T>> children { get; }
private TreeNode(T value, long id, string fin)
{
Id = id;
FIN = fin;
title = value;
children = new List<TreeNode<T>>();
}
public static TreeNode<T> Parse(IReadOnlyList<IRow<T>> rows)
{
if (rows.Count == 0)
return null;
var result = new TreeNode<T>(rows[0].Value, rows[0].Id, rows[0].FIN);
FillParents(new[] { result }, rows, 1, 1);
return result;
}
private static void FillParents(IList<TreeNode<T>> parents, IReadOnlyList<IRow<T>> rows, int index, int currentLevel)
{
var result = new List<TreeNode<T>>();
for (int i = index; i < rows.Count; i++)
{
var descriptor = new NodeDescriptor(rows[i]);
if (descriptor.Level != currentLevel)
{
FillParents(result, rows, i, descriptor.Level);
return;
}
var treeNode = new TreeNode<T>(rows[i].Value, rows[i].Id, rows[i].FIN);
parents[descriptor.ParentIndex].children.Add(treeNode);
result.Add(treeNode);
}
}
}
g
this is also my JSON output for more information :
{"title":"Earth","Id":32,"FIN":"FIN","children":[{"title":"Europe","Id":33,"FIN":"FIN001","children":[{"title":"France","Id":35,"FIN":"FIN001001","children":[{"title":"Paris","Id":36,"FIN":"FIN001001001","children":[]},{"title":"Brasilia","Id":41,"FIN":"FIN002001001","children":[]},{"title":"Bahia","Id":42,"FIN":"FIN002001002","children":[]}]},{"title":"Spain","Id":38,"FIN":"FIN001002","children":[{"title":"Madrid","Id":37,"FIN":"FIN001002001","children":[{"title":"Salvador","Id":43,"FIN":"FIN002001002001","children":[]}]}]},{"title":"Italy","Id":45,"FIN":"FIN001003","children":[]},{"title":"Germany","Id":48,"FIN":"FIN001004","children":[]},{"title":"test","Id":10049,"FIN":"FIN001005","children":[]}]},{"title":"South America","Id":34,"FIN":"FIN002","children":[{"title":"Brazil","Id":40,"FIN":"FIN002001","children":[{"title":"Morano","Id":47,"FIN":"FIN001003001","children":[]}]}]},{"title":"Antarctica","Id":39,"FIN":"FIN003","children":[{"title":"McMurdo Station","Id":44,"FIN":"FIN003001","children":[]}]}]}
Here is a very simple implementation (assuming that Nodes are in the right order), which may be enhanced in multiple ways
public interface IRow<out T>
{
string TextNode { get; }
T Value { get; }
}
public class TreeNode<T>
{
private struct NodeDescriptor
{
public int Level { get; }
public int ParentIndex { get; }
public NodeDescriptor(IRow<T> row)
{
var split = row.TextNode.Split(new [] {"/"}, StringSplitOptions.RemoveEmptyEntries);
Level = split.Length;
ParentIndex = split.Length > 1 ? int.Parse(split[split.Length - 2]) - 1 : 0;
}
}
public T Value { get; }
public List<TreeNode<T>> Descendants { get; }
private TreeNode(T value)
{
Value = value;
Descendants = new List<TreeNode<T>>();
}
public static TreeNode<T> Parse(IReadOnlyList<IRow<T>> rows)
{
if (rows.Count == 0)
return null;
var result = new TreeNode<T>(rows[0].Value);
FillParents(new[] {result}, rows, 1, 1);
return result;
}
private static void FillParents(IList<TreeNode<T>> parents, IReadOnlyList<IRow<T>> rows, int index, int currentLevel)
{
var result = new List<TreeNode<T>>();
for (int i = index; i < rows.Count; i++)
{
var descriptor = new NodeDescriptor(rows[i]);
if (descriptor.Level != currentLevel)
{
FillParents(result, rows, i, descriptor.Level);
return;
}
var treeNode = new TreeNode<T>(rows[i].Value);
parents[descriptor.ParentIndex].Descendants.Add(treeNode);
result.Add(treeNode);
}
}
}
Sample usage:
public class Row : IRow<string>
{
public string TextNode { get; }
public string Value { get; }
public Row(string textNode, string userName)
{
TextNode = textNode;
Value = userName;
}
}
class Program
{
static void Main(string[] args)
{
IRow<string>[] rows =
{
new Row("/", "Ahmed"),
new Row("/1/", "Saeed"),
new Row("/2/", "Amjid"),
new Row("/1/1/", "Noura"),
new Row("/2/1/", "Noura01"),
new Row("/2/2/", "Reem01"),
new Row("/1/1/1", "Under_noura")
};
var tree = TreeNode<string>.Parse(rows);
PrintTree(tree);
}
private static void PrintTree<T>(TreeNode<T> tree, int level = 0)
{
string prefix = new string('-', level*2);
Console.WriteLine("{0}{1}", prefix, tree.Value);
foreach (var node in tree.Descendants)
{
PrintTree(node, level + 1);
}
}
}
I am storing Linked Lists in an Array List. Each linked list contains different items. I would like to retrieve a particular linkedlist from the array list such as at index position 0 of the and perform certain operations e.g. traversing from the front. However I am having problems getting the array items to be recognised as linked lists. What would be the best way of doing that?
E.g if I have
static ArrayList ar = new ArrayList();
static DLinkedList b = new DLinkedList();
And would like to do the following.
b.TraverseFront(ar[0]);
I have given an example below which I implemented in C#
class Program
{
static ArrayList ar = new ArrayList();
static DLinkedList b = new DLinkedList();
static void Main(string[] args)
{
store("huggo boss");
b.TraverseFront(ar[0]); // THIS IS WHAT I'D LIKE TO DO BUT I DON'T KNOW HOW TO DO IT
}
private static void store(string s)
{
DLinkedList linkedListNode = new DLinkedList();
string output = null;
string norm = null;
int token = 3;
for (int i = 0; i < s.Length; i++)
{
if (!String.IsNullOrWhiteSpace(char.ToString(s[i])))
{
output = output + s[i];
}
}
for (int j = 0; j < output.Length - token + 1 ; j++)
{
norm = norm + output[j] + output[j + 1] + output[j + 2]
linkedListNode.InsertNext(norm);
norm = null;
}
}
}
}
class DLinkedList
{
private Object data;
private DLinkedList next;
private DLinkedList prev;
/*
static void Main(string[] args)
{
DLinkedList node1 = new DLinkedList(1);
DLinkedList node3 = node1.InsertNext(3);
DLinkedList node2 = node3.InsertPrev(2);
DLinkedList node5 = node3.InsertNext(5);
DLinkedList node4 = node5.InsertPrev(4);
node1.TraverseFront();
node5.TraverseBack();
Console.Read();
}
*/
public DLinkedList()
{
data = null;
next = null;
prev = null;
}
public DLinkedList(Object value)
{
data = value;
next = null;
prev = null;
}
public DLinkedList InsertNext(Object value)
{
DLinkedList node = new DLinkedList(value);
if (this.next == null)
{
// Easy to handle
node.prev = this;
node.next = null; // already set in constructor
this.next = node;
}
else
{
// Insert in the middle
DLinkedList temp = this.next;
node.prev = this;
node.next = temp;
this.next = node;
temp.prev = node;
// temp.next does not have to be changed
}
return node;
}
public DLinkedList InsertPrev(Object value)
{
DLinkedList node = new DLinkedList(value);
if (this.prev == null)
{
node.prev = null; // already set on constructor
node.next = this;
this.prev = node;
}
else
{
// Insert in the middle
DLinkedList temp = this.prev;
node.prev = temp;
node.next = this;
this.prev = node;
temp.next = node;
// temp.prev does not have to be changed
}
return node;
}
public void TraverseFront()
{
TraverseFront(this);
}
public void TraverseFront(DLinkedList node)
{
if (node == null)
node = this;
System.Console.WriteLine("\n\nTraversing in Forward
Direction\n\n");
while (node != null)
{
System.Console.WriteLine(node.data);
node = node.next;
}
}
public void TraverseBack()
{
TraverseBack(this);
}
public void TraverseBack(DLinkedList node)
{
if (node == null)
node = this;
while (node != null)
{
System.Console.WriteLine(node.data);
node = node.prev;
}
}
internal void TraverseFront(object p)
{
throw new NotImplementedException();
}
}
}
class Node
{
public int Data { get; set; }
public Node Next { get; set; }
public int Counter { get; set; }
public Node(int element,int counter)
{
Data = element;
Counter = counter;
Next=null;
}
}
I use counter as a TAG on person, or in other words the position from which elimination starts.
class CircularLinkedList
{
Node first;
Node last;
public CircularLinkedList()
{
first = last = null;
}
protected void Insert(int element,int counter)
{
if (IsEmpty())
{
first = last = new Node(element,counter);
}
else
{
last.Next = last = new Node(element,counter);
last.Next = first;
}
}
public int RemoveAt(int index)
{
int value = 0;
Node current = first;
do
{
if (current.Counter == index)
{
value = current.Data;
}
current = current.Next;
} while (current != first);
return value;
}
public void AddMen(int n)
{
for (int i = 1; i <= n; i++)
{
Insert(i*2,i);
}
}
public int Eliminate(int m)
{
int value = 0;
Node current = first;
do
{
value = RemoveAt(m);
current = current.Next;
} while (current != first);
return value;
}
public bool IsEmpty()
{
return first == null;
}
public void Display()
{
Node current = first;
do
{
Console.WriteLine(current.Counter+" "+current.Data+" ");
current = current.Next;
} while (current!=first);
}
}
I am having problem with elimination method, I want it must be constantly called until the list is empty,
I would do:
public int Eliminate(int m)
{
int value = 0;
Node current = first;
Node nextNode;
do
{
nextNode = current.next;
value = RemoveAt(m);
current = nextNode;
} while (current != first);
return value;
}