C# Radix Sort implementation in LinkedList - c#

i have a task to make a radix sort algorithm for a linkedlist class, i have an object "Info", which has int Year and double Price, i need to sort linked list by Year using radix sorting.
class Info
{
public int Year { get; set; }
public double Price { get; set; }
public Info() { }
public Info(int y, double p)
{
Year = y;
Price = p;
}
}
class Node
{
public Info Data { get; set; }
public Node Next { get; set; }
public Node(Info data, Node adress)
{
Data = data;
Next = adress;
}
}
class LinkedList
{
private Node First;
private Node Last;
private Node Current;
public LinkedList()
{
First = null;
Last = null;
Current = null;
}
}
And i have taken radix sort algorithm for integer from this site. Problem is, i don't know how to modify it to work with my linked class.
static void Sort(int[] arr)
{
int temp = 0;
int i, j;
int[] tmp = new int[arr.Length];
for (int shift = 31; shift > -1; --shift)
{
j = 0;
for (i = 0; i < arr.Length; ++i)
{
bool move = (arr[i] << shift) >= 0;
if (shift == 0 ? !move : move)
arr[i - j] = arr[i];
else
tmp[j++] = arr[i];
}
Array.Copy(tmp, 0, arr, arr.Length - j, j);
}
}
How to make it work with my linked class ?

Based on that code, arr and tmp would need to be linked lists. One issue with this approach is that moving a node requires keeping track of the previous nodes in order to move a node. A dummy head node could be used to provide a node previous to the first data node, or special case handing when moving a node to the start of a list. An alternative would be using two pointers (references) to nodes of temp lists, one where bit == 0, one where bit == 1, and then concatenating the two temp lists into a single list. Note this approach takes 32 passes. If the radix sort were based on a byte instead of a bit, it could be reduced to 4 passes, but would need 256 pointers to nodes for 256 lists.

Related

Join element from array if the array element length is less than 5

I am trying to join the next array element together to single element from array if the element of the array is less than length 4. It should add to the next element index.
Another logic is, if the next consecutive array length is also less then 4 char then it joins the next array element also up to 3 times in total. I want to implement this. It's getting complex for me I am not understand this logic.
This is the code, here it has array on titleList, now we have to use the above logic in this array list.
#foreach (var title in randomtitle)
{
</span>#titleList.ElementAt(title)</span>
}
#code {
[Parameter]
public string theTitle { get; set; }
private string[] titleList = Array.Empty<string>();
protected override void OnParametersSet()
{
if (!string.IsNullOrEmpty(theTitle))
{
titleList = theTitle.Split(" ");
}
}
private Random random = new();
private IEnumerable<int> randomtitle =>
Enumerable.Range(0, titleList.Count() - 1) // { 0, 1, 2, 3 } generate sequence
.OrderBy(x => random.Next()) // { 3, 1, 0, 2 } random shuffle
.Take(2) // { 3, 1 } pick two
.ToList();
}
I think you are looking for a method that does following:
take a collection of strings(like a string[])
iterate each string and check if it's length is greater than or equal 4
if so, everything is fine, take it as it is
if not, append the next to the current string and check their length afterwards
if they are still not greater than or equal 4 append the next one, but max 3 times
Then this should work (not tested well though):
Demo: https://dotnetfiddle.net/2uHREv
static string[] MergeItems(IList<string> all, int minLength, int maxGroupCount)
{
List<string> list = new List<string>(all.Count);
for(int i = 0; i < all.Count; i++)
{
string current = all[i];
if(i == all.Count - 1)
{
list.Add(current);
break;
}
if (current.Length < minLength)
{
for (int ii = 1; ii < maxGroupCount && i + ii < all.Count; ii++)
{
int nextIndex = i + ii;
string next = all[nextIndex];
current = current + next;
if (current.Length >= minLength || ii+1 == maxGroupCount)
{
list.Add(current);
i = nextIndex;
break;
}
}
}
else
{
list.Add(current);
}
}
return list.ToArray();
}

C# Optimize Conditional in Loop where input is a value that needs to be between a start/end value found in each list item

