Insertion Sort from T Cormen Book - c++

I am working through the "Introduction to Algorithms" book by Cormen, and I have created the following from pseudocode. However, the first two elements of the Array do not seem to be sorted. I cannot spot the error (possibly because its late). So I was wondering if anybody could see from first glance.
#include <iostream>
#include <stdlib.h>
using namespace std;
int main(){
int input;
cout << "Enter length of desired array." << "\n";
cin >> input;
cout << "\n";
int A [input];
//Populate and print the Array.
for(int i=0; i<input; i++){
A[i] = rand()%99-1;
cout << A[i] << " ";
}
cout << "\n";
//Insertion sort.
for(int j=2; j<input; j++){ //Iterate through the Array.
int key = A[j]; //Store the current element into key.
int i = j-1; //Iterator for while loop.
while(i>0 && A[i]>key){ //Loop to insert A[j] into the sorted sequence.
A[i+1] = A[i]; //Move the element.
i=i-1; //New value of i.
A[i+1] = key; //Update the key
}
}
for(int i=0; i<input; i++){
cout << A[i] << " ";
}
return 0;
}

I haven't looked too carefully, but I think the book's pseudocode uses one-based indexing, and for coding in C (or most modern languages) you need to adjust it to zero-based indexing.
The principal suspect is
for(int j=2; j<input; j++)
Where you might want to start at 1 instead of 2.
The termination condition
while(i>0 && A[i]>key)
might also need to be changed to ensure you're above -1 rather than 0.
EDIT:
After a bit closer look, I'm pretty sure you do also have to adjust that while.
You should also of course review all upper limits for similar off-by-one issues.

change to for (int j = 1; ...)

Actually your code is correct but the problem in there in your for loop initialization. the pseudocode for insertion sort is :
for j ←1 to length(A)-1
key ← A[ j ]
> A[ j ] is added in the sorted sequence A[0, .. j-1]
i ← j - 1
while i >= 0 and A [ i ] > key
A[ i +1 ] ← A[ i ]
i ← i -1
A [i +1] ← key
Actually your code is not considering the first element of the array. It is just staring sorting from second element of the array that's you getting that type of result.
Just change the initialization of j to 1 and it would run correctly.

You can use this code , I have corrected your error
#include<iostream>
#include<stdlib.h>
#include<cstdlib>
using namespace std;
int main(){
int input;
cout<< "Enter length of desired array";
cin>>input;
cout<<"\n";
int A[input];
for(int i = 0 ;i <input ; i++)
{
A[i] = rand() % 100;
cout<<A[i] << "\t";
}
cout<<"\n";
for(int j =1; j<input ; j++)
{ int i;
int key = A[j];
i = j-1;
while( i >=0 && A[i] > key)
{
A[i+1] = A[i];
i = i-1;
A[i+1] = key;
}
}
for(int i = 0 ;i <input ; i++)
{
cout<<A[i] << "\t";
}
}

Take a look at the CLRS insertion sort algorithm translated in java.
int a[] = {5,2,4,3,1};
int key;
int i;
for(int j = 0; j < 5; j++)
{
key = a[j];
i = j - 1;
while(i>=0 && a[i]>key)
{
a[i+1]= a[i];
i--;
}
a[i+1] = key;
System.out.println("i in for loop "+i);
for(int k=0; k<a.length;k++)
{
System.out.print(a[k]+" ");
}
}

Book's pseudocode uses one-based indexing, and for coding in C (or most modern languages) you need to adjust it to zero-based indexing.
Make the following changes and it will work:
for(int i=1; i<input+1; i++){
A[i] = rand()%99-1;
cout << A[i] << " ";
}
for(int j=2; j<input+1; j++){ //Iterate through the Array.
int key = A[j]; //Store the current element into key.
int i = j-1; //Iterator for while loop.
while(i>0 && A[i]>key){ //Loop to insert A[j] into the sorted sequence.
A[i+1] = A[i]; //Move the element.
i=i-1; //New value of i.
A[i+1] = key; //Update the key
}
}
for(int i=1; i<input+1; i++){
cout << A[i] << " ";
}

