I have a homework assignment of coding a bidirectional bubble sort. Can someone please see if my logic is correct with respect to it. I Don't want code as I want to figure it out myself. I just want a logic check of how i understand it.
As i understand the Bidirectional Bubble sort you implement 2 for loops one starting at position 1 in the list and performing a normal bubble sort. As the first for loop reaches the end a second one is implemented working in reverse. I just don't completely understand what the terminating conditions for each loop would be.
Would the for loop conditions be something as follows?
loop 1 - for(i = 0; i < Count -i; i++)
loop 2 - for(j = Count - i; j > i; j--)
in each loop the swap conditions would be specified.
Thanks
The "classic" bubble sort goes through the entire array on each iteration, so the loops should be
for(i = 0; i < Count - 1; i++)
and
for(j = Count - 1; j > 0; j--)
Both loops skip one index: the first loop skips the last index, while the second loop skips the initial one. This is so that your code could safely compare data[i] to data[i+1], and data[j] to data[j-1].
EDIT The "optimized" bubble sort skips the initial k elements on k-th iteration. Since your bubble sort is bidirectional, you will be able to skip the initial k and the tail k elements, like this:
int k = 0;
do { // The outer loop
...
for(int i = k; i < Count - k - 1; i++)
...
for(int j = Count - k - 1; j > k ; j--)
...
k++;
} while (<there were swaps>);
bidirectional bubble sort works like this:
instead of passing the list from bottom to top every time (bubble sort) you start one time at the bottom and every second time from the top of the list.
the wikipedia article does a way better job at explaining it:
http://en.wikipedia.org/wiki/Cocktail_sort
- rich
Related
I'm super new to c# and programming in general. I'm trying to do some exercises online to familiarize myself with the basics of the language before I start school next month.
I've written a super simple program and I just can't understand why it's doing what it's doing and I haven't been able to find an answer anywhere. Here's the code.
int i, j, rows;
Console.Write("\n\n");
Console.Write("Display the pattern like right angle triangle which repeat a number in a row:\n");
Console.Write("-------------------------------------------------------------------------------");
Console.Write("\n\n");
Console.Write("Input number of rows : ");
rows = Convert.ToInt32(Console.ReadLine());
for (i = 1; i <= rows; i++)
{
for (j = 1; j <= i; j++)
Console.Write("{0}", i);
Console.Write("\n");
}
All this program is suppose to do is a simple pyramid with the same number.
My question is that in the second for loop it writes i but then it re-evaluates j++ and j<= instead of writing \n until the end of the last run of the loop. I don't understand why? The program works but I am not understanding why. Isn't the for loop always suppose to execute everything in it unless you break it?
thanks and sorry for the very novice question but its driving me nuts!
In programming every statement have a scope block in which it run.
By default for loop have only one statement scope that just comes after it. If we wanted to run more then one statement in for loop scope then we use curly braces {} to define the code block.
in your case you need to use curly braces like this to run both statements.
for (j = 1; j <= i; j++)
{
Console.Write("{0}", i);
Console.Write("\n");
}
its best programming practices to used braces {} in all you conditional and looping constructs. It make easy to read and understand the code.
A for loop will execute everything in its scope. Without using { } the scope of a for loop is the next line after it. To execute more than one command you need to put them in curly braces like so:
for (j = 1; j <= i; j++)
{
Console.Write("{0}", i);
Console.Write("\n");
}
It's generally best practice to always have the { } for readability and to easily update the loop if needed. Though you could write your for loop like so and it would be perfectly readable.
for (i = 1; i <= rows; i++)
for (j = 1; j <= i; j++)
{
Console.Write("{0}", i);
Console.Write("\n");
}
The above code will do the same thing keeping the second for loop in the scope of the first.
As an aside, I noticed you declared your variables outside of the for loop, being new to programming you may not be aware of certain features of the for loop.
You can declare your iterator right in the for loop:
for (int i = 1; i <= rows; ++i)
In most cases it's better to declare your iterator in the for loop like this as it gives 'i' the same scope as the for loop.
Another neat feature of the for loop is that all the options between the semi-colons are actually optional. So for instance, if you declared your iterator outside the for loop you can omit it in the for loop:
int i = 1;
for (; i<= rows; ++i)
You can omit any part or all of it even:
for (;;) // a perfectly valid for loop that will loop forever.
You can even have multiple iterators:
for (int i = 0, j = 0; i < 5; ++i, ++j)
Your expectation that in every iteration of inner for loop both Console.Write statements will get executed is wrong:
for (j = 1; j <= i; j++)
Console.Write("{0}", i); //inner for loop scope starts and ends on this statement
There is no curly brace after inner for loop. So, by default ONLY first statement encountered after for statement will be treated under the scope of inner for loop.
Outer for loop has a curly brace as shown below:
for (i = 1; i <= rows; i++)
{//outer for loop scope starts here
for (j = 1; j <= i; j++)
Console.Write("{0}", i);
Console.Write("\n");
}//outer for loop scope ends here
So in every iteration of outer for loop the whole inner for loop and the Console.Write("\n"); will execute.
As a general practice, if you have only one statement to execute inside your for loop then you indent it with a tab as depicted in your code snippet as well.
I have a loop which in theory should loop 40000 times but exits and doesn't continue with code after the loop, just after one iteration. I figured that I wasnt being a silly willy about the for-loops since it didn't continue after the loops at all, so that might be something with restrictions for Lists? Or mayby something about the VS-debugger that isn't working preperly? (probably not tho...)
Edit: Thanks for pointing out that the last layer was pointless. I edited the code, but the problem persists.
Edit2: To clarify, the code does not result in an exception, or breaks. It just stops without any notifications, and shows the form(since I do a windows forms application). Just... it just don't want to continue and skips the rest of the code.
for (int i = 0; i < hiddenLayerDepth - 1; i++)
{
Connectors.Add(new List<List<List<List<Connector>>>>());
for (int j = 0; j < playfieldSize; j++)
{
Connectors[i].Add(new List<List<List<Connector>>>());
for (int k = 0; k < playfieldSize; k++)
{
Connectors[i][j].Add(new List<List<Connector>>());
for (int l = 0; l < playfieldSize; l++)
{
Connectors[i][j][k][l].Add(new Connector());
}
}
}
}
hiddenLayerDepth is set to 5 when entering the loop, and playfieldSize is set to 10. It enters the innermost loop and executes the code inside, then it just stops without increasing m.
Missing
Connectors[i][j][k].Add(new List<List<Connector>>());
If you know the sizes you should just create and array up front
Well, I tried to add a 'Connector' where there were no list. The List that contained the lists that would countain the Connectors was not added.
Next in my series of Big O questions that I can't find the answer to
Take the following example
for(int i = 0; i < someNumber; i++)
{
for(int j = i; j < someNumber; j++)
{
DoSomething();
}
}
Would this still be considered O(n^2)? I only ask because I feel that this has to be less that O(n^2), since the inner loop is executing less and less for every iteration of i (since j is starting closer and closer to someNumber).
Thanks
The outer loop runs n times. The inner loop starts out running n times, but decreases with each iteration of the outer loop, until the last iteration where it only runs once. The code inside the inner loop will run
n + (n−1) + ... + 2 + 1
times.
That can be simplified to n(n + 1)/2 (proof), or n2/2 + n/2, or finally (n2 + n) / 2. Since the first term is n2, the algorithm is in O(n2).
I wrote code to implement a bidirectional selection sort in parallel. I used c#, and the the parallel.invoke function. 2 loops were invoked in parallel, one to find the minimum, and one to find the max. Yet, it doesn't sort. I was wondering is the problem because this type of sort can't handle being done in parallel, since each loop relies on data existing in the other loop?...or is there simply something wrong with my code?
Parallel.Invoke(
() =>
{
for (int i=0; i < array.Length / 2; i++)
{
int m;
int min = i;
for (m = i + 1; m < array.Length - 1; m++)
if (array[m] < array[min])
min = m;
//swap
int temp = array[min];
array[min] = array[m];
array[m] = temp;
}
},
() =>
{
for (int m = 0; m < array.Length / 2; m++)
{
int length = array.Length - 1;
int max = length - m;
int k;
for (k = length--; k > 0; k--)
if (array[k] > array[max])
max = k;
//swap
int temp = array[max];
array[max] = array[k];
array[k] = temp;
}
});
I think it's easier if you search the minimum and maximum within the same loop in 1 thread: (java-code, but I assume you'll understand the principle)
int minimum, maximum;
int k = size();
for(int i = 0; i < size(); ++i)
{
--k;
minimum = i;
maximum = k;
if(k - i <= 0)
break;
for(int j = i; j <= k; ++j)
{
if(greaterThan(minimum, j))
minimum = j;
if(lessThan(maximum, j))
maximum = j;
}
if(minimum != i)
{
swap(minimum, i);
if(maximum == i)
maximum = minimum;
}
if(maximum != k)
swap(maximum, k);
}
The problem with your code is this:
Say this is the array:
[5, 4, 3, 2, 1]
Iteration 0: The first thread will find the smallest element to put on index 0
The first thread finds the minimum element at index 4
Iteration 0: The second thread will find the largest element to put on index 4
The second thread finds the maximum element at index 0
You will already see that this will not end well, as both threads will perform a swap between index 0 and 4 resulting in the same situation as it is now.
Another problem is if your first thread is looping from m -> array.length - 1. If at the same time thread 2 moves the minimum element (which it doesn't need, because it's searching the maximum) from index k to "max" via a swap. With index "max" being < "m". That means the first thread will never find the next minimum value because it was moved before its position.
EDIT: After consideration, I don't think it's possible to implement a straightforward parallel version of selection sort. The version I first recommended was indeed not going to work due to the algorithm finding the same minimum every time because it didn't change the input-array.
What is possible is to only perform selection sort with thread 1 on the first half of the array (and only allow it to find the minimum in that half) and the second half of the array is for the second thread. And then in the end you can merge both halfs with a mergesort-algorithm.
This way you can always use more than 2 threads; say "p" amount of threads for example. Each responsible for N/p part of the input array with "N" being the inputsize. And in the end you just merge every part with a mergesort-algorithm. I never implemented it myself, so I can't say if it would be efficient, but I assume there will be better algorithms to parallelize out there (like mergesort itself).
PS: About the code posted above. I assume everything seems rather straightforward except this part:
if(maximum == i)
maximum = minimum;
That's to deal with a situation like this:
. . . i . . . k
[1, 4, 3, 1, 5]
so with i = 1 and k = 3 (the indices).
The algorithm will find:
maximum = index 1
minimum = index 3
After swapping the minimum value with the one on index i, the situation changes like this:
. . . i . . . k
[1, 1, 3, 4, 5]
Meaning the maximum value (integer 4) actually moved from index "i" to index "minimum". If we would perform a swap(maximum, k), it would have a bad result. That's why we need to update the index of the maximum element if it was positioned at index i.
I'm loping datatable with 100 to 10000 rows, comparing each row to each other through doyble loop.
for (int i = 0; i < DT1.Rows.Count; i++)
{
for (int j = 0; j < DT1.Rows.Count; j++)
{
//some code to compare data
}
}
For 100-200 rows it's done in few minutes, which is OK, but comparing few thousands rows to few thousands, takes hours and isn't finished.
What can I do to speed it up? Best I thought up is to use lists of objects, instead of datatables.
Any other sugestions?
Can thread be used to do this?
Thanks.
I recently came across a similar scenario that I had to work through. Though in my case, I was comparing a pair of excel files. For my trial run, after getting it working, I had 530 rows on one side and 459000 on the other inside nested loop. This is roughly 234 million iterations. My program was able to work through it in roughly 30 seconds. I used a foreach in this scenario:
foreach (DataRow r1 in DT1.Rows) //Loop the First Source data
{
foreach (DataRow r2 in DT2.Rows) //Loop the Second Source data
{
//Comparison code here...
}
}
Edit: In your loop, as a point of reference, you are causing 3 variables to be tracked at each iteration of the loops, first and second are your counters. The third is the major performance hit, DT1.Rows.Count. By using the Direct row count as a part of the loops, it must be re-evaluated at each iteration. This adds unneeded time to the program. If you absolutely require that there be the counters, then assign the Row count out first:
int DT1Count = DT1.Rows.Count;
for (int i = 0; i < DT1Count; i++)
{
for (int j = 0; j < DT1Count; j++)
{
//some code to compare data
}
}
This way, the row count is static and shall remove the extra processing needed to evaluate the row count at each iteration.
Although you can certainly optimize your search by using hash tables, the best optimization is to let the database engine to the search for you. RDBMS engines are optimized for this kind of task - no client-side optimization should be able to beat it. Your biggest disadvantage is having to pull the data from the database into your program. This is very slow. The database engine has all the data right there - this is a huge advantage.
For example, if you are looking for rows representing users with identical first and last name, a simple query with a self-join will get you results in seconds, not minutes, because the data never leaves the engine.
select u1.userId, u2.userId
from User u1
join User u2 on u1.FirstName=u2.FirstName and u1.LastName=u2.LastName
Assuming that FirstName and LastName columns are indexed, this query will find you duplicates very quickly.
If the results are sorted in some sort of order you can put the results into an array and loop through using a Binary Search
for (int i = 0; i < DT1.Rows.Count; i++)
{
for (int j = i+1; j < DT1.Rows.Count; j++) //<-- starts from next row
{
//some code to compare data
}
}
you could also count on .NET internals to do better job than manual looping using:
DataTable.Select(filterExpression, sortExpression)
The biggest optimization to be made here is the following:
Currently, you are comparing each value twice. For example, in the first iteration of the loop, you are comparing the first row with itself, because both loops start at index 0.
The simplest fix to this would be to change the inner loop to this:
for (int j = i + 1; j < DT1.Rows.Count; j++)
This will dramatically reduce the number of comparisons. Your algorithm currently needs n^2 comparisons. The proposed fix reduces this number to less than the half. With the fix you only need (n^2 - n) / 2 comparisons.