How does Binary Insertion Sort Work? - c#

I know how binary search works, and also know how Insertion sort works but this code is about Binary Insertion Sort and i have problem in understanding how it works.
static void Main(string[] args)
{
int[] b = BinarySort(new[] { 4, 3, 7, 1, 9, 6, 2 });
foreach (var i in b)
Console.WriteLine(i);
}
public static int[] BinarySort(int[] list)
{
for (int i = 1; i < list.Length; i++)
{
int low = 0;
int high = i - 1;
int temp = list[i];
//Find
while (low <= high)
{
int mid = (low + high) / 2;
if (temp < list[mid])
high = mid - 1;
else
low = mid + 1;
}
//backward shift
for (int j = i - 1; j >= low; j--)
list[j + 1] = list[j];
list[low] = temp;
}
return list;
}
I don't understand what this part do:
//backward shift
for (int j = i - 1; j >= low; j--)
list[j + 1] = list[j];
list[low] = temp;
and what is the purpose of using binary search here?
Can you tell me how binary insertion sort works? (c# console)
code source:http://w3mentor.com/learn/asp-dot-net-c-sharp/asp-dot-net-language-basics/binary-insertion-sort-in-c-net/

Binary insertion sort works as insertion sort, but it separates locating the insertion point from the actual insertion.
Insertion sort implemented for an array will move items at the same time as locating the insertion point. While looping through the items to find the insertion point, it will also shift the items to make room for the insertion.
Binary insertion sort will make use of the fact that the items that are already sorted are sorted, so it can use a binary search to find the insertion point. As the binary search can't also shift the items to make room for the insertion, that has to be done in a separate step after the insertion point has been found.
The code that you wanted explained is the code that shifts the items to make room for the insertion.

Related

Counting sort in singly-linked list C#

Is there any way to make a counting sort in singly-linked list? I haven't seen any examples and it's quite hard to make it without them. I have example of it in array and would like to do it in singly-linked list.
Has anybody did it in singly-linked list?
public static int[] CountingSortArray(int[] array)
{
int[] aux = new int[array.Length];
// find the smallest and the largest value
int min = array[0];
int max = array[0];
for (int i = 1; i < array.Length; i++)
{
if (array[i] < min) min = array[i];
else if (array[i] > max) max = array[i];
}
int[] counts = new int[max - min + 1];
for (int i = 0; i < array.Length; i++)
{
counts[array[i] - min]++;
}
counts[0]--;
for (int i = 1; i < counts.Length; i++)
{
counts[i] = counts[i] + counts[i - 1];
}
for (int i = array.Length - 1; i >= 0; i--)
{
aux[counts[array[i] - min]--] = array[i];
}
return aux;
}
I found one that works on an array at: http://www.geeksforgeeks.org/counting-sort/
I think with minimal effort it could be changed to a linked list, the only problem is that you'll end up traversing the linked list many many times since you don't have random access eg.[] making it rather inefficient. Since you seem to have found the same thing i did before I could finish typing I think my answer is kinda pointless. However, I'm still a bit curious as to where you're having problems.
Heres a hint if figuring out where to start is the problem: Every time you see array[i] used, you will need to traverse your linked list first instead to get the i'th item first.
Edit: The only reason you would need to create a 2nd linked list of frequencies is if you needed to actually do work on the resulting linked list. If you just need a sorted list of the values inside the linked list for display purposes an array holding the frequencies would work (i suppose at the same time you could just create an array of all the values then do the counting sort you already have on it). I apologize if i have confused my c, c++, c++/cx, somewhere along the way (i don't have a compiler handy right now), but this should give you a good idea of how to do it.
public static node* FindMin(node* root){ //FindMax would be nearly identical
node* minValue = root;
while(node->Next){
if(node->Value < minValue->Value)
minValue = node;
}
return minValue;
}
public static node* CountingSortArray(node* linklist){
node* root = linkedlist
node* min = FindMin(linklist);
node* max = FindMax(linklist);
int[] counts = new int[max->Value - min->Value + 1];
while(root != NULL){
counts[root->Value] += 1;
root = root->Next;
}
int i = 0;
root = linkedlist;
while(ptr != NULL){
if(counts[i] == 0)
++i;
else{
root->Value = i;
--count[i];
root = root->Next;
}
}
}
void push(node** head, int new_data){
node* newNode = new node();
newNode->Value = new_data;
newNode->Next = (*head);
(*head) = newNode;
}
void printList(node* root){
while(root != NULL){
printf(%d ", root->Value);
root = root->Next;
}
printf("\n");
}
int main(void){
node* myLinkedList = NULL;
push(&head, 0);
push(&head, 1);
push(&head, 0);
push(&head, 2);
push(&head, 0);
push(&head, 2);
printList(myLinkedList);
CountingSortArray(myLinkedList);
printList(myLinkedList);
}
The example code is more like a radix sort with base (max-min+1). Usually a counting sort looks like the code below. Make a pass over the list to get min and max. Make a second pass to generate the counts. Make a pass over the counts to generate a new array based on the counts (instead of copying data). Example code fragment:
for (size_t i = 0; i < array.Length; i++)
counts[array[i]-min]++;
size_t i = 0;
for(size_t j = 0; j < counts.Length); j++){
for(size_t n = counts[j]; n; n--){
aux[i++] = j+min;
}
}

Finding smallest number using tournament bracket

I'm writing a program that has to find the smallest number through the tournament bracket. For example there is an array
int[] a = new int[4] {4, 2, 1, 3}
and by comparing numbers standing next to each other I've to choose the smallest one. (min(4, 2) -> 2, min(1, 3) -> 1, and then I'm comparing 1 and 2, 1 is the smallest so it's the winner, but it's not possible to compare 2 and 1. Just a[0] with a1, a[2] with a[3] and so. In general a[2*i] with a[(2*i)+1] for(int i=0; i<a.Length/2; i++) <- something like this
First question: If there are n numbers, the whole tree consists of 2n-1 brackets. Am I supposed to create an array of 4 or 7 elements? 4 seems like a better option.
Second question: if I'm comparing 4 and 2, and 2 is smaller should I make a[0] = 2, and then while comparing 1 and 3 a1 = 1? Finally comparing a[0] with a1 and putting the smallest number to a[0]? Temporary int might be needed.
Last question: what do you propose to do it in the simplest way? I could hardly find any info about this algorithm. I hope you will direct my mind into working algorithm.
Not much, but I'm posting my code:
int[] a = new int[4] { 4, 2, 1, 3 };
int tmp = 0;
for (int i = 0; i < (a.Length)/2; i++)
{
if (a[tmp] > a[tmp + 1])
{
a[i] = a[i + 1];
}
else if(a[tmp] < a[tmp +1])
{
a[i] = a[i + 1];
}
tmp = tmp + 2;
}
Can you point what I'm doing ok, and what should be improved?
If tournament style is a must, a recursive approach seems the most appropriate:
int Minimum (int [] values, int start, int end)
{
if (start == end)
return values [start];
if (end - start == 1)
if ( values [start] < values [end])
return values [start];
else
return values [end];
else
{
int middle = start + (end - start) / 2;
int min1 = Minimum (values, start, middle);
int min2 = Minimum (values, middle + 1, end);
if (min1 < min2)
return min1;
else
return min2;
}
}
EDIT: Code is untested and errors might have slipped in, since it's been typed on the Android app.
EDIT: Forgot to say how you call this method. Like so:
int min = Minimum (myArray, 0, myArray.Length -1);
EDIT: Or create another overload:
int Minimum (int [] values)
{
return Minimum (values, 0, values.Length -1);
}
And to call use just:
int min = Minimum (myArray);
EDIT: And here's non-recursive method (bare in mind that this method actually modifies the array):
int Minimum(int[] values)
{
int step = 1;
do
{
for (int i = 0; i < values.Length - step; i += step)
if(values[i] > values[i + step])
values[i] = values[i + step];
step *= 2;
}
while(step < values.Length);
return values[0];
}
There are various simple solutions that utilize functions set up in C#:
int min = myArray.Min();
//Call your array something other than 'a' that's generally difficult to figure out later
Alternatively this will loop with a foreach through all of your values.
int minint = myArray[0];
foreach (int value in myArray) {
if (value < minint) minint = value;
}
1 - What tree are you talking about? Your array has n values to start with, so it will have n values max. If you mean the number of values in all the arrays you will create is 2n-1, it still doesn't mean you need to fit all of these in 1 array, create an array, use it and then create another array. C# GC will collect Objects of a reference type that have no pointers (are not going to be used again) so it will be fine memory wise if that's your concern?
2 - Post your code. There are a few gotchas but likely you will be fine changing the current array values or creating a new array. Temp int will not be needed.
3 - The above posted algos are the "simplest" using built in functions available to C#. If this is a homework assignment, please post some code.
As a general direction, using a recursive function would likely be most elegant (and some general reading on merge sorts would prove useful to you going forward).

Sort two dimensional string array by id using insertion sort - C#

I'm new here and sorry If my question is stupid, but I really need you help.
I need to sort that two dimensional string array by id (the first column):
string [,] a = new string [,]
{
{"2","Pena","pena"},
{"1","Kon","kon"},
{"5","Sopol","sopol"},
{"4","Pastet","pastet"},
{"7","Kuche","kuche"}
};
The problem is that I'm sorting only the number and I want after them to sort the words. That's what I did so far
static void Main(string[] args)
{
string [,] a = new string [,]
{
{"2","Pena","pena"},
{"1","Kon","kon"},
{"5","Sopol","sopol"},
{"4","Pastet","pastet"},
{"7","Kuche","kuche"}
};
int b = a.GetLength(0);
Console.WriteLine(b);
Console.WriteLine(a[0,0]);
Console.WriteLine(a[0,1]);
Console.WriteLine(a[1,0]);
InsertionSort(a, b);
Console.WriteLine();
Console.Write("Sorted Array: ");
printArray(a);
Console.WriteLine();
Console.Write("Press any key to close");
Console.ReadKey();
}
public static void InsertionSort(string[,] iNumbers, int iArraySize)
{
int i, j, index;
for (i = 1; i < iArraySize; i++)
{
for (int k = 0; k < iNumbers.GetLength(1); k++)
{
index = Convert.ToInt32(iNumbers[i, 0]);
j = i;
while ((j > 0) && (Convert.ToInt32(iNumbers[j - 1, 0]) > index))
{
iNumbers[j, k] = iNumbers[j - 1, k];
j = j - 1;
}
iNumbers[j, 0] = Convert.ToString(index);
}
}
}
static void printArray(string[,] iNumbers)
{
for (int i = 0; i < iNumbers.GetLength(0); i++)
{
for (int k = 0; k < iNumbers.GetLength(1); k++)
{
Console.Write(iNumbers[i, k] + " ");
}
}
Console.WriteLine();
}
Unfortunatelly as output I get
1 Pena pena 2 Kon kon 4 Sopol sopol 5 Pastet pastet 7 Kuche kuche
I would be really grateful if you could help me.
Based on the nature of the example and the question, I am guessing that this is a homework assignment and so must be implemented in a fashion that is a) not far from your current example, and b) actually demonstrates an insertion sort.
With that in mind, the following is a corrected version of your example that works:
public static void InsertionSort(string[,] iNumbers, int iArraySize)
{
int i, j, index;
for (i = 1; i < iArraySize; i++)
{
index = Convert.ToInt32(iNumbers[i, 0]);
j = i;
while ((j > 0) && (Convert.ToInt32(iNumbers[j - 1, 0]) > index))
{
for (int k = 0; k < iNumbers.GetLength(1); k++)
{
string temp = iNumbers[j, k];
iNumbers[j, k] = iNumbers[j - 1, k];
iNumbers[j - 1, k] = temp;
}
j = j - 1;
}
}
}
I made two key changes to your original code:
I rearranged the k and j loops so that the k loop is the inner-most loop, rather than the j loop. Your j loop is the one performing the actual sort, while the k loop is what should be actually moving a row for an insertion operation.
In your original example, you had this reversed, with the result that by the time you went to sort anything except the index element of a row, everything looked sorted to the code (because it's only comparing the index element) and so nothing else got moved.
With the above example, the insertion point is determined first, and then the k loop is used simply to do the actual insertion.
I added logic to actually swap the elements. In your original code, there wasn't really a swap there. You had hard-coded the second part of a swap, simply copying the index element to the target, so the swap did work for the index element. But it wouldn't have achieved the swap for any other element; instead, you'd just have overwritten data.
With the above, a proper, traditional swap is used: one of the values to be swapped is copied to a temp local variable, the other value to be swapped is copied to the location of the first value, and then finally the saved value is copied to the location of the second.
The above should be good enough to get you back on track with your assignment. However, I will mention that you can get rid of the k loop altogether if your teacher will allow you to implement this using jagged arrays (i.e. a single-dimensional array containing several other single-dimensional arrays), or by using a second "index array" (i.e. where you swap the indexes relative to the original array, but leave the original array untouched).

Incrementing/decrementing during integer swap in quicksort implementation

I'm trying to implement a quicksort in C#. I found code closely resembling my code below on the web:
public void Sort(List<int> list, int low, int high)
{
int i = low;
int j = high;
IComparable pivot = list[(low + high) / 2];
while (i <= j)
{
while (list[i].CompareTo(pivot) < 0)
{
i++;
}
while (list[j].CompareTo(pivot) > 0)
{
j--;
}
if (i <= j)
{
int temp = list[i];
list[i++] = list[j]; // ??
list[j--] = temp; // ??
}
}
if (j > low)
{
Sort(list, low, j);
}
if (i < high)
{
Sort(list, i, high);
}
}
The code works fine but I can't understand why i and j need to be incremented and decremented when swapping the integers in list[i] and list[j].
I'm new to sorting algorithms.
I'd be very grateful for any insights..
The increment and decrement aren't done for the swap itself, but in order for the pointers to be in place so that the sort will proceed with the next pair of elements on the next iteration.
Consider the following example.
4 1 7 3 5 4 8 1 9
↑ ↑ ↑
i pivot j
The value at i is greater than pivot, and the one at j is less, making them eligible for a swap. However, once the swap is ready, it is pointless to re-compare the same two elements, since we already know that they're in the correct place. Thus, we progress i and j as part of the same operation.
4 1 1 3 5 4 8 7 9
↑ ↑ ↑
i pivot j
Edit: The operations are postfix, meaning they are done after the assignment. The following would be equivalent:
int temp = list[i];
list[i] = list[j];
i = i + 1;
list[j] = temp;
j = j + 1;

Counting sort - implementation differences

I heard about Counting Sort and wrote my version of it based on what I understood.
public void my_counting_sort(int[] arr)
{
int range = 100;
int[] count = new int[range];
for (int i = 0; i < arr.Length; i++) count[arr[i]]++;
int index = 0;
for (int i = 0; i < count.Length; i++)
{
while (count[i] != 0)
{
arr[index++] = i;
count[i]--;
}
}
}
The above code works perfectly.
However, the algorithm given in CLRS is different. Below is my implementation
public int[] counting_sort(int[] arr)
{
int k = 100;
int[] count = new int[k + 1];
for (int i = 0; i < arr.Length; i++)
count[arr[i]]++;
for (int i = 1; i <= k; i++)
count[i] = count[i] + count[i - 1];
int[] b = new int[arr.Length];
for (int i = arr.Length - 1; i >= 0; i--)
{
b[count[arr[i]]] = arr[i];
count[arr[i]]--;
}
return b;
}
I've directly translated this from pseudocode to C#. The code doesn't work and I get an IndexOutOfRange Exception.
So my questions are:
What's wrong with the second piece of code ?
What's the difference algorithm wise between my naive implementation and the one given in the book ?
The problem with your version is that it won't work if the elements have satellite data.
CLRS version would work and it's stable.
EDIT:
Here's an implementation of the CLRS version in Python, which sorts pairs (key, value) by key:
def sort(a):
B = 101
count = [0] * B
for (k, v) in a:
count[k] += 1
for i in range(1, B):
count[i] += count[i-1]
b = [None] * len(a)
for i in range(len(a) - 1, -1, -1):
(k, v) = a[i]
count[k] -= 1
b[count[k]] = a[i]
return b
>>> print sort([(3,'b'),(2,'a'),(3,'l'),(1,'s'),(1,'t'),(3,'e')])
[(1, 's'), (1, 't'), (2, 'a'), (3, 'b'), (3, 'l'), (3, 'e')]
It should be
b[count[arr[i]]-1] = arr[i];
I'll leave it to you to track down why ;-).
I don't think they perform any differently. The second just pushes the correlation of counts out of the loop so that it's simplified a bit within the final loop. That's not necessary as far as I'm concerned. Your way is just as straightforward and probably more readable. In fact (I don't know about C# since I'm a Java guy) I would expect that you could replace that inner while-loop with a library array fill; something like this:
for (int i = 0; i < count.Length; i++)
{
arrayFill(arr, index, count[i], i);
index += count[i];
}
In Java the method is java.util.Arrays.fill(...).
The problem is that you have hard-coded the length of the array that you are using to 100. The length of the array should be m + 1 where m is the maximum element on the original array. This is the first reason that you would think using counting-sort, if you have information about the elements of the array are all minor that some constant and it would work great.

Categories

Resources