Sorting a Queue - c#

I have to simulate a process scheduler using SRTN algorithm and im having trouble within a certain part.
I have a queue of a custom class called 'Process' I need to sort it based on a a field called 'last_prediction'. My code works most of the time, but if you look at time:19 of my output, the output in the ready queue is wrong (it should be: 1004(1.5) 1002(2) 1003(2)).
Here is my code:
int count = ReadyQueue.Count;
// Copy Queue into Vector
ArrayList temp = new ArrayList();
for (int i = 0; i < count; i++)
{
Process p = (Process)ReadyQueue.Dequeue();
temp.Add(p);
}
// Sort Vector
for (int i = 0; i < count; i++)
{
double min = ((Process)temp[i]).last_prediction;
for (int j=i+1; j<count; j++)
{
if ( ((Process)temp[j]).last_prediction < min )
{
min = ((Process)temp[j]).last_prediction;
Process dummy = (Process)temp[j];
temp[j] = temp[i];
temp[i] = dummy;
}
}
}
// Copy Vector back into Queue
for (int i = 0; i < count; i++)
{
Process p = (Process)temp[i];
ReadyQueue.Enqueue(p);
}
EDIT: ok, im trying to use ICompare, similar to what you gave hughdbrown.Now i get a different error:
public class Process
{
public int process_id;
public int arrival_time;
public int total_time;
public int avg_burst;
public int actual_burst;
public int last_burst; // SRTN
public double last_prediction; // SRTN
public int io_delay;
public int context_switch_delay;
public class ProcessSort : IComparer
{
public int Compare(object x, object y)
{
var a = x as Process;
var b = y as Process;
double aNum = a.last_prediction;
double bNum = b.last_prediction;
return Compare(aNum, bNum);
}
}
}
this is the error i get now:
Unhandled Exception: System.InvalidOperationException: Failed to compare two elements in the array. ---> System.NullReferenceException: Object reference not set to an instance of an object.

I would use a real sorting routine on this array, not a hand-crafted insertion/bubble sort. Add a comparison function to your object.
I'd also use a templatized data collection, not ArrayList. You might be interested in using this C# PriorityQueue code from my website. That has Queue semantics and maintains items in a sorted order.
Later: Your IComparable code would be something like this:
public class Process : IComparable
{
int last_prediction;
public int CompareTo(object obj)
{
Process right = obj as Process;
return this.last_prediction.CompareTo(right.last_prediction);
}
}
Later still: here is a complete test program that has a sortable Process. Tested in Mono on ubuntu.
using System;
using System.Collections.Generic;
using System.Text;
namespace Comparer
{
public class Process : IComparable
{
int last_prediction;
public Process(int p)
{
this.last_prediction = p;
}
public int CompareTo(object obj)
{
Process right = obj as Process;
return this.last_prediction.CompareTo(right.last_prediction);
}
public int Prediction { get { return this.last_prediction; } }
}
class MainClass
{
public static void Main (string[] args)
{
List<Process> list = new List<Process>();
for (int i = 0; i < 10; i++)
list.Add(new Process(10 - i));
System.Console.WriteLine("Current values:");
foreach (Process p in list)
System.Console.WriteLine("Process {0}", p.Prediction);
list.Sort();
System.Console.WriteLine("Sorted values:");
foreach (Process p in list)
System.Console.WriteLine("Process {0}", p.Prediction);
}
}
}

Have you considered using the ArrayList.Sort method instead of attempting to write your own sort?

Here's how I would sort the Process objects. Let's use a List<Process> instead of an ArrayList so that we don't have to keep casting it back and forth. I haven't done much with queues in C# so I'm afraid I can't help much with those. And please note that this code is untested. :)
int count = ReadyQueue.Count;
// Copy Queue into Vector
List<Process> listProcesses = new List<Process>();
for(int i = 0; i < count; i++)
{
Process p = (Process)ReadyQueue.Dequeue();
listProcesses.Add(p);
}
// Sort Vector
listProcesses.Sort(CompareProcessesByPrediction);
// Copy Vector back into Queue
foreach(Process p in listProcesses)
ReadyQueue.Enqueue(p);
private static int CompareProcessesByPrediction(Process proc1, Process proc2)
{
//if they're both not-null, figure out which one is greatest/smallest.
//otherwise just pick the one that isn't null
if(proc1 == null)
return proc2 == null ? 0 : -1;
else
return proc1 == null ? 1 : proc1.last_prediction.CompareTo(proc2.last_prediction);
}

