Using Multidimensional Arrays to Keep Track of Indices in C++ - c++

I'm working on a project where I need to sort an array from least to greatest, but save the values of the indices. For example, with the array {2, 7, 8, 1, 3}, the sorted indices would be {3, 0, 4, 1, 2}. I thought that I could use a two dimensional array to accomplish this; I would add the index to each component, sort the array, then retrieve the original index from the second element. It hasn't been working for me as well as I hoped though, I have my current code below and it keeps giving me a segmentation fault. I don't know what I'm doing wrong, but I'm assuming its something in my for loops.
#include <iostream>
#include <algorithm>
using namespace std;
const int SIZE = 7;
int main()
{
int intArray[SIZE] = {5, 3, 32, -1, 1, 104, 53};
int i, j, k, l = 0;
int temp[SIZE][2];
//fills multidimensional array temp with data from intArray or index #
for(i = 0; i < 7; i++){
for(j = 0; j < 2; j++){
switch (j)
{
case '0':
temp[i][j] = *intArray;
break;
case '1':
temp[i][j] = i;
break;
}
}
}
sort(intArray, intArray + SIZE);
//prints each component of temp individually
cout << "Sorted Array looks like this." << endl;
for (k = 0; i < 7; i++){
for (l = 0; j < 2; i++){
cout << &temp[k][l] << endl;
}
}
return 0;
}

The following loop is much simpler and does what it should:
for(i = 0; i < 7; i++){
temp[i][0] = intArray[i];
temp[i][1] = i;
}
One error in your code is the line
temp[i][j] = *intArray;
This always assigns the 1st element of intArray.
The thing that causes the segmentation fault is probably the & in the output statement, just remove it.
Aside from that, I agree with the recommendation in the comment by RyanP.

Use std::map. The code will be the easiest. Test on cpp.sh
#include <iostream>
#include <map>
int main()
{
std::map<int,int>arr = {{5,0}, {3,1}, {32,2}, {-1,3}, {1,4}, {104,5}, {53,6}};
for(auto&x:arr) std::cout << x.first << " - > " << x.second << std::endl;
return 0;
}

I ended up using what Frank Puffer said and chose to use a simple bubble sort instead of using any of the built in functions. Here is a link to what my final program looked like http://ideone.com/cpEgGA
#include <iostream>
#include <algorithm>
using namespace std;
const int SIZE = 7;
int main()
{
int intArray[SIZE] = {5, 3, 32, -1, 1, 104, 53};
int i, j, k, l, m = 0;
int temp2[SIZE][2];
int indices[SIZE] = {};
for(i = 0; i < 7; i++){
temp2[i][0] = intArray[i];
temp2[i][1] = i;
}
cout << "Unsorted Array looks like this." << endl;
for (j = 0; j < 7; j++){
cout << temp2[j][0];
cout << " : ";
cout << temp2[j][1] << endl;
}
for(k = 0; k < SIZE; k++)
{
for(j = 0; j < SIZE-1-k; j++)
{
if(temp2[j+1][0] < temp2[j][0])
{
l = temp2[j][0];
temp2[j][0] = temp2[j+1][0];
temp2[j+1][0] = l;
l = temp2[j][1];
temp2[j][1] = temp2[j+1][1];
temp2[j+1][1] = l;
}
}
}
cout << "Sorted Array looks like this." << endl;
for (m = 0; m < SIZE; m++)
{
cout << temp2[m][0];
cout << " : ";
cout << temp2[m][1] << endl;
}
for(i = 0; i < SIZE; i++){
indices[i] = temp2[i][1];
}
cout << "Indices of Sorted Array look like this." << endl;
for(i = 0; i < SIZE; i++){
cout << indices[i] << endl;
}
return 0;
}

Related

Static array and Dynamic array in a function