EDIT: This is a general problem when you are stuck in a situation that you have to use a List instead of a Dictionary because instead of searching for a key you may be searching for a range of number like a text minimum and maximum index, and each item may have inner items in them, in my case it added up to 100k+ items before I found a workable solution just after posting this question.
Solution below involves partitioning the list into smaller chunks, much like database indexing.
I call the following a lot in a particular project. It works fine, but there's a problem with this as far as optimization is concerned. I have an index and need to get all text spans where the index is between the start and end, as shown below.
Example:
List<Lexer.Span> spans = new List<Lexer.Span>();
for (int i1 = 0; i1 < input.OrganizedSpans.Count; i1++)
{
Lexer.Span span1 = input.OrganizedSpans[i1];
if (index >= span1.Start && index < span1.End) { spans.Add(span1); }
}
...
public class Lexer {
...
public class Span
{
public int Start {get;set;}
public int End {get;set;}
public string Text {get;set;}
public List<Span> InnerSpans {get;set;} = new List<Span>();
}
}
OrganizedSpans has 6,000+ items stemming from lexemes tokenized of an 18k HTML document, so it gets weighed down significantly doing a straight iteration. I will show you a partitioning optimization in the answer that will help in situations like this. It brought my execution down from a few seconds to near-instantaneous.
Original: It works, but is a bottleneck according to the Visual Studio Profiler on the if conditional line. It gets called quite a bit from the parser code.
Is there a faster way to do what I want to do here? I've looked at several optimization articles and stackoverflow posts, but am having trouble finding it.
UPDATE: Yes there is. :)
The answer is simple, partition your lists into smaller lists, here's an example code:
List Partition Building, replace Span and Lexer for whatever you need to partition, in my case it was a syntax node tree of text from an LL(1) parser:
public class LexerResult
{
public class ResultPartition
{
public int Minimum { get; set; }
public int Maximum { get; set; }
public List<Span> Spans { get; set; }
}
public List<Span> RawSpans { get; set; }
public List<Span> OrganizedSpans { get; set; }
public List<ResultPartition> OrganizedPartitions { get; set; }
...
Partition Method:
public List<LexerResult.ResultPartition> OrganizePartitions(List<Span> spans, int partitionSize = 300)
{
List<LexerResult.ResultPartition> partitions = new List<LexerResult.ResultPartition>();
bool done = false;
int recordsProcessed = 0;
while(!done)
{
int recordsNeeded = 0;
if (recordsProcessed + partitionSize > spans.Count)
{
recordsNeeded = spans.Count - recordsProcessed;
done = true;
}
else
{
recordsNeeded = partitionSize;
}
int recordsNeededEnd = recordsProcessed + recordsNeeded;
int min = Int32.MaxValue;
int max = Int32.MinValue;
List<Span> partition = new List<Span>();
for(int i=recordsProcessed;i<recordsNeededEnd;i++)
{
Span span = spans[i];
min = Math.Min(span.Start, min);
max = Math.Max(span.End, max);
partition.Add(span);
}
recordsProcessed += recordsNeeded;
LexerResult.ResultPartition resultPartition = new LexerResult.ResultPartition()
{
Spans = partition,
Maximum = max,
Minimum = min
};
partitions.Add(resultPartition);
}
return partitions;
}
Usage:
List<Lexer.Span> spans = new List<Lexer.Span>();
for(int i1=0;i1<input.OrganizedPartitions.Count;i1++)
{
Lexer.LexerResult.ResultPartition partition = input.OrganizedPartitions[i1];
if (partition.Minimum <= index && index < partition.Maximum)
{
List<Lexer.Span> spans_1a = partition.Spans;
for (int i3 = 0; i3 < spans_1a.Count; i3++)
{
Lexer.Span span_1a = spans_1a[i3];
if (span_1a.Start <= index && index < span_1a.End)
{
spans.Add(span_1a);
}
}
}
...
}
Note: Using for instead of foreach does seem to clock faster in Visual Studio's Profiler.
So I'm taking a minimum and maximum from each span and building partitions that have a min/max property you can use for easily seeing which data points have a start and end surrounding whatever index you supply.
I didn't see this mentioned on any of the articles and posts I read about optimizing .NET code so it seemed worth mention. The program I'm writing is running near-instantaneous and soon to be released after some testing/documentation.

Printing a binary tree in order

I have a problem to convert a sorted array to a binary tree. I think that I have done it. Now I just want to print all items after conversion to double check it.
My question is that my printing part doesn't print all items. Something is wrong in the method 'inOrderTraversalHelper'.
class Program
{
// Given an array where elements are sorted in ascending order,
// convert it to a height balanced BST
static int[] arr = new int[8] {1,2,3,4,5,6,7,8};
static TreeNode node { get; set; }
static void Main(string[] args)
{
node = SortedArrayToBST(arr, 0, arr.Length-1);
inOrderTraversal();
}
static void inOrderTraversal()
{
inOrderTraversalHelper(node);
}
static void inOrderTraversalHelper(TreeNode r)
{
if (r != null)
{
**// UPDATED**
inOrderTraversalHelper(r.leftNode);
Console.Write("{0} ", r.data);
inOrderTraversalHelper(r.rightNode);
}
}
static TreeNode SortedArrayToBST(int[] a,int start,int end)
{
if (start > end) return null;
int mid = (start + end) / 2;
TreeNode node = new TreeNode(a[mid]);
node.leftNode= SortedArrayToBST(a, start, mid-1);
node.rightNode = SortedArrayToBST(a, mid + 1, end);
return node;
}
}
public class TreeNode
{
public int data;
public TreeNode leftNode;
public TreeNode rightNode;
public TreeNode(int data)
{
this.data = data;
}
}
It's because you are storing the value of the index mid not the value at the index of mid:
int mid = (start + end) / 2;
TreeNode node = new TreeNode(mid);
You are calculating the value of mid and then passing it in as the data. Instead mid should be the index of the value you want. For, example if you had a data set where the data was ordered but non sequential you'd get even stranger results:
{-1,22,33,44,55,66,77,100}
So your code should probably look up the value at index mid instead:
var mid = (int)((start + end) / 2.0);
var node = new TreeNode(arr[mid]);
In SortedArrayToBST, you work with the index mid, rather than with the element a[mid], change:
TreeNode node = new TreeNode(mid);
to:
TreeNode node = new TreeNode(a[mid]);
In the call to the SortedArrayToBST function, you need to pass array size - 1, since the end condition in inclusive, change:
node = SortedArrayToBST(arr, 0, arr.Length);
to:
node = SortedArrayToBST(arr, 0, arr.Length-1);
Also, your inOrderTraversalHelper function isn't actually in-order, but rather post-order.

C#: Linking string[] and int[] elements to stay together when sorting int[]

So I need to take names and ages of people, store them in two separate arrays, sort them by age, and then display the results in a listbox. I have everything down until putting it back into the listbox. It sounds simple, but the foreach loop (from my very basic understanding of C#) can only take the values of one of the arrays. I need the names and ages on the same line because they're linked together, so I decided to switch to a for loop. However, even though my sorting on the Ages works just fine, I can't make the name match the age. Here is some of my code:
const int MAX = 100;
int count = 0;
int[] Age = new int[MAX];
string[] NameEntry = new string[MAX];
Just to show you how I declared the arrays. Here is my "store" click event:
int age;
if (txtName.Text == "")
{
lblWarningMessage.Text = "There is an error with your entries. A name must be entered!";
btnClearWarn.Show();
}
else
{
NameEntry[count] = txtName.Text;
if (int.TryParse(txtAge.Text, out age))
{
Age[count] = age;
txtAge.Clear();
txtName.Clear();
txtName.Focus();
lstbxResults.Items.Add(NameEntry[count] + " is " + Age[count].ToString() + " years old.");
count++;
}
else
{
lblWarningMessage.Text = "There is an error with your entries. The Age entry must be an integer.";
btnClearWarn.Show();
}
}
And finally, the sorting operation and subsequent for loop to add it to my listbox:
Array.Resize(ref NameEntry, count);
Array.Resize(ref Age, count);
lstbxResults.Items.Clear();
int minAge = 0;
int minIndex = 0;
for (int a = 0; a < Age.Length - 1; a++)
{
minAge = Age[a];
minIndex = a;
for (int b = a + 1; b < Age.Length; b++)
{
if (Age[b] < minAge)
{
minAge = Age[b];
minIndex = b;
}
}
OrderByAges(ref Age[minIndex], ref Age[a]);
}
for (int c = 0; c < Age.Length; c++)
{
lstbxResults.Items.Add(NameEntry[c] + " is " + Age[c] + " years old.");
}
}
private void OrderByAges(ref int p1, ref int p2)
{
int temp = p2;
p2 = p1;
p1 = temp;
}
Yes, I realize Array.sort would be faster, but this serves the same purpose, and this is how I was instructed to do it. Any thoughts on how to link the element in "NameEntry" to "Age", and have it change along with the Age when it is sorted?
You really should use "Array.Sort" in this case. It is capable of co-sorting keys and values in two linked arrays, as in:
Array.Sort(Age, NameEntry, 0, count);
If your teacher really insists on a solution that does not use Array.Sort, just use a quicksort implementation that simply swaps the elements of both key and value at the same time:
Like this (not tested):
public static class CoSorter
{
public static void Sort<TKey, TValue>(this TKey[] keys, TValue[] values, int start, int count)
{
QuickCosort(keys, values, start, count - 1, Comparer<TKey>.Default);
}
public static void Sort<TKey, TValue>(this TKey[] keys, TValue[] values, int start, int count, IComparer<TKey> comparer)
{
QuickCosort(keys, values, start, count - 1, comparer);
}
private static void QuickCosort<TKey, TValue>(TKey[] keys, TValue[] values, int left, int right, IComparer<TKey> comparer)
{
int i = left, j = right;
var pivot = keys[(left + right) / 2];
while (i <= j)
{
while (comparer.Compare(keys[i], pivot) < 0)
{
i++;
}
while (comparer.Compare(keys[j], pivot) > 0)
{
j--;
}
if (i <= j)
{
// Swap
var tmpKey = keys[i];
var tmpVal = values[i];
keys[i] = keys[j];
values[i] = values[j];
keys[j] = tmpKey;
values[j] = tmpVal;
i++;
j--;
}
}
// Recursive calls
if (left < j)
{
QuickCosort(keys, values, left, j, comparer);
}
if (i < right)
{
QuickCosort(keys, values, i, right, comparer);
}
}
}
Alternatively you may want to think about this a bit harder and see if maybe you need a data structure instead of two arrays of values that belong together.
Reaction to OP's comment under Alex' answer - if this is a homework/school assignment, it's a good custom on StackOverflow to say so in the question in the first place.
If your teacher doesn't want you to use Array.Sort, is the assignment by any chance primarily about implementing a sorting algorithm? If so, it's obvious that you should implement your own and not use a library function - and again it would be best to have that in the question.
Anyway whether it's the case or not, the most sensible solution would be to create a Person class containing both Name and Age, sort array of people by age and fill the listbox by their names (or rather use a data binding, like this). Two individual arrays of related values don't make much sense in object oriented world and are harder to maintain - as is visible in your case.
If you have to use two separate parallel arrays, the elements of each array are linked by the index. But they are only linked because you happen to put the elements in at the same index. It's not automagic. So when you move something in one array, remember the indexes used, and use those to move the same thing in the other array.
Your code moves the age in the double nested loop, so move the name in that code as well.

How to create a binary tree

I did'nt mean binary search tree.
for example,
if I insert values 1,2,3,4,5 in to a binary search tree the inorder traversal will give
1,2,3,4,5 as output.
but if I insert the same values in to a binary tree, the inorder traversal should give
4,2,5,1,3 as output.
Binary tree can be created using dynamic arrays in which for each element in index n,
2n+1 and 2n+2 represents its left and right childs respectively.
so representation and level order traversal is very easy here.
but I think, in-order,post-order,pre-order is difficult.
my question is how can we create a binary tree like a binary search tree.
ie.
have a tree class which contains data, left and right pointers instead of arrays.
so that we can recursively do traversal.
If I understand you correctly, you want to create a binary tree from an array
int[] values = new int[] {1, 2, 3, 4, 5};
BinaryTree tree = new BinaryTree(values);
this should prepopulate the binary tree with the values 1 - 5 as follows:
1
/ \
2 3
/ \
4 5
this can be done using the following class:
class BinaryTree
{
int value;
BinaryTree left;
BinaryTree right;
public BinaryTree(int[] values) : this(values, 0) {}
BinaryTree(int[] values, int index)
{
Load(this, values, index);
}
void Load(BinaryTree tree, int[] values, int index)
{
this.value = values[index];
if (index * 2 + 1 < values.Length)
{
this.left = new BinaryTree(values, index * 2 + 1);
}
if (index * 2 + 2 < values.Length)
{
this.right = new BinaryTree(values, index * 2 + 2);
}
}
}
Since I have not received any answers to the question which I asked, I will post my own implementaion of the binary tree using arrays.
now I know that array implementaion is easier than i thought ,but still i dont know how to implement the same using linked lists.
the code is in c#
class BinaryTree
{
private static int MAX_ELEM = 100; //initial size of the array
int lastElementIndex;
int?[] dataArray;
public BinaryTree()
{
dataArray = new int?[MAX_ELEM];
lastElementIndex = -1;
}
//function to insert data in to the tree
//insert as a complete binary tree
public void insertData(int data)
{
int?[] temp;
if (lastElementIndex + 1 < MAX_ELEM)
{
dataArray[++lastElementIndex] = data;
}
else
{ //double the size of the array on reaching the limit
temp = new int?[MAX_ELEM * 2];
for (int i = 0; i < MAX_ELEM; i++)
{
temp[i] = dataArray[i];
}
MAX_ELEM *= 2;
dataArray = temp;
dataArray[++lastElementIndex] = data;
}
}
//internal function used to get the left child of an element in the array
int getLeftChild(int index) {
if(lastElementIndex >= (2*index+1))
return (2*index + 1);
return -1;
}
//internal function used to get the right child of an element in the array
int getRightChild(int index) {
if(lastElementIndex >= (2*index+2))
return (2*index + 2);
return -1;
}
//function to check if the tree is empty
public bool isTreeEmpty() {
if (lastElementIndex == -1)
return true;
return false;
}
//recursive function for inorder traversal
public void traverseInOrder(int index) {
if (index == -1)
return;
traverseInOrder(getLeftChild(index));
Console.Write("{0} ", dataArray[index]);
traverseInOrder(getRightChild(index));
}
//recursive function for preorder traversal
public void traversePreOrder(int index) {
if (index == -1)
return;
Console.Write("{0} ", dataArray[index]);
traversePreOrder(getLeftChild(index));
traversePreOrder(getRightChild(index));
}
//recursive function for postorder traversal
public void traversePostOrder(int index) {
if (index == -1)
return;
traversePostOrder(getLeftChild(index));
traversePostOrder(getRightChild(index));
Console.Write("{0} ", dataArray[index]);
}
//function to traverse the tree in level order
public void traverseLevelOrder()
{
Console.WriteLine("\nPrinting Elements Of The Tree In Ascending Level Order\n");
if (lastElementIndex == -1)
{
Console.WriteLine("Empty Tree!...press any key to return");
Console.ReadKey();
return;
}
for (int i = 0; i <= lastElementIndex; i++)
{
Console.Write("{0} ", dataArray[i]);
}
Console.WriteLine("\n");
}
}
The tree class declaration part is, certainly, not the difficulty here. You basically stated exactly how to declare it, in the question:
class BinaryTree
{
private:
int data;
BinaryTree *left, *right;
};
This supports various forms of traversal, like so:
void Inorder(const BinaryTree *root)
{
if(root == 0)
return;
Inorder(root->left);
printf("now at %d\n", root->data);
Inorder(root->right);
}
You should be able to deduce pre- and post-order traversals from that. In a real implementation, the tree would probably be templated to store random data, the traversal routines would be more general (with a user-data input, or perhaps user-supplied per-node callback, or whatever), of course.
If you're after source for a comprehensive BinaryTree implementation you can learn from have a look at The C5 Generic Collection Library.
class BstNode
{
public int data;
public BstNode(int data)
{
this.data = data;
}
public BstNode left;
public BstNode right;
}
class Program
{
public static BstNode Insert(BstNode root, int data)
{
if (root == null) root = new BstNode(data);
else if (data <= root.data) root.left = Insert(root.left, data);
else if (data > root.data) root.right = Insert(root.right, data);
return root;
}
public static void Main(string[] args)
{
// create/insert into BST
BstNode Root = null;
Root = Insert(Root, 15);
Root = Insert(Root, 10);
Root = Insert(Root, 20);
Root = Insert(Root, 8);
Root = Insert(Root, 12);
Root = Insert(Root, 17);
Root = Insert(Root, 25);
}
}

Categories

Resources