yea.. use arraylist.sort
If ur array only got numbers, create a new number array coz.. arraylist.sort for string has some problem.
and use arraylist.sort
take the number of the position you want and convert back to string if u want..

Related

How can I prevent StackOverflowException in my code

In my code, I cannot figure out why I keep getting 'Process is terminating due to StackOverflowException.' only on the second output.
using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
namespace _2018JuniorQ5
{
class Program
{
//Variable Decleration
public static int pages = 0;
public static string[] bookFormat;
public static List<string> alreadyChecked = new List<string>();
public static List<string> nodesToCheck = new List<string>();
public static int level = 0;
public static List<string> childrenNodes = new List<string>();
public static void Main(string[] args)
{
//Get input
pages = Convert.ToInt32(Console.ReadLine());
bookFormat = new string[pages];
for (int x=0; x<pages; x++)
{
bookFormat[x] = Console.ReadLine();
}
//Display if all pages are reachable
Console.WriteLine(getReachablePages(1));
//Find shortest path
List<string> NodeBegin = new List<string>();
NodeBegin.Add("1");
Console.WriteLine(getShortestPath(NodeBegin));
}
public static string getReachablePages(int pageToCheck)
{
string[] options=(bookFormat[pageToCheck - 1]).Split(' ');
alreadyChecked.Add(Convert.ToString(pageToCheck));
for (int a=1; a<=Convert.ToInt32(options[0]); a++)
{
if (!alreadyChecked.Contains(options[a]))
{
getReachablePages(Convert.ToInt32(options[a]));
}
}
if (alreadyChecked.Count == pages)
{
return "Y";
}
else
{
return "N";
}
alreadyChecked.Clear();
}
public static int getShortestPath(List<string> nodesToCheck)
{
level++;
childrenNodes.Clear();
for (int q = 0; q < nodesToCheck.Count; q++)
{
string[] options = bookFormat[Convert.ToInt32(nodesToCheck[q])-1].Split(' ');
if (options[0] == "0")
{
return level;
}
else
{
for (int t = 1; t < options.Length; t++)
{
if (!alreadyChecked.Contains(options[t]))
{
childrenNodes.Add(options[t]);
alreadyChecked.Add(nodesToCheck[q]);
}
}
}
nodesToCheck.Clear();
}
return getShortestPath(childrenNodes);
}
}
}
The first output from the getReachablePages method works, and does not give any errors. However, the second output from the getShortestPath gives the "Process is terminating due to StackOverflowException" error. Can someone explain why the getReachablePages method works, but the getShortestPath method doesn't work?
The problem at the moment is that List<string> is a reference type, so when you pass childrenNodes to getShortestPath (getShortestPath(childrenNodes)), you're actually passing a reference to the same list in memory.
The next thing you do is call childrenNodes.Clear(), which empties that list. Because nodesToCheck and childrenNodes are both pointing at the same list, calling childrenNodes.Clear() means that you have no nodes to check.
Why does this cause a StackOverflowException? It causes one because you have no exit condition for when nodesToCheck is empty. You just keep calling the same method over and over.
I propose the following solution:
public static int getShortestPath(List<string> nodesToCheck)
{
if (!nodesToCheck.Any())
{
return -1;
}
var childrenNodes = new List<string>();
level++;
for (int q = 0; q < nodesToCheck.Count; q++)
{
string[] options = bookFormat[Convert.ToInt32(nodesToCheck[q])-1].Split(' ');
if (options[0] == "0")
{
return level;
}
else
{
for (int t = 1; t < options.Length; t++)
{
if (!alreadyChecked.Contains(options[t]))
{
childrenNodes.Add(options[t]);
alreadyChecked.Add(nodesToCheck[q]);
}
}
}
nodesToCheck.Clear();
}
return getShortestPath(childrenNodes);
}
When nodesToCheck is empty, return -1 (i.e. no path).
Create a new List<string> for childrenNodes within the getShortestPath method.
While this should fix your problem, I would recommend making your entire method self-contained. It's essentially a stateless method, but you're maintaining state outside the method, which led to the problem you have seen, and could lead to more problems if you call this method in a multi-threaded environment.
The other odd thing I noticed, is that you're looping through nodesToCheck, but the way your code is written means that you will only ever consider the first node because you clear nodesToCheck at the end of the first iteration, leaving the list empty. Further more, you're adding nodesToCheck[q] to alreadChecked once per item in options, which I'm sure can't be right.
I recommend learning to use the debugger in Visual Studio. The debugger allows you to step through your code line-by-line, inspect variables, etc. - this will help you locate problems in your code.
P.S. While it is not the correct solution to your problem, if you wish to copy a list you can use LINQ's ToList() method: var listB = listA.ToList();

