Sorting through array c++ - c++

So I am attempting to do a bubble-like sort. Not a bubble sort because I don't want to exchange every single value that i run into. I simply want to find the smallest value of each index and place it in order. Such as in the arrayVal[3, 5, 2].
Instead of replacing the value 3 with 2 and then replacing 5 with 3. I want to find the smallest number of the entire array and place it at arrayVal[0] and then move to arrayVal[1].
I can't quite figure out how to do this and am kind of stuck.(I took out the <> on the libraries so you could see which libraries I am using)
#include iostream
#include cmath
#include ctime
using namespace std;
int main()
{
const int STARTLOOP = 0;
const int MAXLOOP = 5;
const int MINRANGE = 1;
const int MAXRANGE = 10;
//int temp = 0;
int smallestVal = 0;
int arrayVal[MAXLOOP];
srand(time(0));
for (int i = STARTLOOP; i < MAXLOOP; i++)
{
arrayVal[i] = (rand() % MAXRANGE) + MINRANGE;
}
for (int i = STARTLOOP; i < MAXLOOP; i++)
{
cout << arrayVal[i] << endl;
}
cout << "Before the sort" << endl;
for (int i = STARTLOOP; i < MAXLOOP; i++)
{
for (int j = i; j < MAXLOOP; j++)
{
if (arrayVal[j] < arrayVal[i])
{
arrayVal[i] = smallestVal;
}
}
}
for (int i = STARTLOOP; i < MAXLOOP; i++)
{
cout << arrayVal[i] << endl;
}
cout << "After the sort" << endl;
return 0;
I also recognize I'm not using functions, i just wrote up the code because I was trying to figure this out. Thank you in advance.

You're never setting smallestVal to anything from the array. You don't need nested loops. Just go through the array once, comparing each value to smallestVal. If it's smaller, you set smallestVal to that value. You should also have a variable that holds the index of the smallest value, which you update at the same time.
At the end, you swap the first element with the smallest one.
int smallestVal = arrayVal[STARTLOOP];
int smallestIndex = STARTLOOP;
for (int i = STARTLOOP + 1; i < MAXLOOP; i++) {
if (arrayVal[i] < smallestVal) {
smallestVal = arrayVal[i];
smallestIndex = i;
}
}
if (smallestIndex != STARTLOOP) {
// swap it with the first element
int temp = arrayVal[STARTLOOP];
arrayVal[STARTLOOP] = smallestVal;
arrayVal[smallestIndex] = temp;
}
You can then increment STARTLOOP and repeat this.

What you want to achieve is some sort of a modified insertion sort. Check out this implementation :
void sort(int values[], int n)
{
for (int i = 0; i < n; ++i)
{
int min = i;
for ( int j = i ; j < n ; j++)
{
if (values[j]<values[min]) min =j;
}
while(values[min-1]>values[min])
{
if(min==0)
break;
if(values[min-1]!=values[min])
swap (values+min-1,values+min);
min--;
}
}
return;
}
What this function does is that it searches the array every time for the smallest element starting from index i and when it finds this element it keeps on swapping it will all of the previous elements in the array until it reaches a smaller element.

Related

How to store the original indices of array after sorting the array in ascending ordering

Assume that I have a array_dist, and I sorted this array in ascending order successfully. But I need also to store the indices of the original array in new array called index_arr.
Example: array [5,4,3,2,1] has indices [0,1,2,3,4]. what I need after sorting the array [1,2,3,4,5]. is these indices [4,3,2,1,0]
I try the following code which correctly sorted the array_dist but not correctly store the indices in index_arr
int index_arr[4344]{};
for (int i = 0; i < 4344; ++i) {
index_arr[i] = i;
}
float temp; int x;
for (int i = 0; i < 4344 ; i++)
{
for (int j = i + 1; j < 4344; j++)
{
if (array_dist[i] > array_dist[j])
{
temp = array_dist[i];
array_dist[i] = array_dist[j];
array_dist[j] = temp;
x = index_arr[i];
index_arr[i] = index_arr[j];
index_arr[j] = x;
}
}
}
cout << "print out distance colum after ascending sorting : \n";
for (int i = 0; i < 4344; ++i)
{
cout << index_arr[i] << " : "
<< array_dist[i] << endl;
}
The correctly working code that I compare my results with:
auto sortRuleLambda = [](pair<int, float> const& s1, pair<int, float> const& s2) -> bool
{
return s1.second < s2.second;
};
sort(array_dist.begin(), array_dist.end(), sortRuleLambda);
cout << "print out distance colum after ascending sorting : \n";
for (int i = 0; i < array_X_train.size(); ++i)
{
cout << array_dist[i].first << ": "
<< array_dist[i].second << endl;
}
map<int, int> smallest;
int arr[4344];
//do some initialize
for (int i=0;i<4344;i++)
{
smallest.insert(pair(arr[i], i));
}
Now smallest will contain the sorted array by value and contain its corresponding index.
Edit (same but without using map container):
class sth //sorry I don't creative with the name
{
public:
int value, index;
explicit sth()
{
value = 0;
index = 0;
}
sth (const int v, const int i)
{
value = v;
index = i;
}
};
int main()
{
constexpr int n = 10; //make a variable like this will make life easier
sth* smallest = new sth[n];
int arr[n] = {1,2,3,-4,12,5,124,-12,22,123};
//do some initialize
for (int i = 0; i < n; i++)
{
smallest[i]=sth(arr[i], i);
}
for (int i = 0; i < n; i++)
{
for (int j = i + 1; j < n; j++)
{
if (smallest[i].value > smallest[j].value)
{
sth temp = smallest[i];
smallest[i] = smallest[j];
smallest[j] = temp;
}
}
}
}
Now the smallest array should contain the value and the index of the first array.
The issue is that you are sorting the original array_dist when you shouldn't be sorting this at all.
You should only sort the index_array based on the comparison of the array_dist values :
// Compare values at `array_dist`, using the index array
if (array_dist[index_array[i]] > array_dist[index_array[j]])
{
// the indices need to be swapped
x = index_arr[i];
index_arr[i] = index_arr[j];
index_arr[j] = x;
}
Once you have this, then to print out the array_dist in sorted order:
for (int i = 0; i < 4344; ++i)
{
cout << index_arr[i] << " : "
<< array_dist[index_arr[i]] << endl;
}
You use the index_array as a subscript within the original array.

C++ why is there a segmentation fault in my pointer selection sort?

Below is my c++ code. I am trying to implement a selection sort using pointers (start and end). The code compiles, but I am getting a segmentation fault before it will sort the random generated list (currently only prints the random numbers).
Any help as to why this is and how to fix it would be greatly appreciated.
#include<stdio.h>
#include<stdlib.h>
#include <iostream>
using namespace std;
void selectionSort(int *start, int *stop) {
for (int i = *start; i < *stop - 1; ++i) {
int min = i;
for (int j = i + 1; j < *stop; ++j) {
if ((&start[0])[j] < (&start[0])[min])
min = j;
}
swap((&start[0])[i], (&start[0])[min]);
}
}
int main()
{
int size = 10;
int* data = new int[size];
for (int i = 0; i < size; ++i)
{
data[i] = rand() % size;
}
for (int k = 0; k < size; k++)
{
cout << data[k] << " ";
}
cout << endl;
selectionSort(data, data+size);
for (int j = 0; j < size; j++)
{
cout << data[j+1] << " ";
}
return 0;
}
The general logic in your function is in the right direction. However, you seem to be confused between values of the elements of the array and the indexing used to access the elements of the array.
The line
for (int i = *start; i < *stop - 1; ++i)
shows the first signs of the confusion.
You are initializing i with the value of the first element of the array and incrementing the value in the subsequent iterations of the loop. That is not correct. Incrementing the value of the first element of the array does not make logical sense.
*stop causes undefined behavior since stop points to a place one past the last valid element.
You need to use int* i, int* j, and int* min to properly sort the elements. That also means updating almost the entire function accordingly. Here's an updated function that works for me.
void selectionSort(int *start, int *stop) {
for (int* i = start; i < (stop - 1); ++i) {
int* min = i;
for (int* j = i + 1; j < stop; ++j) {
if (*j < *min)
{
min = j;
}
}
swap(*i, *min);
}
}
Also, the following lines in main are not correct. You end up accessing the array using an out of bounds index.
for (int j = 0; j < size; j++)
{
cout << data[j+1] << " ";
}
Replace them by
for (int k = 0; k < size; k++)
{
cout << data[k] << " ";
}

Magic square code

#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;
// Functions used in the program.
bool uniqueCheck(int arr[][3], int num);
bool magicSquare(int arr[][3]);
int rTotal(int arr[][3], int row);
int cTotal(int arr[][3], int col);
int dTotal(int arr[][3], bool left);
void display(int arr[][3]);
int main()
{
int arr[3][3]; //makes the array 3x3 makes it into the square
int test[3][3] = {2, 7, 6, 9, 5, 1 , 4 , 3 ,8}; //numbers from 1-9 in order of magic square.
while (1)
{
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
arr[i][j] = 0;// nested for loop the i is for rows and the j is for columns
srand((unsigned)time(NULL));// generates random numbers
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
while (1)
{
int num = (rand() % 9) + 1; // Random function will spit out random numbers from 1-9.
if (uniqueCheck(arr, num))
{
arr[i][j] = num;
break;
}
}
}
}
display(arr);
if (magicSquare(arr))//If the magic square array is an actual magic square than this outputs
{
cout << "This is the Magic Square !" << endl;
break;
}
else //if not than it'll keep looping this until the top one is displayed
cout << "This is Not the Magic Square !" << endl;
}
return 0;
}
// check if the random number generated is a unique number
bool uniqueCheck(int arr[][3], int num)
{
for (int k = 0; k < 3; k++)
for (int i = 0; i < 3; i++)
if (arr[k][i] == num)
return false;
return true;
}
bool magicSquare(int arr[][3]) //This will check if the number presented (randomly) correspond with the magic square numbers.
{
int sum = dTotal(arr, true); // Will check the sum of the diagonal.
if (sum != dTotal(arr, false))
return false;
for (int i = 0; i < 3; i++)
{
if (sum != rTotal(arr, i)) // This will check each row and see if its true or false.
return false;
if (sum != cTotal(arr, i)) // This will check each column and see if its true or false.
return false;
}
return true;
}
int rTotal(int arr[][3], int row) // This will calculate the sum of one row at a time.
{
int sum = 0;
for (int i = 0; i < 3; i++)
sum += arr[row][i];
return sum;
}
int cTotal(int arr[][3], int col) // This will calculate the sum of one column at a time.
{
int sum = 0;
for (int i = 0; i < 3; i++)
sum += arr[i][col];
return sum;
}
int dTotal(int arr[][3], bool left) // This will calculate the sum of diagonal. if the left is true, it will calculate from the left to the right diagonal. If false it will calculate from the right to the left diagonal.
{
int sum = 0;
if (left == true)
{
for (int i = 0; i < 3; i++)
sum += arr[i][i];
return sum;
}
for (int i = 0; i < 3; i++)
sum += arr[i][3 - i - 1];
return sum;
}
void display(int arr[][3]) //This will display the array.
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
cout << arr[i][j] << " ";
cout << endl;
}
cout << endl;
}
This is my code. This calculates a magic square. The only thing I cannot get is my numbers are suppose to switch each time it loops but it shows the same number each time it loops which basically make it an infinite loop...what I'm asking for is help on getting the numbers to change each time it loops. Thank you very much in advance.
When writing code, you should develop new functionality in isolation, before integrating it with other code.
When you were working with the random number generator, you should have noticed that this:
srand((unsigned)time(NULL));// generates random numbers
resets the random number generator. And since you do this in every pass through the main loop, you get the same "random" numbers every time.
Move that line up, outside the loop.

