Bubble sort tiny error - c++

I'm trying to make my program sort this array of numbers from least to greatest but the output is coming out otherwise. In other words, I'm trying to not use a[4] because that's what this algorithm is doing but I can't figure out how. Thanks for reading.
Output:
9 12 3 14
#include <iostream>
using namespace std;
int main() {
int a[4] = {12, 9, 14, 3};
int temp;
for(int i = 0; i < 4; i++) {
if(a[i] > a[i + 1]) {
temp = a[i];
a[i] = a[i + 1];
a[i + 1] = temp;
}
cout << a[i] << " ";
}
return 0;
}

You have three errors:
Error 1: An out-of-bounds access during the loop.
This:
for(int i = 0; i < 4; i++)
should be
for(int i = 0; i < 3; i++)
The reason being is that if you use the first (wrong) version, you have a buffer overrun:
if(a[i] > a[i + 1]) // if i == 3, a[3+1] == a[4] == out-of-bounds
Error 2: Writing the output while sorting.
You're doing this:
cout << a[i] << " ";
in the middle of the sort. It makes no sense to print out the values of the array if the sort has not been completed.
This should be placed outside the sorting code (once the sorting has completed):
for ( int i = 0; i < 4; ++i)
cout << a[i] << " ";
Error 3: Incorrect implementation of bubble sort.
A bubble sort works by making multiple passes through the data until it is detected that the data is sorted. Your code only makes one pass through the data and then exits.
What you need to do is have a while or similar loop that has within it, the for loop. The while loop only gets executed if the data requires at least one more pass through the data. You will know when the data is sorted if the if condition in the for loop never executes (meaning no swaps occurred, thus the data is sorted).
Here is an example:
int temp;
bool is_sorted = false;
while ( !is_sorted ) // execute while data is not sorted
{
isSorted = true; // assume data is sorted
for(int i = 0; i < 3; i++)
{
if(a[i] > a[i + 1])
{
//.. swap the items
//...
isSorted = false; // swap made, so data was not sorted
}
}
}

There is already a header file called "algorithm" with which you can do that:
#include <iostream>
#include <algorithm>
using namespace std;
typedef pair<char, int> new_pair;
struct sorting{
bool operator() (int i, int j){return i < j;}
}test_sort;
int main(void){
int test[4] = {5, 2, 1, 10};
sort(test, test + 3, test_sort);
for(int i = 0; i <= 3; i++){
cout <<test[i] << endl;
}
return 0;
}
I wish I helped you.

Related

Trying to make a simple Array sorter with input numbers