How can I add objects Cbook to my class CBooks without using lists

Cbooks has an atribute "CTeam[] Teams" and it is of fixed size (8). If I want to add objects to it using this in the Main:
CBook A1 = new CBook("Title1", "Author1");
CBook A2 = new CBook("Title1", "Author2");
CBooks ArrayOfBooks = new CBooks(8);
ArrayOfBooks.Add(A1);
ArrayOfBooks.Add(A2);
then position 0 and 1 are ocuppied, and the positions from 2 to 7 are null. What I want to do is, using a variable "int aux=0", count the ocupied positions like this:
for (int k = 0; k < NumberOfTeams; k++)
{
if (Teams[k].Name=="")
Aux += 1;
}
So, Aux in this case would be 2, then I want to do "Teams[Aux] = A" so that A would be in the position 2 and now I should have three objects in my array. But I'm getting "Index out of bound"
Your implementation then should look similar to this:
public class Program
{
public static void Main(string[] args)
{
Element a = new Element("A");
Element b = new Element("B");
MyArray array = new MyArray(8);
array.Add(a);
array.Add(b);
Console.WriteLine(array.Count()); //2 Elements are in the array
}
}
//Sample element class.
public class Element{
public readonly String MyString;
public Element(String myString){
MyString = myString;
}
}
//Sample array class.
public class MyArray{
private readonly Element[] myArray;
private int count; //Use a property here
public MyArray(int size){
//Be careful -> check if size is >= 0.
myArray = new Element[size];
}
public bool Add(Element element){
if(myArray.Length == count) // return false if no more elements fit.
return false;
myArray[count] = element;
count++;
return true;
}
public int Count(){
return count;
}
}
So there is no need for creating an extra count loop. Your "count" variable in "MyArray" class holds always the correct value.
Anyway the implementation or use case of this code is a little bit clunky.
Why are you cant use directly a more safe list or something. That would be a better solution.
What do you need CBooks for? From what I understand, it's just an array of 8 CBook objects so why not use CBook[]?
CBook A1 = new CBook("Title1", "Author1");
CBook A2 = new CBook("Title1", "Author2");
CBooks[] ArrayOfBooks = new CBook[8];
ArrayOfBooks[0] = A1;
ArrayOfBooks[1] = A2;
int aux = 0;
for (int k = 0; k < ArrayOfBooks.Length; k++)
{
//break the loop because we know there are no more books
if (ArrayOfBooks[k] == null)
break;
aux++;
}
The question doesn't cover what the variables NumberOfTeams and Teams are for but could those be added to the implementation of CBook?

C#: My Sorting Method/ Printing class does not print the first entry

I have implemented my own selection sort method that seems to be doing it's job for the most part; However, when I am printing files to an excel sheet the printer does not print the first item. I am unsure whether or not the sort method is the source of the problem. My test method for my sort method passes, which is why I am doubting that that is the source. My sort method is shown below. Does it have an error in the scope or order or operations? When I manually move through it on paper everything sorts properly.
public bool sortMaterial()
{
for (int i = 0; i < salesList.Count - 2; i++)
{
Sales curr = salesList[i];
Sales temp;
Sales min = curr;
int swap = 0;
for (int j = i + 1; j < salesList.Count; j++ )
{
temp = salesList[j];
if (String.Compare(temp.material, min.material) == -1)
{
min = temp;
swap = j;
}
}
salesList[i] = min;
salesList[swap] = curr;
}
return true;
}
A neat way to do custom sorting is by implementing the IComparer<T> interface:
public class SalesMaterialComparer : IComparer<Sales> {
public int Compare(Sales x, Sales y) {
return String.Compare(x.material, y.material);
}
}
You can pass your custom comparer to the LINQ OrderBy() method.
IEnumerable<Sales> salesList;
var myComparer = new SalesMaterialComparer();
var sorted = salesList.OrderBy(s => s, myComparer);

Splitting array of objects and then process it in batches