I have a question as below C++ code.
this is the code(No function) that can successful execute.
#include <iostream>
using namespace std;
int main()
{
int size_3 = 3;
//arr1 is a static array
int arr1[3][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
//arr2 is a dynamic array
int** arr2 = new int* [size_3];
for (int i = 0; i < size_3; i++) {
arr2[i] = new int[size_3];
}
int val = 9;
for (int i = 0; i < size_3; i++) {
for (int j = 0; j < size_3; j++) {
arr2[i][j] = val--;
}
}
cout << "Elements in matrix 1: " << endl;
for (int i = 0; i < size_3; i++) {
for (int j = 0; j < size_3; j++) {
cout << arr1[i][j] << " ";
}
cout << endl;
}
cout << endl;
cout << "Elements in matrix 2: " << endl;
for (int i = 0; i < size_3; i++) {
for (int j = 0; j < size_3; j++) {
cout << arr2[i][j] << " ";
}
cout << endl;
}
cout << endl;
int** prod_arr = new int* [size_3];
for (int i = 0; i < size_3; i++) {
prod_arr[i] = new int[size_3];
}
for (int i = 0; i < size_3; i++) {
for (int j = 0; j < size_3; j++) {
prod_arr[i][j] = 0;
for (int k = 0; k < size_3; k++) {
prod_arr[i][j] += arr1[i][k] * arr2[k][j];
}
}
}
cout << "Elements in the product of 2 matrices: " << endl;
for (int i = 0; i < size_3; i++) {
for (int j = 0; j < size_3; j++) {
cout << prod_arr[i][j] << " ";
}
cout << endl;
}
}
However, I am gonna to use the function for the multiplication of the 2 matrices.
how could I move it to function, since the first array is static array, the second array is dynamic array.
I have try different way to use pointer , pass-by reference in the function, but still can't work.
My invalid code as below.
#include <iostream>
using namespace std;
int** function(int farr1, int farr2, int size3) {
int** prod_arr = new int* [size3];
for (int i = 0; i < size3; i++) {
prod_arr[i] = new int[size3];
}
for (int i = 0; i < size3; i++) {
for (int j = 0; j < size3; j++) {
prod_arr[i][j] = 0;
for (int k = 0; k < size3; k++) {
prod_arr[i][j] += farr1[i][k] * farr2[k][j];
}
return prod_arr[i][j];
}
}
}
int main()
{
int size_3 = 3;
//arr1 is a static array
int arr1[3][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
//arr2 is a dynamic array
int** arr2 = new int* [size_3];
for (int i = 0; i < size_3; i++) {
arr2[i] = new int[size_3];
}
int val = 9;
for (int i = 0; i < size_3; i++) {
for (int j = 0; j < size_3; j++) {
arr2[i][j] = val--;
}
}
cout << "Elements in matrix 1: " << endl;
for (int i = 0; i < size_3; i++) {
for (int j = 0; j < size_3; j++) {
cout << arr1[i][j] << " ";
}
cout << endl;
}
cout << endl;
cout << "Elements in matrix 2: " << endl;
for (int i = 0; i < size_3; i++) {
for (int j = 0; j < size_3; j++) {
cout << arr2[i][j] << " ";
}
cout << endl;
}
cout << endl;
int** prod_arr = function(farr1, farr2, size_q3);
cout << "Elements in the product of 2 matrices: " << endl;
for (int i = 0; i < size_3; i++) {
for (int j = 0; j < size_3; j++) {
cout << prod_arr[i][j] << " ";
}
cout << endl;
}
cout << endl;
}
I want to use the function to execute the code.
I got 2 array, one is static and another is dynamic,
How to use pointer and pass to function with this different arrays.
Thanks a lot for your help.
Some C++ array examples to get you started :
A 2D dynamically array can be modeled as std::vector<std::vector<int>>
#include <array> // static array
#include <vector> // dynamic array, can resize at runtime
#include <iostream>
// https://en.cppreference.com/w/cpp/container/array
// accept a modifiable static array (content can be changed
// the & means by reference, the array will not get copied
// https://isocpp.org/wiki/faq/references
void func1(std::array<int, 4>& values)
{
values[2] = 3;
}
// array cannot be modified in body of func2 only used : const
void func2(const std::array<int, 4>& values)
{
std::cout << values[2] << "\n";
}
// https://en.cppreference.com/w/cpp/container/vector
// return a dynamically allocated array of integers
// it will have a size of 5 when returned
std::vector<int> get_values()
{
return std::vector<int>{1, 2, 3, 4, 5};
}
int main()
{
auto values = get_values();
values.push_back(6); // add another value
// https://en.cppreference.com/w/cpp/language/range-for
// prefer to use those if you don't need indices
// (which is not as often as you think)
for (const int value : values)
{
std::cout << value << " ";
}
return 0;
}

switch specific elements between two arrays and have the switched element placed at end of the first array

i'm trying to make it so if i enter the number 3 , the matrix would change to {1,2,4,5,6,7,8,9,10,11,12,0}, i'm not sure if the method of switching the element between two arrays is the best way to do it and i'm trying to do it using pointers
using namespace std;
#include <iomanip>
int main() {
int arr[3][4] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }, i, j,c;
int* ptr = &arr[0][0];
int zero[3][4] = { 0,0,0,0,0,0,0,0,0,0,0,0 };
int* zptr = &zero [0][0];
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 4; j++)
{
cout << setw(8) << arr[i][j] << ' ';
}
cout << endl;
cout << ' ' << endl;
}
for (i = 0; i < 3; i++) {
if (arr[i][0] = i)
{
break;
}
for (int j = 0; j < 4; j++)
cin >> i;
cout << ptr;
}
return 0;
}
you could use easier approach to achieve this using vector in c++ and by finding the index of the input element, consider this example :
int getIndex(vector<int> v, int K) {
auto it = find(v.begin(), v.end(), K);
// calculating the index of K
// note that here i'm supposed the input is valid
int index = it - v.begin();
return index;
}
and you can use the index you get to 1) append in A the element B[index], 2) assign B[index] to A[index] and 3) erase the element A[index].
hope this can be helpful.