Frequency of Numbers in a 1D Array

its been 6 hours since I have been writing the code but to no avail, I don't no where I am making the mistake but I am making some. Its a frequency output program and output should be like this:
array[8] = {6,1,7,8,6,6,1,9}
Output:
6:3
1:2
7:1
8:1
9:1
But its repeating the same numbers in my code. Any help would be much appreciable.
int array[8] = {6,1,7,8,6,6,1,9};
int store[8];
int a =0;
int b =0;
int c=0;
int d = 0;
store[d] = array[b];
for (d = 0; d < 8; d++){
int count=0;
c = d;
b = d;
for (int e = 0; e < d; e++){
if (array[b] == store[e]){
store[d] = array[b];
b++;
e = 0;
}
else
{
store[d] = array[b];
break;
}
}
for ( int z = 0; z < 7; z++){
if (store[d] == array[z])
{
count++;
}
}
cout << store[d] << ":" << count << endl;
}
You may use a map first to store num->frequency and then a multimap to store freqeuncy => num.
Here is the working solution.
#include <map>
#include <algorithm>
#include <iostream>
int main()
{
int array[8] = {6,1,7,8,6,6,1,9};
// A map to store num => freq
std::map <int, int> freq;
// A map to store freq(can be duplicate) => num
std::multimap <int, int> freqCounts;
// Store num => frequency
for (int i = 0 ; i < 8; i++)
{
freq[array[i]] += 1;
}
// Now Store freq => num
for(auto const & iter : freq)
{
freqCounts.insert (std::pair<int,int>(iter.second, iter.first));
}
// Print in reverse order i.e. highest frequency first
for (std::multimap<int,int>::reverse_iterator rit=freqCounts.rbegin(); rit!=freqCounts.rend(); ++rit)
{
std::cout << rit->second << " : " << rit->first << '\n';
}
return 0;
}
You never seem to update the counters. Try this:
int array[8] = {6,1,7,8,6,6,1,9};
unsigned int store[10] = {}; // large enough to hold the largest array value,
// initialized to zero
for (int n : array) ++store[n]; // update counts
for (int i = 0; i != 10; ++i)
{
std::cout << "Frequency of int " << i << " is " << store[i] << "\n";
}
If the set of values that occur is sparse, or includes negatives, or simply does not fit into a dense range of integers nicely, you can replace unsigned int[10] with an associative container, e.g.:
std::map<int, unsigned int> store;
// algorithm as before
for (auto const & p : store)
{
std::cout << "Frequency of " << p.first << " is " << p.second << "\n";
}
I'm not sure what you are trying to do with the arrays. I have tried to follow the logic, but it's hard to see it with all the anonymous variable names. It seems like you are trying to look for duplicates earlier in the array, but the variable e never gets any other value than 0, so you will only be comparing with the first item in the array.
You can just look in the array itself for previous occurances, and once you know that the number is the first occurance, you only need to look for more occurances after it in the array:
int array[8] = {6,1,7,8,6,6,1,9};
for (int i = 0; i < 8; i++) {
// look to the left in the array if the number was used before
int found = 0;
for (int j = 0; j < i; j++) {
if (array[i] == array[j]) found++;
}
// go on if it's the first occurance
if (found == 0) {
// we know of one occurance
int count = 1;
// look to the right in the array for other occurances
for (int j = i + 1; j < 8; j++) {
if (array[i] == array[j]) count++;
}
cout << array[i] << ":" << count << endl;
}
}
I wanted to submit my solution which I think it´s a more easy one:
#include <iostream>
using namespace std;
int main() {
int n; //number of Elements in the vector
cin>>n;
int vec[n]; //vector with all elements
int v[n]; //vector with Elements without repetition
int c[n]; // vector which stores the frequency of each element
for(int i=0; i<n; i++)
cin>>vec[i];
int k=0; // number of Elements of the vector without Repetition, in the begining, it has 0 Elements
int j=0; //logic Counter, could be replaced with bool
for(int i=0; i<n; i++) {
for(int h=0; h<=k; h++) {
if(vec[i]==v[h]) {
c[h]++;
j=1;
break;
}
}
//if element i of the original vector is equal to element h of the second vector, then increment the frequency of this element
if(j==0) { //else if the element is not equal to any of the second vector, the Position of the 2nd vector is filled with the element, which in this case is the first of ist Kind.
v[k]=vec[i];
c[k]=1;
k++;
} //the number of Elements is increased by one to store another element;
else {
j=0;
}
}
cout<<endl<<endl;
for(int i=0; i<k; i++)
cout<<v[i]<<":"<<c[i]<<endl;
return 0;
}
#include<iostream>
#include<conio.h>
using namespace std;
main()
{ int count[10],key[10],n=10,m;
int i,j,k,temp;
cout<<"Enter The Size Of Array:-\n";
cin>>n;
int a[n];
cout<<"Enter The Elements in Array:-\n";
for(i=0; i<n; i++)
cin>>a[i];
for(i=0; i<n; i++)
for(j=0; j<n-1; j++)
{ if(a[j]>a[j+1])
{ temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
for(i=0; i<n; i++)
cout<<a[i]<<"\t";
for(i=0,k=0; i<n; k++)
{ count[k]=0;
key[k]=a[i];
for(j=i; j<n; j++)
{ if(a[i]==a[j])
count[k]++;
}
i=i+count[k];
}
for(i=0; i<k; i++)
cout<<endl<<key[i]<<" Occurred "<<count[i]<<" Times\n";
getch();
}
/**
* The methods counts the frequency of each element in an array.
*
* Approach: The method checks if the element is already present in the <strong>Map of frequency</strong>.
* If it is not present, add it to the map with the frequency 1 else put it in the map with
* an increment by one of it's existing frequency.
*
* #param arr list of elements
* #return frequency of each elements
*/
public static Map<Integer, Integer> countFrequency(int[] arr) {
Map<Integer, Integer> frequency= new HashMap<Integer, Integer>();
for(int i = 0; i < arr.length; i++) {
if(frequency.get(arr[i])==null) {
frequency.put(arr[i], 1);
}
else {
frequency.put(arr[i],frequency.get(arr[i])+1);
}
}
System.out.println("\nMap: "+frequency);
return frequency;
}

smallest value of array

I'm trying to write a function that will return the smallest value of an array. So far I have this, but all it returns is 0.
I don't see how it would return 0 since I am using a for loop to cycle through the array. Perhaps it is not cycling through the arrays values as I would think it does. Can anyone elaborate on the logic and the fallacy in this code?
#include <iostream>
using namespace std;
int newArray[9] = {4,5,9,3,6,2,1,7,8};
int minArray()
{
int index = 1;
int minimum;
for (int i = 0; i < 9; i++)
{
if (newArray[i] > newArray[index])
{
minimum = newArray[index];
}
index++;
}
return minimum;
}
int main()
{
cout << "original array:\n ";
for (int i = 0; i < 9; i++)
{
cout << newArray[i] << ", ";
}
cout << "minimum value of array: ";
cout << minArray();
return 0;
}
A good idea might be to initialize minimum with an element in the array.
So:
minimum = newArray[0]
In your loop (pseudocode assuming you don't want the answer):
if: newArray[pos] < minimum
minimum = newArray[pos];
I'd do something like this:
#include <iostream>
int minArray(int a[], int size) {
if (size <= 0) return 0; //
int m = a[0];
for (int i = 1; i < size; ++i) {
if (a[i] < m) m = a[i];
}
return m;
}
int main() {
int a[] = { 4, 3, 6, 2 };
std::cout << minArray(a, 4);
return 0;
}
You should initialize minimum with some known value or with maximum integer value.
int minArray()
{
int minimum = newArray[0];
for (int i = 1; i < 9; i++)
{
if (minimum > newArray[i])
{
minimum = newArray[i];
}
}
return minimum;
}
And you are dealing wrong with index (actually you don't need it at all). Example of how index can be used instead of minimum:
int minArray()
{
int index = 0;
for (int i = 1; i < 9; i++)
{
if (newArray[index] > newArray[i])
{
index = i;
}
}
return newArray[index];
}
Both examples should work fine, but I recommend to use first.
The minimum variable should be initially assigned to a value in the array, then compare each element in the array with minimum. If less than, assign minimum with that value:
int minArray()
{
int minimum = newArray[0];
int index = 0;
for (int i = 0; i < 9; i++)
{
if (newArray[i] < minimum)
{
minimum = newArray[i];
}
index++;
}
return minimum;
}