What would be a good way to call the Execute method in batches of rulesObjs? Lets say the list have more than 10,000 objects and I want to call Execute with no more than 500 at a time.
public static List<object> ExecutePolicy()
{
Policy policy = new Policy();
List<object> rules = GetRules();
object[] rulesObjs = rules.ToArray();
// Call this method with array of object, but in batches.
policy.Execute(rulesObjs);
return rulesObjs.ToList();
}
private static List<object> GetRules()
{
// get the rules via some process
return new List<object>();
}
}
public sealed class Policy
{
public void Execute(params object[] rules)
{
// Process rules...
}
}
I do not have control over Execute() method.
List<object> rules = GetRules();
int batchSize = 500;
int currentBatch = 0;
while (currentBatch * batchSize < rules.Count)
{
object[] nextBatch = rules.Skip(currentBatch * batchSize)
.Take(batchSize).ToArray();
//use batch
currentBatch++;
}
Well, if you have control over the Execute() method, the best way to do it would be to pass an index to that method so that it knows at which index of the array to start at.
public void Execute(int startIndex, /*optional*/ int endIndex, params object[] rules)
{
// Process rules...
}
Don't worry about passing too much data at once. Behind the scenes, your array is just a pointer, so you're only passing a reference anyways.
If you don't have control over the Execute() method, then you can make a new array for your section, using Array.Copy, and process that new array.
With a reference to System.Linq you can use skip and take:
int total = 10000;
int chunkSize = 500;
for (int i = 0; i < total; i += chunkSize )
{
var chunk = rulesObjs.Skip(i).Take(chunkSize).ToArray();
policy.Execute(chunk);
}

Mutithreading in C# queries