How to have code prompt user to enter info rather than hardwiring it?

I have a code that reorders arrays based on an index. The code works fine when hardwired to add the numbers in through the editor, but how do I switch that to prompt the user to have to enter the numbers for both the array and index through terminal?
#include <iostream>
using namespace std;
void reorder(int arr[], int index[], int n)
{
int temp[n];
for (int i = 0; i < n; i++)
temp[index[i]] = arr[i];
for (int i = 0; i < n; i++) {
arr[i] = temp[i];
index[i] = i;
}
}
int main()
{
int arr[] = { 3, 2, 1, 5, 6, 4 };
int arb[] = { 5, 6, 1, 3, 2, 4 };
int index[] = { 3, 4, 2, 0, 1, 5 };
int n = sizeof(arr) / sizeof(arr[0]);
cout << "\nSequence array is: \n";
for (int i = 0; i < n; i++)
std::cout << index[i] << ' ';
cout << "\nOriginal array is: \n";
for (int i = 0; i < n; i++)
cout << arr[i] << " ";
printf("\n");
reorder(arr, index, n);
reorder(arb, index, n);
cout << "Reordered array is: \n";
for (int i = 0; i < n; i++)
cout << arr[i] << " ";
printf("\n");
printf("\n");
return 0;
}
Have a look on your reorder function. As PaulMcKenzie commented, the code works (if corrected maybe like this):
void reorder(int arr[], int index[], int n)
{
vector<int> temp(n);
for (int i = 0; i < n; i++)
temp[index[i]] = arr[i];
for (int i = 0; i < n; i++) {
arr[i] = temp[i];
index[i] = i;
}
}
see live demo.
Explanation: arrays with variable length are not part of any of the C++ standards. You can use a vector for your purpose that is initialized with n default int values (i.e. 0). This is necessary for randomly accessing it. Of course, your solution is somewhat weak/limited because you have to ensure that the values in index are in range: (0 <= v) && (v < NELEMS(arr)).
As Tomas above mentions, use std::vector instead. However, if you really want to use int[] the following should work.
int nDigits = 0;
cout << "Enter number of digits:" << endl;
cin >> nDigits;
int* arr;
int* index;
arr = new int[nDigits];
index = new int[nDigits];
for(int i = 0; i < nDigits; i++){
cout << "Enter arr element (" << i << "):" << endl;
cin >> arr[i];
cout << "Enter index element (" << i << "):" << endl;
cin >> index[i];
}
... Use vectors instead tbh
You have the problem of variable-length arrays. The simplest but really bad solution is to use a global compile-time constant for the array size. You can use std::cin to read the values from terminal. By the way you shouldn't mix std::cout and std::printf. Use std::cout.
You should add a check of the user input if each entry is unique and in the range [0, n-1].
#include <iostream>
using namespace std;
constexpr unsigned int n = 6;
void reorder(int arr[], int index[])
{
int temp[n];
for (int i = 0; i < n; i++)
temp[index[i]] = arr[i];
for (int i = 0; i < n; i++) {
arr[i] = temp[i];
index[i] = i;
}
}
int main()
{
int arr[] = { 3, 2, 1, 5, 6, 4 };
int arb[] = { 5, 6, 1, 3, 2, 4 };
int index[n];
std::cout << "Enter " << n << " values: ";
for (auto &element : index) {
std::cin >> element;
}
cout << "\nSequence array is: \n";
for (int i = 0; i < n; i++)
std::cout << index[i] << ' ';
cout << "\nOriginal array is: \n";
for (int i = 0; i < n; i++)
cout << arr[i] << " ";
printf("\n");
reorder(arr, index);
reorder(arb, index);
cout << "Reordered array is: \n";
for (int i = 0; i < n; i++)
cout << arr[i] << " ";
printf("\n");
printf("\n");
return 0;
}
The best solution is to use std::vector
#include <iostream>
using namespace std;
void reorder(std::vector<int> arr, std::vector<int> index)
{
auto n = arr.size();
std::vector<int> temp(n);
for (int i = 0; i < n; i++)
temp[index[i]] = arr[i];
for (int i = 0; i < n; i++) {
arr[i] = temp[i];
index[i] = i;
}
}
int main()
{
std::vector<int> arr = { 3, 2, 1, 5, 6, 4 };
std::vector<int> arb = { 5, 6, 1, 3, 2, 4 };
auto n = arr.size();
std::vector<int> index(n);
std::cout << "Enter " << n << " values: ";
for (auto &element : index) {
std::cin >> element;
}
cout << "\nSequence array is: \n";
for (int i = 0; i < n; i++)
std::cout << index[i] << ' ';
cout << "\nOriginal array is: \n";
for (int i = 0; i < n; i++)
cout << arr[i] << " ";
printf("\n");
reorder(arr, index);
reorder(arb, index);
cout << "Reordered array is: \n";
for (int i = 0; i < n; i++)
cout << arr[i] << " ";
printf("\n");
printf("\n");
return 0;
}
To get an input from the command line use cin. You'd also need to use a vector instead of an array to hold a "dynamic array", i.e. an array you don't know the size of at compile time.
Best practice is to put that input into a string, and parse that string, as cin does not handle incorrect input (include string for this).
string input;
cin >> input;
next you need to split the input - it is easiest if the delimiter is space, for a comma, you'd need a different method (you'd need to include iterator, vector and sstream for this)
istringstream iss(input);
vector<string> splitted_input{istream_iterator<string>(iss), istream_iterator<string>()};
and convert it to numbers (include algorithm for this)
vector<int> parsed_input(splitted_input.size());
transform(splitted_input.begin(), splitted_input.end(), parsed_input.begin(), [](auto val){ return stoi(val);});
alternatively, you could use stoi directly without the middle step of splitting the string:
size_t idx = 0, input_len = input.size();
vector<int> values;
while (idx < input_len) {
size_t new_idx;
values.push_back(stoi(input.substr(idx, input_len - idx), &new_idx));
idx += new_idx;
for(; !isdigit(input[idx]) && input[idx] != '-'; ++idx); // skip to the next number
}