here's the answer, read the explanation by Don Roby first.
start j = 1 and while loop should have i >= 0

Related

Push to vector only one element, without repeating

I have a code where i should introduce 3 numbers and an multi-dimensional array. I should print all numbers from array that are divisors with 3 numbers from start..
Here's my code:
#include <vector>
#include <iostream>
using namespace std;
int main() {
int r, p, k, nr, n, m, counter=0, temp;
vector <int> numbers;
cout << "Enter value of r, p, k: ";
cin >> r >> p >> k;
cout << "Enter the number of rows and columns: ";
cin >> n >> m;
int T[n][m];
cout << "Enter values: ";
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) {
cin >> T[i][j];
}
}
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) {
for(int a = 0; a < 1; a++) {
numbers.push_back(T[i][j]);
counter++;
}
}
}
for(int f = 0; f < counter; f++) {
if(r%numbers[f]==0 && p%numbers[f]==0 && k%numbers[f]==0) {
cout << numbers[f] << ' ';
}
}
return 0;
}
So, my question is.. how to push in vector numbers that repeats only 1 time.. I mean if in array are 2 the same number, dont print both of them but just one of them.
Thanks in advance.
Use a set: http://en.cppreference.com/w/cpp/container/set
A set does not allow duplicates. For example, if you insert the number 5 more than once, there will still only be one 5 in the set.
First #include<set>.
Then replace vector <int> numbers; with set<int> numbers;
Then replace
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) {
for(int a = 0; a < 1; a++) {
numbers.push_back(T[i][j]);
counter++;
}
}
}
with
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
numbers.insert(T[i][j]);
Then replace
for(int f = 0; f < counter; f++) {
if(r%numbers[f]==0 && p%numbers[f]==0 && k%numbers[f]==0) {
cout << numbers[f] << ' ';
}
}
with
for (auto i = numbers.cbegin(); i != numbers.cend(); ++i)
if(r % *i == 0 && p % *i == 0 && k % *i == 0)
cout << *i << ' ';
That should do it. You can eliminate the counter variable from the program because numbers.size() gives you the number of objects in the set. Also, your temp variable is not used, so eliminate that as well. Also, note that set is an ordered container, so printing it like this will print the numbers in ascending order.
(Also note that the length of an array such as int arr[3]; must be known at compile time to be strictly valid C++. Here 3 is a literal and so is known at compile time. Asking the user to input the length of the array means that it is not known at compile time.)
After you fill your vector, you can first sort all elements in it and than call std::unique, to remove all duplicates from it.
Try to look references for std::unique and std::sort

adding arrays using malloc in c++