I am new to multithreading in C# . I have a 3D array of size (x)(y)(z) and say i want to calculate the average of all the z samples for every (x,y) values. I wish to do that using multithreading (say 2 threads) where i will send half the array of size (x/2)*y*z for processing to thread1 and the other half to thread2.
How to do it? How do I pass and retrieve arguments from individual threads? A code example will be helpful.
Regards
I would recommend using PLINQ for this instead of threading this yourself.
It will let you run your query using LINQ syntax, but parallelize it (across all of your cores) automatically.
There are many reasons why it makes sense to use something PLINQ (as mentioned by Reed) or Parallel.For as implementing a low-overhead scheduler for distributing jobs over several cpus is a bit challenging.
So if I understood you correctly maybe this could get you started (on my 4 core machine the parallel version is 3 times faster than the single core version):
using System;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
class Program
{
static void AverageOfZ (
double[] input,
double[] result,
int x,
int y,
int z
)
{
Debug.Assert(input.Length == x*y*z);
Debug.Assert(result.Length == x*y);
//Replace Parallel with Sequential to compare with non-parallel loop
//Sequential.For(
Parallel.For(
0,
x*y,
i =>
{
var begin = i*z;
var end = begin + z;
var sum = 0.0;
for (var iter = begin; iter < end; ++iter)
{
sum += input[iter];
}
result[i] = sum/z;
});
}
static void Main(string[] args)
{
const int X = 64;
const int Y = 64;
const int Z = 64;
const int Repetitions = 40000;
var random = new Random(19740531);
var samples = Enumerable.Range(0, X*Y*Z).Select(x => random.NextDouble()).ToArray();
var result = new double[X*Y];
var then = DateTime.Now;
for (var iter = 0; iter < Repetitions; ++iter)
{
AverageOfZ(samples, result, X, Y, Z);
}
var diff = DateTime.Now - then;
Console.WriteLine(
"{0} samples processed {1} times in {2} seconds",
samples.Length,
Repetitions,
diff.TotalSeconds
);
}
}
static class Sequential
{
public static void For(int from, int to, Action<int> action)
{
for (var iter = from; iter < to; ++iter)
{
action(iter);
}
}
}
PS. When going for concurrent performance its important to consider how the different cores access memory as its very easy to get disappointing performance otherwise.
Dot Net 3.5 and onward introduced many shortcut keywords that abstract away the complexity of things like Parallel for multi threading or Async for Async IO. Unfortunately this also provides no opportunity for understanding whats involved in these tasks. For example a colleague of mine was recently trying to use Async for a login method which returned an authentication token.
Here is the full blown multi threaded sample code for your scenario. to make it more real the sample code pretends that:
X is Longitude
Y is Lattitude
and Z is Rainfall Samples at the coordinates
The sample code also follows the Unit of Work design pattern where Rainfall Samples at each coordinate becomes a work item. It also creates discrete foreground threads instead of using a background threadpool.
Due to the simplicity of the work item and short compute time involved I've split the thread synchronization locks into two locks. one for the work queue and one for the output data.
Note: I have not used any Dot net shortcuts such as Lync so this code should run on Dot Net 2.0 as well.
In real world app development something like whats below would only be needed in complex scenarios such as stream processing of a continuous stream of work items in which case you would also need to implement output data buffers cleared regularly as the threads would effectively run forever.
public static class MultiThreadSumRainFall
{
const int LongitudeSize = 64;
const int LattitudeSize = 64;
const int RainFallSamplesSize = 64;
const int SampleMinValue = 0;
const int SampleMaxValue = 1000;
const int ThreadCount = 4;
public static void SumRainfallAndOutputValues()
{
int[][][] SampleData;
SampleData = GenerateSampleRainfallData();
for (int Longitude = 0; Longitude < LongitudeSize; Longitude++)
{
for (int Lattitude = 0; Lattitude < LattitudeSize; Lattitude++)
{
QueueWork(new WorkItem(Longitude, Lattitude, SampleData[Longitude][Lattitude]));
}
}
System.Threading.ThreadStart WorkThreadStart;
System.Threading.Thread WorkThread;
List<System.Threading.Thread> RunningThreads;
WorkThreadStart = new System.Threading.ThreadStart(ParallelSum);
int NumThreads;
NumThreads = ThreadCount;
if (ThreadCount < 1)
{
NumThreads = 1;
}
else if (NumThreads > (Environment.ProcessorCount + 1))
{
NumThreads = Environment.ProcessorCount + 1;
}
OutputData = new int[LongitudeSize, LattitudeSize];
RunningThreads = new List<System.Threading.Thread>();
for (int I = 0; I < NumThreads; I++)
{
WorkThread = new System.Threading.Thread(WorkThreadStart);
WorkThread.Start();
RunningThreads.Add(WorkThread);
}
bool AllThreadsComplete;
AllThreadsComplete = false;
while (!AllThreadsComplete)
{
System.Threading.Thread.Sleep(100);
AllThreadsComplete = true;
foreach (System.Threading.Thread WorkerThread in RunningThreads)
{
if (WorkerThread.IsAlive)
{
AllThreadsComplete = false;
}
}
}
for (int Longitude = 0; Longitude < LongitudeSize; Longitude++)
{
for (int Lattitude = 0; Lattitude < LattitudeSize; Lattitude++)
{
Console.Write(string.Concat(OutputData[Longitude, Lattitude], #" "));
}
Console.WriteLine();
}
}
private class WorkItem
{
public WorkItem(int _Longitude, int _Lattitude, int[] _RainFallSamples)
{
Longitude = _Longitude;
Lattitude = _Lattitude;
RainFallSamples = _RainFallSamples;
}
public int Longitude { get; set; }
public int Lattitude { get; set; }
public int[] RainFallSamples { get; set; }
}
public static int[][][] GenerateSampleRainfallData()
{
int[][][] Result;
Random Rnd;
Rnd = new Random();
Result = new int[LongitudeSize][][];
for(int Longitude = 0; Longitude < LongitudeSize; Longitude++)
{
Result[Longitude] = new int[LattitudeSize][];
for (int Lattidude = 0; Lattidude < LattitudeSize; Lattidude++)
{
Result[Longitude][Lattidude] = new int[RainFallSamplesSize];
for (int Sample = 0; Sample < RainFallSamplesSize; Sample++)
{
Result[Longitude][Lattidude][Sample] = Rnd.Next(SampleMinValue, SampleMaxValue);
}
}
}
return Result;
}
private static object SyncRootWorkQueue = new object();
private static Queue<WorkItem> WorkQueue = new Queue<WorkItem>();
private static void QueueWork(WorkItem SamplesWorkItem)
{
lock(SyncRootWorkQueue)
{
WorkQueue.Enqueue(SamplesWorkItem);
}
}
private static WorkItem DeQueueWork()
{
WorkItem Samples;
Samples = null;
lock (SyncRootWorkQueue)
{
if (WorkQueue.Count > 0)
{
Samples = WorkQueue.Dequeue();
}
}
return Samples;
}
private static int QueueSize()
{
lock(SyncRootWorkQueue)
{
return WorkQueue.Count;
}
}
private static object SyncRootOutputData = new object();
private static int[,] OutputData;
private static void SetOutputData(int Longitude, int Lattitude, int SumSamples)
{
lock(SyncRootOutputData)
{
OutputData[Longitude, Lattitude] = SumSamples;
}
}
private static void ParallelSum()
{
WorkItem SamplesWorkItem;
int SummedResult;
SamplesWorkItem = DeQueueWork();
while (SamplesWorkItem != null)
{
SummedResult = 0;
foreach (int SampleValue in SamplesWorkItem.RainFallSamples)
{
SummedResult += SampleValue;
}
SetOutputData(SamplesWorkItem.Longitude, SamplesWorkItem.Lattitude, SummedResult);
SamplesWorkItem = DeQueueWork();
}
}
}

Categories

Resources