When to use bucket sort effectively and how many buckets needed?

Hello I wanted to implement a bucket sort. I think it works for me:
#include <iostream>
using namespace std;
#include <vector>
#include <cmath>
#include <algorithm>
void bucket_sort(int[], const int);
int main(){
system("color 1f");
int array[] = {
5, 77, 99, 100, 77, 57, 23, 1, 2, 57,
81, 24, 21
};
cout << "before sorting: " << endl;
for(auto x : array)
cout << x << ", ";
cout << endl;
bucket_sort(array, 13);
cout << "after sorting: " << endl;
for( auto x : array)
cout << x << ", ";
cout << endl << endl;
return 0;
}
void bucket_sort(int array[], const int size){
int bucket = 10, divider;
int min = array[0], max = array[0], j;
for(auto i(0); i != size; ++i){
if(min > array[i])
min = array[i];
if(max < array[i])
max = array[i];
}
divider = (ceil( (double)(max + 1) / bucket) );
std::vector<int>* vi = new vector<int>[bucket];
for(i = 0; i < size; i++){
j = floor(array[i] / divider);
vi[j].push_back(array[i]);
}
for(i = 0; i < bucket; i++)
std::sort(vi[i].begin(), vi[i].end());
int k = 0;
for(i = 0; i < bucket; i++){
for(int j(0); j < vi[i].size(); j++){
array[k] = vi[i][j];
k++;
}
}
delete[]vi;
}
The code works fine. But is this the way I should do? If I have an array with values close to each other but one or two are too much big:
66, 42, 70, 10, 30, 32, 28, 1000, 50000
How to apply this bucket sort algorithm? Also how many buckets should I use?
I am not sure where you get the number 10. You can use the total number of items in the array.
You can declare vector of vector to create a 2-D vector (instead of new)
vector<vector<int>> vec;
Ideally, bucket_sort should not rely on other sort methods. Here is a version which uses recursion. It keeps iterating until there is zero or one element in each bucket (or several elements with the same value)
Example:
void bucket_sort(std::vector<int> &src)
{
if(src.size() <= 1)
return;
int min = *std::min_element(src.begin(), src.end());
int max = *std::max_element(src.begin(), src.end());
if(min == max)
return;
std::vector<std::vector<int>> vec;
vec.resize(src.size());
for(int i = 0; i < src.size(); i++)
{
//edit: double precision required
int v = int(double(src[i] - min) * src.size() / double(max - min + 1));
vec[v].push_back(src[i]);
}
for(size_t i = 0; i < vec.size(); i++)
//std::sort(vec[i].begin(), vec[i].end());
bucket_sort(vec[i]);
int index = 0;
for(size_t i = 0; i < vec.size(); i++)
for(size_t j = 0; j < vec[i].size(); j++)
src[index++] = vec[i][j];
}
int main()
{
std::vector<int> src = {66, 66, 42, 70, 10, 30, 32, 28, 1000, 50000 };
for(auto x : src) cout << x << ", ";
cout << endl;
bucket_sort(src);
for(auto x : src) cout << x << ", ";
cout << endl << endl;
return 0;
}
Testing:
int test()
{
srand((unsigned int)time(NULL));
//add 1 million random numbers for testing
std::vector<int> src;
for(int i = 0; i < 1000000; i++)
src.push_back(rand());
bucket_sort(src);
for(size_t i = 1; i < src.size(); i++)
if(src[i - 1] > src[i])
{
cout << "fail\n";
return 0;
}
cout << "success\n";
return 0;
}
Edit: changed division calculation to double precision, added test for 1 million