i dont know whats wrong with my code but im getting same value of "sum" on the
screen..
assume that m and n are entered equal ....enter image description here
#include<stdio.h>
#include<malloc.h>
#include<iostream>
#include<stdlib.h>
using namespace std;
int main()
{
int n,m;
int *ptr1, *ptr2, *sum;
cout<<" enter the size of 1st and 2nd array : "<<endl;
cin>>n>>m;
ptr1=(int*)malloc(n*sizeof(int));
ptr2=(int*)malloc(m*sizeof(int));
sum=(int*)malloc((n)*sizeof(int));
cout<<"enter 1st array element :";
for(int i=0;i<n;i++)
{
cin>>*(ptr1+i) ;
}
cout<<"enter 2st array element :";
for(int i=0;i<m;i++)
{
cin>>*(ptr2+i);
}
for(int j=0;j<m||j<n;j++)
{
*(sum+j) = (*(ptr1) + *(ptr2)) ;
}
cout<<" the sum is "<<endl;
for(int j=0;j<m||j<n;j++)
{
cout<<*(sum+j)<<endl;
}
}
First, the reason you get the same number springs from where you form the sums.
In this loop
for (int j = 0; j<m || j<n; j++)
{
*(sum + j) = (*(ptr1)+*(ptr2));
}
you find the sum of the contents of ptr1 and ptr2 over and over which never change - this is always the first two numbers.
So, we could iterate over the arrays by indexing in j along as follows
for (int j = 0; j<m || j<n; j++)
{
*(sum + j) = (*(ptr1 + j) + *(ptr2 + j));
}
BUT what happens if m!=n? You'll walk off the end of the array.
If you change the loop to
for (int j = 0; j<m && j<n; j++)
{
*(sum + j) = (*(ptr1 + j) + *(ptr2 + j));
}
then you find the sum for pairs of numbers up to the smaller of m and n.
You will have to do likewise with the display of the results
for (int j = 0; j<m && j<n; j++)
{
cout << *(sum + j) << endl;
}
However, I believe you wanted to either display n numbers, regardless of which is bigger, or perhaps assume a 0 if there is no element. Also, I notice you have malloced and not freed - perhaps using a C++ array rather than C-style arrays is better? I'll come to that in a moment.
Let's do the C appraoch and have a 0 if we go beyond the end of an array.
This will work, but can be tidied up - comments inline about some important things
#include<stdlib.h>
#include <algorithm> //for std::max
#include <iostream>
using namespace std;
int main()
{
int n, m;
int *ptr1, *ptr2, *sum;
cout << " enter the size of 1st and 2nd array : " << endl;
cin >> n >> m;
ptr1 = (int*)malloc(n * sizeof(int));
ptr2 = (int*)malloc(m * sizeof(int));
sum = (int*)malloc((std::max(n, m)) * sizeof(int));
// ^--- sum big enough for biggest "array"
// data entry as before - omitted for brevity
for (int j = 0; j<m || j<n; j++)
{
*(sum + j) = 0;
if (j < n)
*(sum + j) += *(ptr1 + j);
if (j < m)
*(sum + j) += *(ptr2 + j);
}
cout << " the sum is " << endl;
for (int j = 0; std::max(n, m); j++)//however big it is
{
cout << *(sum + j) << endl;
}
free(ptr1); //tidy up
free(ptr2);
free(sum);
}
I know you said you wanted to use malloc and perhaps this is a practise with pointers, but consider using C++ idioms (at least you won't forget to free things you have maoolced this way).
Let's nudge your code towards using a std::vector:
First the include and the input:
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int n, m;
vector<int> data1, data2, sum;
cout << " enter the size of 1st and 2nd array : " << endl;
cin >> n >> m;
cout << "enter 1st array element :";
for (int i = 0; i<n; i++)
{
int number;
cin >> number;
data1.push_back(number); //there is a neater way, but start simple
}
cout << "enter 2st array element :";
for (int i = 0; i<m; i++)
{
int number;
cin >> number;
data2.push_back(number);
}
This post shows a way to neaten up the data entry. However, let's do something simple and get the sum:
for (int j = 0; j < std::max(m, n); j++)
{
int number = 0;
if (j < n)
number += data1[j];
if (j < m)
number += data2[j];
sum.push_back(number);
}
And now for a C++ way to do output
cout << " the sum is " << endl;
for (auto item : sum)
{
cout << item << '\n';
}
}
Finally, let's have a brief think about the sum.
If you now #include <iterator> you can use an algorithm to put your sum into sum
std::transform(data1.begin(), data1.end(),
data2.begin(), std::back_inserter(sum), std::plus<int>());
However, note this won't fill with zeros. You could either make the vectors the same size, filled with zeros first, or lookup/discover ways to zip vectors of different sizes. Or stick with ifs in a loop as I demonstrated above.
Avoid malloc in C++. Just saying.
I highly encourage you to use a modern cpp data structure like a vector for storing your data. Thus, you don't have to worry about malloc and can access them far more easyly.
But now to your question: Your summation for loop is broken. Use
for(int j=0;j<m||j<n;j++)
{
*(sum+j) = (*(ptr1+j) + *(ptr2+j)) ;
}
Best regrads, Georg

