I was just practising a little bit and tried to sort an array with the bubble sort algorithm.
Compiler didn't give me any warnings nor errors and it worked well! First you type 10 times a number and then the program sorts them + prints them.
Code:
#include <iostream>
using namespace std;
void arr_sort(int* array, const int arr_size){
int temp = 0; //Temporary integer to store (if necessary) the current element
int end = 0; //Run time condition
while(end++ != arr_size){ // Will loop max. 10 times
for(int i = 0; i < arr_size; i++){
if(array[i] > array[i + 1]){ //If the current element
temp = array[i]; //is bigger than the next
array[i] = array[i + 1];//Change the positions
array[i + 1] = temp;
}
}
}
}
int main(){
int arr_input[10];
for(int i = 0; i < 10;i++) //The user has to type 10 numbers
cin >> arr_input[i]; //which will be stored in this array
arr_sort(arr_input, 10); //sorts the array
cout << endl << endl;
for(int i = 0; i < 10; i++) //Print out the array!
cout << arr_input[i] << ", ";
cout << endl;
return 0;
}
My only problem is the while-loop in the arr_sort function. I mean it sorts the array until end has the same value as arr_size. But often it doesn't need that long. My question now... How can I improve this function? How can I test if the array is completely sorted so the while-loop can stop without running another time and another time ...?
Before your for loop, assume it's sorted:
bool sorted = true;
In your if statement`, record that it's not sorted:
sorted = false;
After your for loop`, return if there was no evidence that it's not sorted:
if ( sorted ) return;
Just outside of the for loop, place a bool and set it to false. Inside the swap block, set the bool to true. After the for loop, check the value of the boolean, and if it's still false, no swaps were made so the array is sorted, so break out of the while loop.
while(end++ != arr_size){ // Will loop max. 10 times
bool swapped = false;
for(int i = 0; i < arr_size; i++){
if(array[i] > array[i + 1]){ //If the current element
temp = array[i]; //is bigger than the next
array[i] = array[i + 1];//Change the positions
array[i + 1] = temp;
swapped = true;
}
}
if (!swapped) break;
}
Related
c++
When printing to console, if function execution is sequential it would seem logical the ordered array would be printed after calling insertionSort, however order list does not print until next loop. Any help would be appreciated.
#include <stdio.h>
#include <iostream>
#include <array>
using namespace std;
void insertionSort(int* array, int size) {
for (int i = 1; i < size; i++) {
int key = i - 1;
while (i > 0 && array[key] > array[i] ) {
int tmp = array[i];
array[i] = array[key];
array[key] = tmp;
i -= 1;
key -= 1;
}
}
}
const int ARRAY_MAXSIZE = 5;
int main(void) {
int *array = (int*)calloc(ARRAY_MAXSIZE, sizeof(int));
int input;
cout << "Enter 5 digits\n";
for (int size=0; size < ARRAY_MAXSIZE; size++) {
cout << size << " index ";
cin >> input;
array[size] = input;
insertionSort(array, size);
for (int j=0; j <= size; j++) {
cout << array[j];
}
cout << '\n';
}
}
Console Entry
This is a classic off-by-one error. Your insertionSort expects you to pass the number of elements to sort via the parameter size. But your main loop is always holding a value that is one less than the size immediately after adding an element.
I want to say that bugs like this are easily discovered by stepping through your program's execution with a debugger. If you don't know how to use a debugger, start learning now. It is one of the most important tools used by developers.
Anyway, the quick fix is to change your function call to:
insertionSort(array, size + 1);
However, as Paul McKenzie pointed out in comments, it's a bit crazy to do this every time you add a new element because your function sorts an entire unsorted array. Your array is always nearly sorted except for the last element. You only need to call that function once after your input loop is done:
// Read unsorted data
for (int size = 0; size < ARRAY_MAXSIZE; size++) {
cout << size << " index ";
cin >> input;
array[size] = input;
}
// Sort everything
insertionSort(array, ARRAY_MAXSIZE);
// Output
for (int j = 0; j < ARRAY_MAXSIZE; j++) {
cout << array[j];
}
cout << '\n';
But if you want every insertion to result in a sorted array, you can "slide" each new value into place after inserting it. It's similar to a single iteration of your insertion-sort:
// Sort the last element into the correct position
for (int i = size; i >= 1 && array[i] > array[i - 1]; i--)
{
std::swap(array[i], array[i - 1]);
}
Even better, you don't need to swap all those values. You simply read the value, then shuffle the array contents over to make room, then stick it in the right spot:
// Read next value
cin >> input;
// Shuffle elements to make room for new value
int newPos = size;
while (newPos > 0 && array[newPos - 1] > input) {
array[newPos] - array[newPos - 1];
newPos--;
}
// Add the new value
array[newPos] = input;
I have a program I am writing that prints out a Fibonacci Sequence up to 30 numbers. I must do this by traversing the array using pointers, but I don't know how to.
There is not a lot of easy to follow information that I can understand.
When I see the code for c++ answers to this, all I see is this...
I'm a noob and I am having a hard time looking at all of the 'std::' conventions when I have to look at code. I know it's probably good convention, but I am not good with it yet. So I would like a straightforward example, assuming I am using the using namespace std; line of code within my project.
I have tried setting the for..loop up with the pointer variable but I am not sure how to do this.
void fibonacciSequence(){
//initialize the array and users input
const int ARRAY_SIZE = 30;
int numbers[ARRAY_SIZE];
int *pointer;
pointer = numbers;
//Traverse the array and generate the Fibonacci Sequence
for(int i = 0; i < ARRAY_SIZE; i++){
//Set first element to 0
if(i == 0){
numbers[i] = 0;
}
//Set second element to 1
else if (i == 1){
numbers[i] = 1;
}
//Start calculating the sequence after the first 2 elements
//have been established.
else{
numbers[i] = numbers[(i - 1)] + numbers[(i - 2)];
}
}
// Output the Fibonacci Sequence after calculations.
for(int i = 0; i < ARRAY_SIZE; i++){
cout << numbers[i] << endl;
}
}
This code I have works perfectly. But instead of traversing the array using 'i' in the for...loop, i need to use 'pointer.'
It's actually very simple change this
for(int i = 0; i < ARRAY_SIZE; i++){
cout << numbers[i] << endl;
}
to this
for(int* p = numbers; p < numbers + ARRAY_SIZE; p++){
cout << *p << endl;
}
Explanation
int* p = numbers - set p to point to the beginning of the array
p < numbers + ARRAY_SIZE - check p hasn't reached the end of the array
p++ - move p on to the next element of the array
*p - access the element that p is pointing to
Similar changes to your first loop.
This whole topic is pointer arithmetic, maybe you could do some research.
This probably isn't a good project for learning pointers, since indexing is the most natural way of computing a fibanocci sequence. But here goes. Replace that generator loop with this:
int *current = numbers;
*current++ = 0;
*current++ = 1;
while (current != numbers + ARRAY_SIZE) {
*current = *(current - 1) + *(current - 2);
++current;
}
And then for the output:
for (current = numbers; current != numbers + ARRAY_SIZE; ++current)
std::cout << *current << '\n';
I'm trying to use a bubble sort to sort an array of 10 numbers. The program asks for 10 numbers from the user then outputs the unsorted array. This part works fine. It then runs a bubble sort and outputs the sorted array. In my tests I only entered positive integers, however the first value in the sorted array is always a really small number expressed like "2.6812368e-317" or something similar. The rest of the values in the array then appear after that number sorted as they should be. After the sorted array displays Windows then comes up with an error saying the program has stopped working.
My code is as follows:
int main(int argc, char** argv) {
double arrSort[10];// declare array to store numbers to be sorted
cout << "Please enter 10 numbers to be sorted" << endl;
// ask for values from user and input them in array
for (int i = 0; i < 10; i++)
{
cin >> arrSort[i];
}
// display unsorted array
cout << "Unsorted Array: " << endl;
for (int i = 0; i < 10; i++)
{
if (i < 9)
cout << arrSort[i] << ", ";
else
cout << arrSort[i] << endl;
}
bool changed = true; // variable to store whether a change has been made
double temp; // variable to temporarily store a value while swapping
//start looping the array
do
{
changed = false; // change to false so that if no changes are made to array the loop exits
for (int i = 0; i < 10; i++) // start loop within array to check values
{
if (arrSort[i] > arrSort[i + 1]) // check if current index is greater than next index
{
// swap values
temp = arrSort[i]; // store current index in temp variable
arrSort[i] = arrSort[i + 1]; // assign next index to current index
arrSort[i + 1] = temp; // assign temp value to next index
changed = true; // set changed to true to run another loop
}
}
}while (changed); // if array was changed loop through again, if not changed exit loop
// output results of sorted array
cout << "Sorted Array: " << endl;
for (int i = 0; i < 10; i++)
{
if (i < 9)
cout << arrSort[i] << ", ";
else
cout << arrSort[i] << endl;
}
return 0;
}
Here is a screenshot of a test run of the program:
Sorted Array output
for (int i = 0; i < 10; i++) // <-- here's problem.
{
if (arrSort[i] > arrSort[i + 1])
{
// swap values
}
}
i variable should be less than 9 not 10. As you can see in if statement you are checking arrSort[i + 1], so in last element you are checking number which is out of your table range (arrSort[10] doesn't exist). I'm not able to check it right now, but I guess it's the problem.
I think the problem is here:
if (arrSort[i] > arrSort[i + 1])
When
i=9
Your array have 10 elements and you try to compare
arrSort[9] > arrSort[9+1]
And
arrSort[10]
Does not exist
Hi everyone I need to write merge sort in C++ using a given header for mergeSort();
I have the partitioning correct but at a point where its merging an array that was merged before it has 0's. For example: If I have [34][21] i get [21, 34] but when this is merged with let's say [8] it gives [0, 0, 8]. I am losing values. Please help me debug it.
Note: I have some moveCount to count data moves and compCount to count computations. Please don't get confused with those.
int * merge(int * left ,int szLeft ,int * right,int szRight, int &compCount, int &moveCount){
int * newArr = new int [szLeft+szRight];
cout << "Left: ";
for (int i = 0; i < szLeft; ++i){
cout << left[i] << " ";
}
cout << endl;
cout << "Right: ";
for (int i = 0; i < szRight; ++i){
cout << right[i] << " ";
}
cout << endl;
int bigArrIndex = 0, rightArrIndex = 0,leftArrIndex = 0;
while(leftArrIndex < szLeft && rightArrIndex < szRight){
compCount++;
if(right[rightArrIndex] <= left[leftArrIndex]){
newArr[bigArrIndex] = right[rightArrIndex];
rightArrIndex++;
compCount++;
}
else{
newArr[bigArrIndex] = left[leftArrIndex];
leftArrIndex++;
}
moveCount++;
bigArrIndex++;
}
//1 more computation done even if the loop is not executed
compCount++;
//copy the rest of the stuff if left
while(rightArrIndex < szRight){
moveCount++;
compCount++;
newArr[bigArrIndex] = right[rightArrIndex];
rightArrIndex++;
bigArrIndex++;
}
//1 more computation done even if the loop is not executed
compCount++;
//copy the rest of the stuff if left
while(leftArrIndex < szLeft){
moveCount++;
compCount++;
newArr[bigArrIndex] = left[leftArrIndex];
leftArrIndex++;
bigArrIndex++;
}
//1 more computation done even if the loop is not executed
compCount++;
return newArr;
}
void mergeSort( int * arr, int size, int &compCount, int &moveCount){
//to take the branch or not needs 1 comparison
compCount++;
if(size > 1){
int mid = size/2;
int * left = new int[mid];
int * right = new int[size-mid];
for(int i = 0; i < mid; i++){
compCount++;
left[i] = arr[i];
moveCount++;
}
//1 more computation done even if the loop is not executed
compCount++;
for(int i = mid; i < size; i++){
right[i-mid] = arr[i];
moveCount++;
compCount++;
}
//1 more computation done even if the loop is not executed
compCount++;
mergeSort(left,mid,compCount,moveCount);
mergeSort(right,size-mid,compCount,moveCount);
int * sortedArr = merge(left,mid,right,size-mid,compCount,moveCount);
cout << "Done: ";
for (int i = 0; i < size; ++i)
cout << sortedArr[i] << " ";
cout << endl;
//delete[] left;
//delete[] right;
for(int i = 0; i < size; i++){
arr[i] = sortedArr[size];
moveCount++;
compCount++;
}
//1 more computation done even if the loop is not executed
compCount++;
}
}
Just one line. Fix noted in comment:
//delete[] left;
//delete[] right;
for(int i = 0; i < size; i++){
arr[i] = sortedArr[i]; // fix from [size] to [i]
moveCount++;
compCount++;
}
Comment: in mergeSort, rather than allocate left and right, the code could use arr instead of left, and arr+mid instead of right. Two less allocations. An entry / helper function could do a one time allocation of a temp array the same size as the original array, and pass that as a parameter to mergeSort() which would in turn pass it as a parameter to merge(). In that case, all mergeSort does is create pairs of indices on the stack, and merge does the actual merge and copy back.
Although probably beyond the scope of this class, the copy back can also be eliminated with two mutually recursive versions of mergeSort, one where the merged data ends in in the original array, call this mergeSortO(), one where the merged data ends up in the temp array, call this mergeSortT(). mergeSortO() calls mergeSortT() twice (left and right halves), then calls merge() to merge from temp array to original array. mergeSortT() calls mergeSortO() twice (left and right halves), then calls merge() to merge from original array to temp array, or if size is 1, it copies one element from original to temp array.
Also probably beyond the class, another alternative would be bottom up merge sort, as most libraries such as STL std::stable_sort() use some variation of bottom up merge sort.
I'm using bubble sort to sort numbers in an array in order from lowest to highest. But there are some numbers which are the same, but I don't need them to be printed twice. So how do I check whether it was already printed and not to repeat the action?
The Bubble sort:
for(int i=0;i<n-1;i++){
for(int j=i+1;j<n;j++){
if(m[i]>m[j]){
temp=m[i];
m[i]=m[j];
m[j]=temp;
}
}
}
Since number are already sorted when you are printing it, you can store the last printed number and compare against this before printing.
Something like:
std::cout << m[0] << std::endl;
int last_print = m[0];
for(int i = 1; i < n; ++i)
{
if(m[i] != last_print)
{
std::cout << m[i] << std::endl;
last_print = m[i];
}
}
filter duplicate out when printing (assuming m being int[])
int last = 0;
for(int i=0;i<n;i++){
int num = m[i];
if (i == 0 || last != num) {
// print num;
}
last = num;
}
or this way if you don't like too much vars
for(int i=0;i<n;i++){
if (i == 0 || m[i - 1] != [i]) {
// print m[i];
}
}
Alternatively you could remove duplicates on sort
for(int i=0;i<n-1;i++){
for(int j=i+1;j<n;){
if (m[i]==m[j]) { // remove
m [j] = m [n - 1]; // replace with last
n --; // cut last
} else {
if(m[i]>m[j]){
temp=m[i];
m[i]=m[j];
m[j]=temp;
}
j ++;
}
}
}
You can add the number to a std::set as soon as you print it, and check all numbers if they are in the set before printing them.
EDIT: I missed the restriction that the numbers are sorted. In that case, a set is overkill and less efficient than just keeping track of the last number printed, and only printing numbers that are different from it afterwards.