Checking duplicated numbers in Array

The function should check if there is any duplicated number but it's not working somehow.
anyone knows why?
#include <iostream>
using namespace std;
int main()
{
int const size = 10;
int arry[size] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 ,10};
int i = 0;
int k = 1;
for (i = 0; i < size; i++)
{
for (k = 1; k < size; k++)
{
if (arry[i] == arry[k])
{
cout << arry[i] << " " << arry[k] << endl;
cout << "duplicate" << endl;
return 0;
}
}
}
cout << "no duplicate" << endl;
return 0;
}
You should skip when i == k.
for (i = 0; i < size; i++)
{
for (k = i+1; k < size; k++) // <-- either change HERE
{
if (i != k && arry[i] == arry[k])
// ^^^^^^ or HERE
{
cout << arry[i] << " " << arry[k] << endl;
cout << "duplicate" << endl;
return 0;
}
}
}
You're checking every combination twice - for example, you're comparing element 2 with element 5, and then 5 with 2. Aside from the fact that you're also checking an element with itself (which is what timrau's answer is guarding against), you're doing the same work twice.
So try
for (i = 0; i < size; i++)
{
for (k = i + 1; k < size; k++)
instead.
Your approach still doesn't scale very well, it's essentially O(n^2). It would be faster to sort your array and then look for duplicate neighbors.
A more efficient approach should be to sort the array first:
std::vector<int> a = {4, 3, 2, 1, 2, 5, 6};
std::sort(std::begin(a), std::end(a));
for (std::size_t i = 1; i < a.size(); ++i) {
if (a[i - 1] == a[i]) {
std::cout << a[i] << " " << a[i] << std::endl;
std::cout << "duplicate" << std::endl;
return 0;
}
}
return 0;