I'm very new to C++ or even coding. I was trying to make a simple array sorter, where the I first input the number of elements that will be in the array and then input the elements. My outcome should be the array sorted in ascending order. I have not thought about the case if elements inserted are same. So I would love to get some help from you folks.
The main error that I'm facing is that only the first unsorted element is sorted while the rest are either interchanged or left the same.
int main(){
int x;
cout<<"Enter no. of elements"<<endl;
cin>>x;
int A[x];
for (int i = 0;i<x;i++){
cin>>A[i];
}
for(int i=0;i<x;i++)
cout<<A[i]<<",";
int count=0;
if(count <= (x-1)){
for (int i=0;i<(x-1);i++){
if(A[i]>A[i+1]){
int a;
a = A[i];
A[i] = A[(i+1)];
A[i+1] = a;
}
else if(A[i]<A[i+1])
count++;
}
}
cout<<"Sorted array:";
for(int i=0;i<x;i++)
cout<<A[i]<<",";
return 0;
}
You declared a variable length array
int x;
cout<<"Enter no. of elements"<<endl;
cin>>x;
int A[x];
because its size is not a compile-time constant.
However variable length arrays are not a standard C++ feature though some compilers have their own language extensions that support variable length arrays,
It is better to use the class template std::vector.
Another problem is that it seems you are trying to use the bubble sort method to sort the array. But this method requires two loops.
Here is a demonstration program that shows how the bubble sort algorithm can be implemented.
#include <iostream>
int main()
{
int a[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
const size_t N = sizeof( a ) / sizeof( *a );
for (const auto &item : a)
{
std::cout << item << ' ';
}
std::cout << '\n';
for (size_t last = N, sorted = N; not ( last < 2 ); last = sorted)
{
for (size_t i = sorted = 1; i < last; i++)
{
if (a[i] < a[i - 1])
{
// std::swap( a[i-1], a[i] );
int tmp = a[i - 1];
a[i - 1] = a[i];
a[i] = tmp;
sorted = i;
}
}
}
for (const auto &item : a)
{
std::cout << item << ' ';
}
std::cout << '\n';
}
The program output is
9 8 7 6 5 4 3 2 1 0
0 1 2 3 4 5 6 7 8 9
Let us try the following method:
find the largest element in the array and move it to the end, by swapping with the last element;
repeat with the array but the last element, and so on.
To find the largest element in A[0..m-1], scan the array and keep an index to the largest so far, let l. This index can be initialized to 0.
// Move the largest to the end
int l= 0;
for (int i= 1; i < m; i++)
{
if (A[i] > A[l]) l= i;
}
// A[l] is the largest in A[0..m-1]
Swap(A[l], A[m-1]);
// A[m-1] is the largest in A[0..m-1]
To sort, repeat with decreasing m. You can stop when the subarray just holds one element:
// Sort
for (int m= n-1; m > 1; m--)
{
// Move the largest to the end
....
}
Writing the Swap operation and assembling the whole code is your task. Also check
correctness of the Move for the limit cases m= 0, 1, 2.
correctness of the Sort for the limit cases n= 1, 2, 3.
how you could instrument the code to verify that the Move does its job.
how you could instrument the code to verify that the Sort does its job.
what happens in case of equal keys.
Your code can be fixed a bit to make it working.
Just replace if (count <= (x - 1)) with while (count < (x - 1)) and also set count = 0; at start of loop, plus replace else if (A[i] < A[i + 1]) with just else. And your code becomes working!
Necessary fixes I did in code below. Also I did formatting (indents and spaces) to make code looks nicer. Rest remains same.
As I see you have a kind of Bubble Sort.
Try it online!
#include <iostream>
using namespace std;
int main() {
int x;
cout << "Enter no. of elements" << endl;
cin >> x;
int A[x];
for (int i = 0; i < x; i++) {
cin >> A[i];
}
for (int i = 0; i < x; i++)
cout << A[i] << ",";
int count = 0;
while (count < (x - 1)) {
count = 0;
for (int i = 0; i < (x - 1); i++) {
if (A[i] > A[i + 1]) {
int a;
a = A[i];
A[i] = A[(i + 1)];
A[i + 1] = a;
} else
count++;
}
}
cout << "Sorted array:";
for (int i = 0; i < x; i++)
cout << A[i] << ",";
return 0;
}
Input:
10
7 3 5 9 1 8 6 0 2 4
Output:
7,3,5,9,1,8,6,0,2,4,Sorted array:0,1,2,3,4,5,6,7,8,9,
If you are taking the size of array as input from user you have to create your array dynamically in c++ like
int *array=new int(x)
and after taking the inputs of the elements just run a nested loop from 0 to size and
the inner loop from 0 to size-1 and check if(A[i]>A[i+1]) if true then swap the values else continue

Print the array value which can produce the input by using addition operator

How do I edit the given program to get all possible combinations of array values which will provide the given data using addition operator?
The following code works fine only if there is only one combination. For example, in the array = {1,2,3,4,5}, the given value = 6; the only possibility is the sum of 2 and 4. Thus the output desired is array [1] & array[3]. Attached coding works fine for this. But for array ={1, 3, 3, 4, 2}, there is two possibilities but the code returns nothing...
#include<iostream>
using namespace std;
int main() {
int n = 5; int m = 0;
int givendata;
int a[n];
for (int i = 0; i < n; i++) {
cin >> a[i];
}
cin >> givendata;
if (m < n) {
for (int i = 0; i < n; i++) {
int sum = a[n - i] + a[m];
if (sum == givendata) {
cout << m << " " << n - i;
}
}
}
m = m + 1;
return 0;
}
You need to use a double loop to compare all the values:
// start at 0, the first position of the array. Loop until the 2nd to last element
for (int i=0; i<n-1;i++)
{
// start this index at one higher than i. Since a+b == b+a, there's no need to
// add the later values in the array with the previous ones, we've already
// done that
for (int j=i+1; j<n; j++)
{
int sum = a[i]+a[j];
if (sum == givendata)
{
std::cout << a[i] << " + " << a[j] << " = " << givendata << std::endl;
}
}
}
Demonstration
Also see Why is "using namespace std;" considered bad practice?

Unexpected Value While using Bubble Sort in C++

When using the bubble sort method to sort my array from smallest to largest its outputting an unexpected value of: -858993460.
Within the debugger i'm being prompted with "Stack around variable 'numb was corrupted'.
I'm currently using Visual studios to run the code.
I have also ran the same code within a new project with no results.
#include <iostream>
int main()
{
int length = 6;
int temp = 0;
int end = 6;
int numb[] = { 6, 5, 4, 3, 2, 1 };
for (int counter = length - 1; counter > 0; counter--)
{
for (int i = 0; i < end; i++)
{
if (numb[i] > numb[i + 1])
{
temp = numb[i + 1];
numb[i + 1] = numb[i];
numb[i] = temp;
}
}
for (int i = 0; i <= 5; i++)
{
std::cout << numb[i] << " ";
}
std::cout << "\n";
end--;
}
system("pause");
}
In you inner for loop where int i = 0; i < end; i++, you need to set the condition to be i < end - 1. This is because you are already going to be at the end of the array with i + 1 when swapping the indexes around.

Duplicate numbers in an array [duplicate]

This question already has answers here:
Deleting duplicates in the array
(2 answers)
Closed 8 years ago.
I need to write a program where I have to print the numbers which occur twice or more than twice in the array. To make things simpler, I am working on a sorted array.
Here is my code.
#include <stdio.h>
int main()
{
int n,i;
int a[10]={2,2,2,4,6,6,9,10,10,11};
printf("%d\n",a[10]);
for(i=0;i<10;++i)
{
if(a[i]==a[i+1] && a[i]!=a[i-1])
printf("%d ",a[i]);
else
continue;
}
return 0;
}
The code seems to work fine but I do not like my code because at some point, the loop compares the value of a[0] with a[-1] and a[9] with a[10] and both of these, a[-1] and a[10], are garbage values. I am sure there are better ways to do it but I am unable to think of any.
Also, I need to extend the above program to count the frequency of duplicate numbers.
Help is appreciated. Thanks!
First, you can't access a[10] in your printf line, this is outside your array.
This should work fine.
#include <stdio.h>
int main()
{
int n,i;
int a[10]={2,2,2,4,6,6,9,10,10,11};
for(i=0; i < 9; ++i)
{
if(a[i] == a[i+1])
if(i > 0 && a[i] == a[i-1])
continue;
else
printf("%d ",a[i]);
}
return 0;
}
Edit: Or you can use the shorter yet harder to read:
for(i=0; i < 9; ++i)
{
if(a[i] == a[i+1] && (!i || a[i] != a[i-1]))
printf("%d ",a[i]);
}
See code below for the solution, which will print only the duplicate numbers from the array and how many times they occur.
I added the int c which is used for your count. It is initially set to 1, and increased by 1 for each duplicate number.
#include <stdio.h>
using namespace std;
int main() {
int n,i,c;
int a[10]={2,2,2,4,6,6,9,10,10,11};
c = 1;
for(i=0; i < 9; ++i)
{
if (a[i] == a[i+1]) {
n = a[i];
c += 1;
} else {
if (c > 1) {
printf("Number: %d, Occurences: %d \n",n,c);
c = 1;
}
}
}
return 0;
}
Since the array is already sorted, it'd be easier to do something like this, with another loop inside the for loop.
int duplicateCount = 1; // Must be at least one instance of a value in the array
for(int i = 0; i < 9; ++i) {
int j = i;
while(j != 9 && a[j] == a[j + 1]) {
++j;
++duplicateCount;
}
i = j; // j is now at end of list of duplicates, so put i at the end as well,
// to be incremented to the next unique value at end of for loop iteration
printf("%d: %d\n", a[j], duplicateCount);
duplicateCount = 1; // Reset for next values
}
If you want to count the frequency of all the numbers, you can easily turn duplicateCount into an array of values to count the frequency of each unique value. For a better solution, you could use another data structure, such as a map.
You are really going to need to have two indexes that walk through your array.
Here's a start:
int i = 0;
int j;
while (i < 10) {
for (j = i+1; j < 10; ++j) if (a[i] != a[j]) break;
if (j !+ i+i) printf("%d\n", a[i]);
i = j;
}
You could use a functor, overload operator() and return a set (unique values). Assuming your array is sorted it's just a matter of comparing the previous one with the next and inserting it in the set if they equal. If they are not sorted then you have to go through the whole array for every entry. Below are two examples with output as an explanation.
#include <set>
using namespace std;
Unsorted array:
struct UnsortedArrayDuplicateEntries {
set<int> operator()(int* array, int size) {
set<int> duplicates;
for (int i = 0; i < size - 1; i++)
for (int j = i + 1;j < size; j++)
if (array[i] == array[j])
duplicates.insert(array[j]);
return duplicates;
}
};
Sorted array:
struct SortedArrayDuplicateEntries {
set<int> operator()(int* array, int size) {
set<int> duplicates;
for (int i = 0; i < size - 1; i++)
if (array[i] == array[i+1])
duplicates.insert(array[j]);
return duplicates;
}
};
Test sorted:
SortedArrayDuplicateEntries d;
int sorted[10]={2,2,2,4,6,6,9,10,10,11};
set<int> resultSorted = d(sorted,10);
for (int i : resultSorted) cout << i << endl;
Output sorted:
2
6
10
Test unsorted:
UnsortedArrayDuplicateEntries d;
int unsorted[10]={2,6,4,2,10,2,9,6,10,11};
set<int> resultUnsorted = d(unsorted,10);
for (int i : resultUnsorted) cout << i << endl;
Output unsorted:
2
6
10
I hope it helps!
#include <stdio.h>
int main(){
int i, a[10]={2,2,2,4,6,6,9,10,10,11};
int size = 10;
for(i=0;i<size;++i){
int tmp = a[i];
int c = 1;
while(++i < size && tmp == a[i])
++c;
if(c > 1)
printf("%d times %d\n", tmp, c);
--i;
}
return 0;
}

copy one array to another without duplicates C++

The problem is that, I have an array of 10 integers, having some duplicates. The task is to copy this array to another array of same size, but without duplicate values. That is, read one element from array1, compare it with all the elements in array2, if it's already in array2, just skip it or print that it's already in array2, go to second element of array1, and repeat the process.
Now, I've tried this but don't know where's the problem:
#include <iostream>
using namespace std;
int main()
{
int temp;
int array1[] = {10,2,5,4,10,5,6,9,8,10};
int array2[11] = {0};
for(int i = 1; i <= 10; i++)
{
temp = array1[i-1];
for(int j = 1; j <= 10; j++)
{
if(temp == array2[j])
{
cout << "Duplicate " << temp << endl;
i++;
break;
}
}
array2[i] = array1[i-1];
}
for(int k = 1; k <= 10; k++)
cout << array2[k] << " " << endl;
system("pause");
}
array1 has 10 elements and array2 has 11, so right away the requirements haven't been met. Presumably, having 11 elements was a workaround for using incorrect index values in the for loops; the index should run from 0 to 9, not from 1 to 10.
When you add an element to the second array, you should only check it value against the elements that have already been added, not against the values in the entire array.
Finally, there's an underspecification. Once you've eliminated duplicates, you have fewer than 10 elements; array2 has 10 elements; what values should the extra elements have?
std::unique_copy is your friend:
http://en.cppreference.com/w/cpp/algorithm/unique_copy
remember to sort the source array first
In C++, break immediately ends one loop structure, and starts execution immediately after it. Thus, the line array2[i] = array1[i-1]; executes redardless of whether the inner for loop finds a duplicate. One solution is to set a variable indicating that the value is a duplicate:
int main() {
int temp;
bool isDuplicate; //added this line
int array1[] = {10,2,5,4,10,5,6,9,8,10};
int array2[11] = {0};
for(int i = 1; i <= 10; i++)
{
temp = array1[i-1];
isDuplicate=false;//added this line
for(int j = 1; j <= 10; j++)
{
if(temp == array2[j])
{
cout << "Duplicate " << temp << endl;
i++;
isDuplicate=true; //added this line
break;
}
}
if(!isDuplicate) //added this line
array2[i] = array1[i-1];
}
for(int k = 1; k <= 10; k++)
cout << array2[k] << " " << endl; system("pause"); }
Alternatively (though many programmers would disagree with this practice) you could use a goto statement instead of a break statement:
int main()
{
int temp;
int array1[] = {10,2,5,4,10,5,6,9,8,10};
int array2[11] = {0};
for(int i = 1; i <= 10; i++)
{
temp = array1[i-1];
for(int j = 1; j <= 10; j++)
{
if(temp == array2[j])
{
cout << "Duplicate " << temp << endl;
i++;
goto duplicate; //added this line
}
}
array2[i] = array1[i-1];
//added next line
duplicate:
}
for(int k = 1; k <= 10; k++)
cout << array2[k] << " " << endl;
system("pause");
}
You could use a std::set to ensure uniqueness for you.
http://en.cppreference.com/w/cpp/container/set
You have three approaches:
compare each element one by one (O(N^2) performance)
sort your reference array and use a binary search to determine if the element exists (O(N*lnN) performance)
create a lookup hash (O(1) performance)
I can see two main sources of problems in your code: 1) the break statement, as it is, does not solve the problem of differentiating between the case when duplicate is found, and when the element in array1 should be added to array2. 2) There is no counter which would store the number of elements inserted so far into array2, this way they could not be copied to array2 next to each other. The code which fixes both is:
#include <iostream>
using namespace std;
int main()
{
int array1[] = {10,2,5,4,10,5,6,9,8,10};
int array2[10];
int array2_elements_inserted = 0;
for(int i = 0; i < 10; i++)
{
int temp = array1[i];
bool isDuplicate = false;
for(int j = 0; j < array2_elements_inserted; j++)
{
if(temp == array2[j])
{
cout << "Duplicate " << temp << endl;
isDuplicate = true;
break;
}
}
if (!isDuplicate)
{
array2[array2_elements_inserted] = temp;
++array2_elements_inserted;
}
}
for(int k = 0; k < array2_elements_inserted; k++)
cout << array2[k] << " " << endl;
// system("pause");
}
Output:
10
2
5
4
6
9
8
First of all, use dynamic containers. Especially have a look at those provide by
the standard library, e.g. std::vector. Second, you should use a set data structure
to keep track of the elements you have seen before, e.g., std::set.
Then it's just an iteration on the input array and appending new elements to the
output array.
Here's an example:
#include <vector>
#include <set>
#include <iostream>
int main() {
// define and print input data
std::vector<int> v1 = {10,2,5,4,10,5,6,9,8,10};
for (int i : v1)
std::cout << i << " ";
std::cout << "\n";
// this will soon contain the output data
std::vector<int> v2;
// a set to keep track of the already seen elements
std::set<int> set;
// iterate the input array using range-based for loop
for (int i : v1) {
// check for duplicates
if (set.find(i) == set.end()) {
// first occurrence, insert to set, append to output data
set.insert(i);
v2.push_back(i);
}
else {
// seen before, do nothing
}
}
// print output data
for (int i : v2)
std::cout << i << " ";
std::cout << "\n";
}
The output:
$ g++ test.cc -std=c++11 && ./a.out
10 2 5 4 10 5 6 9 8 10
10 2 5 4 6 9 8
For reference:
http://en.cppreference.com/w/cpp/container/vector
http://en.cppreference.com/w/cpp/language/range-for
http://en.cppreference.com/w/cpp/container/set
http://en.cppreference.com/w/cpp/container/set/find