Insert Sort not working

I am learning sorting algorithms. I googled the insert sort code and when I tried it on my own it's not working out. Can someone please find the error in my code?
#include<iostream>
using namespace std;
int main()
{
int i,size, a[40], key;
cout << "Enter size: ";
cin >> size;
for(int o=0; o<size; o++)
{
cin >> a[o];
}
//insertion sort
for(int j = 1; j <= size-1; j++)
{
key = a[j];
i = j-1;
while((key < a[i]) && (i >= 0));
{
a[i + 1] = a[i];
i = i - 1;
}
a[i + 1] = key;
}
cout << "\nSorted list is as follows\n";
for(int o = 0; o < size; o++)
{
cout << endl << a[o];
}
}
while((key<a[i])&&(i>=0));
You have an infinite while loop here. The semi colon at the end means that the while loop body is empty. Hence i is never decremented and the loop runs forever.
Also, you need to check if the index is valid (i >= 0) before trying to access it's value.
So change the line as below.
while((i >= 0) && (key < a[i]))

My C++ code goes into infinite loop when array size increases

I am trying to solve the problem at: Cut the Sticks.
My code works fine when the array size <=3 but goes bonkers then the size increases to >=6
#include<iostream>
using namespace std;
int minElement(int a[]){
int min = a[0];
int k;
for (k=1; k < 6; k++){
if (a[k] < min and a[k] > 0)
min = a[k];
}
return min;
}
int main(){
int a[6];
for (int i=0; i<6; i++){
cin >> a[i];
}
int minElem, flag;
while (true){
flag = 0;
minElem = minElement(a);
for (int i = 0; i < 6; i++){
a[i] = a[i] - minElem;
}
for (int j = 0; j < 6; j++){
if (a[j] > 0){
cout<<a[j]<<endl;
flag++;
}
}
if (flag == 0)
break;
};
return 0;
}
The problem is arising in the minElement function, it seems. On print min after assignment, it shows min as empty. Similarly, inside the loop in the function, I am getting blanks for all mins. What could be the issue?
EDIT
Please try the code here: http://cpp.sh/2ti6 with the input as [5,4,4,2,2,8]. It doesn't reach zero, the code starts failing before the first iteration, when the minimum element is called as Nothing is returned from the minElement functionn
Problem is there because of this line in the code
int min = a[0];
you need to check that array element is non-zero
int minElement(int a[]){
int min = 0;
int i=0;
while(i<6) // check the array element is non -zero
{
if(a[i]>0){
min = a[i];
break;
}
i++;
}
//int min = a[0];
int k;
for (k=1; k < 6; k++){
if (a[k] < min && a[k] > 0)
min = a[k];
}
return min;
}
The problem lies in your minElement function.
In the case that a[0] happens to be zero, you'll never assign another value to min and will return zero. Out of the function you will subtract zero to the values and enter the infinite loop.
In the case that a[0] is a negative number, you'll end up subtracting a negative value (and so increase the values instead). Then a[0] will become zero and your program loops.
Initializing min with a[0] is not enough, you have to look for a valid minimum value. You could, for example, initialize it with a very large value (not a very good solution) or search the array for the first valid min value.
EDIT:
I added some prints to your code:
...
while (true){
flag = 0;
minElem = minElement(a);
std::cout << "Min: " << minElem << std::endl;
for (int i = 0; i < 6; i++){
a[i] = a[i] - minElem;
}
std::cout << "Values:";
for (int j = 0; j < 6; j++){
std::cout << " " << a[j];
if (a[j] > 0){
//cout << " " << a[j];
flag++;
}
}
std::cout << std::endl;
if (flag == 0)
break;
getchar();
}
...
Here's the output:
5 4 4 2 2 8
Min: 2
Values: 3 2 2 0 0 6
Min: 2
Values: 1 0 0 -2 -2 4
Min: 1
Values: 0 -1 -1 -3 -3 3
Min: 0
Values: 0 -1 -1 -3 -3 3
(...) Loop forever
I hope that helps you understand now what the problem is.
int minElement(int a[]); change this to int minElement(int a[], int size)
2.
int a[6];
for (int i=0; i<6; i++){
cin >> a[i];
}
change this to
int arr_size=0;
cout << "Enter the array size ";
cin >> arr_size;
int a[arr_size];
for (int i=0; i<arr_size; i++){
cin >> a[i];
}
for (int i = 0; i < 6; i++){
a[i] = a[i] - minElem;
}
You are subtracting the min of the array from each element, so at this point there is only one 0 in the array and rest are positive numbers.
for (int j = 0; j < 6; j++){
if (a[j] > 0){
cout<<a[j]<<endl;
flag++;
}
So at this point flag has to be some positive number, and in this case 5.
if (flag == 0)
break;
This condition will never hit and hence the infinite loop.
it has nothing to do with the dimension.
What happens is that if a[0] is the smallest value => it will run in an infinte loop. Why because a[0] eventually becomes 0.
Why does a[0]=0 run in an infinte loop?
What value does minElement return when a[0] is 0?
try replace int min = a[0]; qith min = (a[0]>0) ? a[0]: 1;
or adding `minElem= (minElem>0) ? minElem: 1;' after 'minElem = minElement(a);'
PS:
Looking at all the answers this seems the simplest minElement that does what you want:
int minElement(int a[]){
int min = a[0];
int k;
for (k=1; k < 6; k++){
if(min==0 && a[k]>0 )
min=a[k];
else
if (a[k] < min and a[k] > 0)
min = a[k];
}
return min;
}
the min will only be zero at iteration N if a[j]==0 for all j+1
I solve this base on the link you provide. I use vector for me to easy remove those minimum length stick.
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main(){
int noOfInput;
int input;
vector<int> myVec;
cin>>noOfInput;
for (int i=0; i<noOfInput; i++){
cin >> input;
myVec.push_back(input);
}
sort(myVec.begin(),myVec.end(),greater<int>());
while(myVec.size()>0){
int minimum = myVec[myVec.size()-1];
int lengthOfVector = myVec.size();
cout<<myVec.size()<<" ";
for(int i = lengthOfVector-1 ; i >=0 ; i--){
myVec[i]=myVec[i]-minimum;
if(myVec[i]==0){
myVec.pop_back();
}
}
}
return 0;
}

Insertion sort task

I was trying to solve a problem in which I should sort increasingly array of numbers, than take first k numbers from sorted array and eliminate those numbers that are repeating and write them on the output.
This is my code:
#include <iostream>
using namespace std;
int main()
{
int n, k;
cin >> n >> k;
int tab[n];
for (int i = 0; i < n; i++) //taking n numbers from input
{
cin >> tab[i];
}
int j, element;
for (int i = 1; i < n; i++) //i am using insertion sort
{
j = 0;
while (tab[j] < tab[i])
j++;
element = tab[i];
for(int k = i - 1; k >= j; k--)
tab[k + 1] = tab[k];
tab[j] = element;
}
for (int i = 0; i < k; i++) //writing k smallest numbers without repetitions
{
if (tab[i] == tab[i + 1])
continue;
cout << tab[i] <<"\n";
}
cin >> n;
return 0;
}
generally it works and it gives expected output, however when I am uploading this problem to check its correctness (i found this problem on polish site), it says "wrong anwser".
I cannot see any errors here, maybe you will see something which I wrote bad.
I think you misunderstood the problem. 'eliminate those numbers that are repeating' means you have to print the number once and eliminate subsequent occurrence(s) of that number. For ex.
n = 5;
k = 3;
tab[n] = 5 1 1 1 1
Here, sorted tab[] becomes '1 1 1 1 5', then expected output is '1', but your program gives nothing!
I hope this helps :)