shell sort pseudocode to C++ code - c++

# Sort an array a[0...n-1].
gaps = [701, 301, 132, 57, 23, 10, 4, 1]
foreach (gap in gaps)
# Do an insertion sort for each gap size.
for (i = gap; i < n; i += 1)
temp = a[i]
for (j = i; j >= gap and a[j - gap] > temp; j -= gap)
a[j] = a[j - gap]
a[j] = temp
this is the pseudocode in Wikipedia page.
I'm not sure about that if my c++ code is correct according to it. Here is my code:
void shellSort(int *array, int array_size)
{
int e, i, j, temp;
for(e = 0; e < array_size; e++)
{
for( i = e; i < array_size; i++)
{
temp = array[i];
for( j = i; j >= e && array[j - e] > temp; j -= e)
{
array[j] = array[j-e];
}
array[j] = array[temp];
}
}
}
And here is my test code:
int main()
{
int sizes[9] = {9,3,5,7,1,0,6,2,4};
int size = 0;
shellSort(sizes,size);
for(int i=0;i<size;i++)
{
cout << sizes[i] << endl;
}
return 0;
}
but it shows nothing on the screen.

Okay, let's take this from the top
void shellSort(int *array, int array_size)
{
Your code completely omitted the needed gaps array
const int gaps[] = {701, 301, 132, 57, 23, 10, 4, 1};
int e, i, j, temp;
The outer loop needs to be across gaps rather than 0 to array_size
for(e = 0; e < sizeof(gaps)/sizeof(int); ++e)
{
int gap = gaps[e];
You need to use the gap from the gaps array in the inner loop
for( i = gap; i < array_size; ++i)
{
temp = array[i];
for( j = i; j >= gap && array[j - gap] > temp; j -= gap)
{
array[j] = array[j-gap];
}
You need to store temp back into the array
array[j] = temp;
}
}
}
NB: I don't have a compiler to hand right now, so I haven't checked that, but I think it's right.
Also, a few minor points, this:
int e, i, j, temp;
is bad practice, instead declare each variable as you use it, i.e. do this instead:
for( int i = gap; i < array_size; ++i)
{
int temp = array[i];

For some reason (no comments were given), my first answer was deleted (typo - you set size to 0, not 9). The question wondered why "it shows nothing on the screen". If you set size to 0, what do you expect a for loop to do when it iterates from 0 to < size???
Before looking at the algorithm, your parameters must be correct. Start there. If SOMETHING now gets dumped to the screen, NOW you can start debugging the algorithm (if the output was wrong). If the output is right, then your algorithm is probably okay.
If I am wrong about this, PLEASE POST A COMMENT TO MY ANSWER. Don't just "delete" it!?!

Related

Sorting Selection larger number to the right not completing

I am creating a sort selecting that puts the max number to the right. I think i have it mostly done and when i execute the code it works but it does not sort the first two numbers in order from smallest to largest.
When I compile I get 2,1,4,7,9,12,99
int n = 7;
int list[] = { 9, 2, 99, 4, 1, 12, 7};
int maxIndex = n - 1;
for (int i = 0; i < maxIndex-1; i++)
{
int maxNum = i;
for (int j = i+1; j < n; j++)
{
if (list[j] > list[maxNum])
{
maxNum = j;
}
int temp = list[j];
list[j] = list[maxNum];
list[maxNum] = temp;
}
}
Im not too sure if its the for function or it has to do with the swap that i have but i dont think its the swap or else the it wouldn't order the other numbers.
So there are a few problems. The first is that your loop limit is incorrect
for (int i = 0; i < maxIndex-1; i++)
should be
for (int i = 0; i < n-1; i++)
You can get rid of the maxIndex variable.
Second your swap is in the wrong place and you swap the wrong elements. You are supposed to swap the maximum value with the current value, so the swap should go after the j loop and not inside it. It's only after the j loop completes that you know what the maximum value is. Plus what you swap is list[i] (the current value) with list[maxNum] (the maximum value). Like this
int maxNum = i;
for (int j = i+1; j < n; j++)
{
if (list[j] > list[maxNum])
{
maxNum = j;
}
}
int temp = list[i];
list[i] = list[maxNum];
list[maxNum] = temp;
Incidentally I don't like the variable name maxNum because it is not a number it's an index. Maybe maxNumIndex would be a better name?

Array gives correct output for this mergesort function but vector is giving incorrect output. What is going wrong?

I've been trying to do the count inversions question using mergesort for the past 2-3 days and after much trying, I just picked up the answer from Hackerrank's editorial, now their code is using an Array, and if I use a Vector instead of an Array, the answer is Actual answer + 1 (or different to say the least haven't tried it on many cases). I was wondering what might be the reason for it.
I also have another question on explanation of this code, in particular the variable declarations and their use in the mergei function. I understand the rest of the code conceptually, but because of this part, I have some confusion.
int ni = ((i+j)/2) + 1, nj = j + 1;
int s = i;
int* arr = new int [j - i + 1];
j = ni; int k = 0;
Code:
void mergei(int a[], int i, int j) {
int ni = ((i+j)/2) + 1, nj = j + 1;
int s = i;
int* arr = new int [j - i + 1];
j = ni; int k = 0;
while(i < ni && j < nj) {
if(a[i] <= a[j]) {
arr[k++] = a[i++];
} else {
arr[k++] = a[j++];
ans += (ni-i);
}
}
for(; i < ni; i++, k++) arr[k] = a[i];
for(; j < nj; j++, k++) arr[k] = a[j];
for(k = 0; s < nj; s++, k++) a[s] = arr[k];
delete [] arr;
}
void m_sort(int a[], int i, int j) {
if(i < j) {
m_sort(a, i, (i+j)/2);
m_sort(a, ((i+j)/2) + 1, j);
mergei(a, i, j);
}
}
int main() {
// vector<int> a = {2, 1, 3, 1, 2};
int a[] = {2, 1, 3, 1, 2};
// int n = a.size();
int n = sizeof(a)/sizeof(a[0]);
m_sort(a, 0, n - 1);
cout << ans << endl;
return 0;
}
I was not passing the Vector by reference, something I didn't have to worry about in case of array.

Selection sort, number of actions

I need to get number of comparison actions and number of copying actions. It should be about ~4. By this formula, but I'm getting it about ~2 (my n is 2, so it should be 2^2=4). What's wrong?
void selection(double A[], int N)
{
int i, j, min, tmp;
for (i = 1; i < N; i++)
{
min = i;
for (j = i + 1; j < N; j++)
if (A[j] < A[min]) {
noofcomparison++;
min = j;
}
if (min != i)
{
noofcomparison++;
tmp = A[i];
A[i] = A[min];
A[min] = tmp;
noofcopying += 3;
}
}
}
}
Full code: https://repl.it/repls/WobblyMountainousDegus
You are doing noofcomparison++ inside if statement. Your code doesn't increment noofcomparison when comparison results false. You need to move noofcomparison++ outside of if statements.

memory issue in using partially initialized array(in 0/1 knapsack)

Given n items with size Ai and value Vi, and a backpack with size m. What's the maximum value can you put into the backpack?
Have you met this question in a real interview? Yes
Example
Given 4 items with size [2, 3, 5, 7] and value [1, 5, 2, 4], and a backpack with size 10. The maximum value is 9.
Note
You cannot divide item into small pieces and the total size of items you choose should smaller or equal to m.
int knapsack(int m, vector<int> A, vector<int> V) {
int dp[m + 1], tmp[m + 1];
for (int n = 1; n <= m; n++) {
//******the problem would disappear if i change n to start with 0
dp[n] = (n < A[0]) ? 0 : V[0] ;
tmp[n] = dp[n];
}
for (int i = 1; i < A.size(); i++) {
for (int n = 1; n <= m; n++) {
tmp[n] = dp[n];
}
for (int j = 1; j <= m; j++) {
if (j >= A[i]) {
dp[j] = max(tmp[j], (V[i] + tmp[j - A[i]]));
}
}
}
return dp[m];
}
I am failing the specific testcase and all other are fine(even larger m values)
m = 10, A = [2,3,5,7], V = [1,5,2,4]
Output: 563858905 (actually random every time) Expected: 9
I know this question is some what trivial but I'm really curious about the memory allocation process in this scenario
I'm guessing that it would be dangerous to use any array that is not initialized at the first memory location, can someone confirm with me?
I tried following code, a simpler version of yours;
#include <iostream>
using namespace std;
int knapsack(int m, int A[], int V[], int size) {
int dp[m+1], tmp[m+1];
for (int n = 1; n <= m; n++) { //*1*
dp[n] = (n < A[0]) ? 0 : V[0] ;
tmp[n] = dp[n];
}
for (int i = 1; i < 4; i++) { //*2*
for (int n = 1; n <= m; n++) { //*3*
tmp[n] = dp[n];
}
for (int j = 1; j <= m; j++) { //*4*
if (j >= A[i]) {
dp[j] = (tmp[j]> (V[i] + tmp[j - A[i]])? //*5*
tmp[j] :
(V[i] + tmp[j - A[i]])
);
}
}
}
cout << "answer:" << dp[m] << endl;
return dp[m];
}
int main(){
int a[] = {2,3,5,7};
int b[] = {1,5,2,4};
knapsack(10, a, b, 4);
return 0;
}
and got 8 as the answer, rather than a random number.
I'm not sure that my code is the correct version of yours, but I luckily noticed that the expression of V[i] + tmp[j-A[i]] at the line marked by "\\*5" accesses tmp[0] when j=2 and i=1, since A[1] == 2 and 2 >= A[1]. Thus it would not be safe without initialization of tmp[0] in this logic.
So, I guess you are right; the uninitialized value of tmp[0] may change the result value, (and in some cases the flow of the logic as well, at the conditional statement of line //*5.)

SIGSEGV(signal 11) 'segmentation fault' in FCTRL2 codechef

I am facing SIGSEGV error on submitting solution for codechef small factorial problem code FCTRL2 though the code works fine on ideone
coding language C++ 4.3.2
Example
Sample input:
4
1
2
5
3
Sample output:
1
2
120
6
#include <iostream>
using namespace std;
void fact(int n) {
int m = 1, a[200];
for (int j = 0; j < 200; j++) {
a[j] = 0;
}
a[0] = 1;
for (int i = 1; i <= n; i++) {
int temp = 0;
for (int j = 0; j < m; j++) {
a[j] = (a[j] * i) + temp;
temp = a[j] / 10;
a[j] %= 10;
if (temp > 0) {
m++;
}
}
}
if (a[m - 1] == 0) {
m -= 1;
}
for (int l = m - 1; l >= 0; l--) {
cout << a[l];
}
}
int main() {
int i;
cin >> i;
while (i--) {
int n;
cin >> n;
fact(n);
cout << endl;
}
return 0;
}
Caveat I'm not going to just fix up your code for you straight up, but I will highlight where it's going wrong and why you get the seg fault.
Your problem is with your implementation of how you're trying to handle the digit by digit multiplication - specifically with what happens to your m value. Test it out by outputting m each time it's incremented - you'll find it's incrementing more often than you intend. You're right to realise you need to use an approach to get to 158 digits and your basic concept could be made to work.
The first clue is by testing with n = 6 when you get a leading 0 that you shouldn't even though you try to get rid of that problem with the if block that contains m-=1
Try with n = 25 and you will see a lot of leading zeros.
Any value greater than this will fail with a Segmentation error. The Seg fault is because, with this error, you try to set values of the array a beyond the max index (as m gets greater than 200)
N.B. Your assertion that the code works on Ideone.com is only true up to a point - it will fail with n > 25.
(Erased code computing a factorial using int)
The problem in your code is that you increment m each time temp is not 0 for each digit multiplication. You may then get a SIGSEGV when computing big factorials because m becomes too big. You probably saw it because 0 shows up in front of your result. I guess this is why you added the
if (a[m - 1] == 0) {
m -= 1;
}
You should only increment m when the inside loop is finished and term is not null. Once fixed you can get rid of the above code.
void fact(int n) {
int m = 1, a[200];
for (int j = 0; j < 200; j++) {
a[j] = 0;
}
a[0] = 1;
for (int i = 1; i <= n; i++) {
int temp = 0;
for (int j = 0; j < m; j++) {
a[j] = (a[j] * i) + temp;
temp = a[j] / 10;
a[j] %= 10;
}
// if (temp > 0) {
// a[m++] = temp;
// }
while (temp > 0)
{
a[m++] = temp%10;
temp /= 10;
}
}
for (int l = m - 1; l >= 0; l--) {
cout << a[l];
}
}