Hollerith's Radix Sort - c++

I have implemented the normal Radix Sort:
#include <iostream>
using namespace std;
void print(int arr[], int n) {
for (int i = 0; i < n; i++) {
cout << arr[i] << " ";
}
cout << endl;
}
int findMax(int arr[], int n) {
int mx = 0;
for (int i = 0; i < n; i++) {
if (arr[i] > mx)
mx = arr[i];
}
return mx;
}
void countingSort(int arr[], int n, int exp) {
int output[n];
const int m = findMax(arr, n) + 1;
int C[m];
for (int i = 0; i < m; i++) {
C[i] = 0;
}
for (int i = 0; i < n; i++)
C[(arr[i] / exp) % 10]++;
for (int i = 1; i < 10; i++)
C[i] += C[i - 1];
for (int i = n - 1; i >= 0; i--) {
output[C[(arr[i] / exp) % 10] - 1] = arr[i];
C[(arr[i] / exp) % 10]--;
}
for (int i = 0; i < n; i++)
arr[i] = output[i];
}
void radixSotr(int arr[], int n) {
int m = findMax(arr, n);
for (int exp = 1; m / exp > 0; exp *= 10) {
countingSort(arr, n, exp);
}
}
int main() {
int n;
cout << "Enter the number of elements: ";
cin >> n;
int arr[n];
cout << "Enter the elements of the array: ";
for (int i = 0; i < n; i++) {
cin >> arr[i];
}
cout << endl;
cout << "Unsorted version of the array: " << endl;
print(arr, n);
cout << endl;
cout << "Sorted version of the array: " << endl;
radixSotr(arr, n);
print(arr, n);
return 0;
}
Now I am trying to implement Hollerith's version of Radix Sort, where the Radix Sort starts with the most significant bit and propagates iteratively to the least significant bit. Could you give me any ideas how to modify my code, because I am stuck.

Your countingSort function has a problem:
you should use an array of 10 indexes for counting instead of finding the largest element and declaring int C[m]. Your current code allocates a potentially huge array in automatic storage, invoking undefined behavior.
Here is a corrected version:
void countingSort(int arr[], int n, int exp) {
int output[n];
int C[10] = { 0 };
for (int i = 0; i < n; i++)
C[(arr[i] / exp) % 10]++;
for (int i = 1; i < 10; i++)
C[i] += C[i - 1];
for (int i = n - 1; i >= 0; i--) {
output[--C[(arr[i] / exp) % 10]] = arr[i];
C[(arr[i] / exp) % 10]--;
}
for (int i = 0; i < n; i++)
arr[i] = output[i];
}
Note that this algorithm cannot sort an array with negative numbers.
The Hollerith algorithm uses least significant digit to most significant digit. It was invented for sorting US Census data tabulated on punched cards using tabulating machines. This is a very early example of computing for data processing that goes back to 1887. Punch cards used 2 different character encoding schemes named H-code and T-code all the way to the end of the 20th century, H standing for Herman Hollerith, inventor of these sorting machines, who died in 1929. (see http://ed-thelen.org/comp-hist/Knuth-Sort.html )
For the most significant bit down to the least significant bit, you need recursion, not an iterative method like the one you have:
Find the maximum value, hence the maximum exponent to get the most significant digit.
Sort the array according to the current digit
For each bucket of elements with the same digit at the current position:
if the bucket is empty or has only one element, it is sorted
otherwise, recurse on the bucket for the next lesser digit, using exp/10.
You can do this with any base >= 2.

Related

Can't find the minimum in an array with respect to maximum from the same array

I wanted to write a program to take two arrays as input and convert the first array such that the difference of maximum value and minimum value from the first array gives the smallest possible number.
I tried to write a code to find a smaller number most closest to the maximum from the array in C++, but the function for finding the minimum works on Codelite, but not on other compilers;
Is there any fix to solve this, either to the code or the compiler?
Here is the code I tried:
#include <iostream>
using namespace std;
void swap(int A[], int B[], int n)
{
int x, y, temp;
for(x=0;x<n;++x)
{
for(y=0;y<n;++y)
{
if(A[x]>B[y])
{
temp = A[x];
A[x] = B[y];
B[y] = temp;
}
}
}
}
void sortas(int A[], int n)
{
int i, j, temp;
for (i = 0; i < n; i++)
{
for (j = i; j < n; j++)
{
if (A[i] > A[j+1])
{
temp = A[i];
A[i] = A[j+1];
A[j+1] = temp;
}
}
}
}
int maxfind(int A[], int n)
{
int z, a;
a = A[0];
for(z=0;z<n;++z)
{
if(a<A[z])
{
a = A[z];
}
}
cout << "Max value in A is" << a << endl;
return a;
}
int minfind(int A[], int n, int amax, int amin)
{
int z, maxi;
maxi = amax;
for(z=0;z<n;++z)
{
if(maxi >= A[z])
{
amin = A[z];
}
else
{
maxi = maxi-1;
}
}
cout << "Mix value in A is" << amin << endl;
return amin;
}
int main() {
int z, t;
cout << "Enter number of test cases: ";
cin >> t;
int n, i, j, amax, amin;
for(z=0;z<t;++z)
{
cout << "Enter size of array" << endl;
cin >> n;
int A[n], B[n];
cout << "Enter Array A values:" << endl;
for(i=0;i<n;++i)
{
cin >> A[i];
}
cout << "Enter Array B values:" << endl;
for(j=0;j<n;++j)
{
cin >> B[j];
}
swap(A, B, n);
sortas(A, n);
cout << "Swapped and sorted array is: " << endl;
for(i=0;i<n;++i)
{
cout << A[i] << "\t" << B[i] << endl;
}
amax = 0;
amin = 0;
amax = maxfind(A, n);
amin = minfind(A, n, amax, amin);
}
return 0;
}
Here is the output to that code:
1 1 1 3 4 2
Max value in A is 1 Min value in A is 1
1 2 2
-1882830412 4 3 6 3
Max value in A is 2 Min value in A is -1882830412
The problem is with your bubble sort:
void sortas(int A[], int n)
{
int i, j, temp;
for (i = 0; i < n; i++)
{
for (j = i; j < n; j++) // why not start at i + 1 ??
{
if (A[i] > A[j+1]) // j + 1 is out of bounds when j == n - 1
{
temp = A[i];
A[i] = A[j+1]; // <-- Some random value is written to A.
A[j+1] = temp; // <-- Overwriting some variable on the stack
// of main() (possibly B ?)
}
}
}
}
A correct bubble sort (this is not the pedantic bubble sort), this is probably the most used.
void sortas(int A[], int n)
{
for (int i = 0; i < n - 1; ++i)
{
for (int j = i + 1; j < n; ++j)
{
if (A[i] > A[j])
std::swap(A[i], A[j]);
}
}
}
The actual bubble sort algorithn (the "pedantic" bubble sort), swaps only occur on neighboring values.
void sortas(int A[], int n)
{
for (int i = 0; i < n - 1; ++i)
{
for (int j = 0; j < (n - i) - 1; ++j)
{
if (A[j] > A[j + 1])
std::swap(A[j], A[j + 1]);
}
}
}
Use one or the other, for integers, the performance is identical.

Right rotation operation

int main()
{
int shiftSteps, newposition;
int numbers[10], numberscopy[10];
cin >> shiftSteps;
for (int i = 0; i < 10; i++)
cin >> numbers[i];
for (int i = 0; i < 10; i++)
numberscopy[i] = numbers[i];
//----------------------------------------
for (int i = 0; i < 10; i++)
{
newposition = (i + shiftSteps) % 10;
numbers[newposition] = numberscopy[i];
}
for (int i = 0; i < 10; i++)
cout << numbers[i] << " ";
}
I wrote this code to rotate 10 numbers to Right with auxiliary array "numberscopy", but i want to rewrite the code without auxiliary array and i don't know how.
You can rotate the array in-place, i.e. without using an auxiliary array with std::rotate which is a standard algorithm.
std::rotate(numbers, numbers + shiftSteps, numbers + 10);
Without auxiliary array, you can make use of reversal algorithm to rotate array by "shiftSteps".
It involves following three steps,
reversing array from 0 to sizeOfArray-1
reversing array from 0 to shiftSteps-1
reversing array from shiftSteps to sizeOfArray-1
Here's final code,
void reverseArray(int numbers[], int begin, int end)
{
while (begin < end)
{
swap(numbers[begin], numbers[end]);
begin++;
end--;
}
}
void rightRotate(int numbers[], int shiftSteps, int sizeOfArray)
{
reverseArray(numbers, 0, sizeOfArray-1);
reverseArray(numbers, 0, shiftSteps-1);
reverseArray(numbers, shiftSteps, sizeOfArray-1);
}
int main()
{
int shiftSteps;
int numbers[10];
cin >> shiftSteps;
for (int i = 0; i < 10; i++)
cin >> numbers[i];
rightRotate(numbers, shiftSteps, 10);
for (int i = 0; i < 10; i++)
cout << numbers[i] << " ";
}
Source for more info.

Generating all R-digit numbers among N digits in C++ (combinations, iterative)?

I have a program, where I have to generate all R-digit numbers among N digits in C++, for example for N=3 (all digits from 1 to N inclusive) and R=2 the program should generate 12 13 21 23 31 32. I tried to do this with arrays as follows, but it does not seem to work correctly.
#define nmax 20
#include <iostream>
using namespace std;
int n, r;
void print(int[]);
int main()
{
cin >> n;
cin >> r;
int a[nmax];
int b[nmax];
int used[nmax];
for (int p = 1; p <= n; p++) {
//Filling the a[] array with numbers from 1 to n
a[p] = n;
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < r; j++) {
b[j] = a[i];
used[j] = 1;
if (used[j]) {
b[j] = a[i + 1];
}
used[j] = 0;
}
print(b);
}
return 0;
}
void print(int k[]) {
for (int i = 0; i < r; i++) {
cout << k[i];
}
}
If I understand your question correctly, you can explore this website where it explains the problem and suggests the solution thoroughly.
Here is a slightly altered code:
Pay attention that time is an issue for bigger N values.
#define N 5 // number of elements to permute. Let N > 2
#include <iostream>
using namespace std;
// NOTICE: Original Copyright 1991-2010, Phillip Paul Fuchs
void PrintPerm(unsigned int *a, unsigned int j, unsigned int i){
for(unsigned int x = 0; x < N; x++)
cout << " " << a[x];
cout << " swapped( " << j << " , " << i << " )\n";
}
void QuickPerm(void){
unsigned int a[N], p[N+1];
register unsigned int i, j, PermCounter = 1; // Upper Index i; Lower Index j
for(i = 0; i < N; i++){ // initialize arrays; a[N] can be any type
a[i] = i + 1; // a[i] value is not revealed and can be arbitrary
p[i] = i;
}
p[N] = N; // p[N] > 0 controls iteration and the index boundary for i
PrintPerm(a, 0, 0); // remove comment to PrintPerm array a[]
i = 1; // setup first swap points to be 1 and 0 respectively (i & j)
while(i < N){
p[i]--; // decrease index "weight" for i by one
j = i % 2 * p[i]; // IF i is odd then j = p[i] otherwise j = 0
swap(a[i], a[j]); // swap(a[j], a[i])
PrintPerm(a, j, i); // remove comment to PrintPerm target array a[]
PermCounter++;
i = 1; // reset index i to 1 (assumed)
while (!p[i]) { // while (p[i] == 0)
p[i] = i; // reset p[i] zero value
i++; // set new index value for i (increase by one)
} // while(!p[i])
} // while(i < N)
cout << "\n\n ---> " << PermCounter << " permutations. \n\n\n";
} // QuickPerm()
int main(){
QuickPerm();
} //main
Here is a list of the modified items from the original code.
N defined to be 5 instead of 12.
A Counter has been added for more informative result.
The original swap instructions reduced by using c++ standard libraries' swap() function.
The getch() has been removed.
The 'Display()' function has been renamed to be 'PrintPerm()'.
The printf() function has been replaced by cout.
Printing number of permutation has been added.

Counting number of copying and comparisons in heapsort and insertation sort

I want to count how many times does algorithm makes comparisons and how many times algorithm makes copying.
#include <stdio.h>
#include <random>
#include <fstream>
#include <iostream>
#include <algorithm>
#include <time.h>
void generuoti(int _N, const char *_file);
void nuskaityti(const char *_file);
int ps = 0;
int ks = 0;
void heapify(double arr[], int n, int i)
{
int largest = i; // Initialize largest as root
int l = 2 * i + 1; // left = 2*i + 1
int r = 2 * i + 2; // right = 2*i + 2
// If left child is larger than root
if (l < n && arr[l] > arr[largest])
largest = l;
ps+=1;
// If right child is larger than largest so far
if (r < n && arr[r] > arr[largest])
largest = r;
ps += 1;
// If largest is not root
if (largest != i)
{
std::swap(arr[i], arr[largest]);
ps += 1;
ks += 1;
// Recursively heapify the affected sub-tree
heapify(arr, n, largest);
}
}
// pagr funkcija haep sortui
void heapSort(double arr[], int n)
{
// Build heap (rearrange array)
for (int i = n / 2 - 1; i >= 0; i--)
heapify(arr, n, i);
// One by one extract an element from heap
for (int i = n - 1; i >= 0; i--)
{
// Move current root to end
std::swap(arr[0], arr[i]);
ks+=1;
// call max heapify on the reduced heap
heapify(arr, i, 0);
}
}
void insertion_sort(double arr[], int n)
{
int i, key, j;
for (i = 1; i < n; i++)
{
key = arr[i];
j = i - 1;
ks+=1;
while (j >= 0 && arr[j] > key)
{
arr[j + 1] = arr[j];
j = j - 1;
ks+=1;
ps+=1;
}
arr[j + 1] = key;
ks+=1;
}
}
using namespace std;
double *Data;
double* A;
double* B;
double N;
int main()
{
srand(time(NULL));
cout << "Generuojame atsitktinius duomenis" << endl;
generuoti(20000, "duom.txt");
cout << "Nuskaitome duomenis" << endl;
nuskaityti("duom.txt");
A = new double[(int)N];
B = new double[(int)N];//jeigu algoritmui reikia papildomo masyvo
for (int i = 0; i < N; i++) {
A[i] = Data[i];
}
cout << "Pradine skaiciu seka:" << endl;
for (int i = 0; i < N; i++)
cout << A[i] << " ";
cout << endl;
//
insertion_sort(A, N);
//heapSort(A, N);
//truksta veiksmu sk
cout << "Surusiuota skaiciu seka:" << endl;
for (int i = 0; i < N; i++)
cout << A[i] << " ";
cout << endl;
cout << "Kopijavimu skaicius " << ks << endl;
cout << "Palyginimu skaicius " << ps << endl;
system("pause");
return 0;
}
void generuoti(int _n, const char *_file) {
ofstream os(_file);
os << _n << endl;
for (int i = 0; i<_n; i++)
os << " " << 500+ (double)(rand() % 3001) ;
os.close();
}
void nuskaityti(const char *_file) {
ifstream is(_file);
if (is.fail()) {
cout << "Failo nera" << endl;
exit(1);
}
is >> N;
Data = new double[(int)N];
for (int i = 0; i < N; i++) {
is >> Data[i];
}
}
This is my code, and ps - is equal to a number of comparisons, and ks - is equal to number of copying. I want to ask if I counted all comparisons and all copying in the algorithms? Thanks for answers.
No
if (l < n && arr[l] > arr[largest])
largest = l;
ps+=1;
There are two problems here. Assuming you are talking about double comparisons (rather than integer), the comparison may or may not occur.
Secondly your indentation is deeply misleading. (You always increment.)
You need
if (l < n) {
ps++; // About to compare
if (arr[l] > arr[largest])
largest = l;
}
There are probably other errors, but it is impossible to tell because I can't read your language, so the printed text, comments, and names are meaningless.
Given you are writing in C++, I would write a class with operator <() and operator =, and a copy constructor, and instrument those. That way you cannot possibly get it wrong.

Finding the maximum value of every row in 2D array C++

I've managed to find the minimum value of every row of my 2D array with this
void findLowest(int A[][Cm], int n, int m)
{
int min = A[0][0];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
if (A[i][j] < min)
{
min = A[i][j];
}
}
out << i << " row's lowest value " << min << endl;
}
}
I'am trying to find the maximum value of every row using the same way,but it only shows me first maximum value
void findHighest(int A[][Cm], int n, int m)
{
int max = A[0][0];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
if (A[i][j] > max)
{
max = A[i][j];
}
}
out << i << " row's highest value " << max << endl;
}
}
I can't find what's wrong with the second function and why is it only showing me the first maximum value it finds. Any help ?
Both functions return the result (maximum or minimum) for the whole array rather than each row, because you set max once rather than once per row. You can get the result for each row as follows:
void findHighest(int A[][Cm], int n, int m)
{
for (int i = 0; i < n; i++)
{
int max = A[i][0];
for (int j = 1; j < m; j++)
{
if (A[i][j] > max)
{
max = A[i][j];
}
}
// do something with max
}
}
or, even better, use the standard library function max_element:
void findHighest(int A[][Cm], int n, int m)
{
if (m <= 0) return;
for (int i = 0; i < n; i++)
{
int max = *std::max_element(A[i], A[i] + m);
// do something with max
}
}
This should give you all values which is easy to check:
#include <algorithm>
#include <iostream>
enum { Cm = 2 };
void findHighest(int A[][Cm], int n, int m) {
if (m <= 0) return;
for (int i = 0; i < n; i++) {
int max = *std::max_element(A[i], A[i] + m);
std::cout << max << " ";
}
}
int main() {
int A[2][2] = {{1, 2}, {3, 4}};
findHighest(A, 2, 2);
}
prints 2 4.
If your compiler supports C++11, for concrete arrays you could use the following alternative, that's based on std::minmax_element:
template<typename T, std::size_t N, std::size_t M>
void
minmax_row(T const (&arr)[N][M], T (&mincol)[N], T (&maxcol)[N]) {
for(int i(0); i < N; ++i) {
auto mnmx = std::minmax_element(std::begin(arr[i]), std::end(arr[i]));
if(mnmx.first != std::end(arr[i])) mincol[i] = *(mnmx.first);
if(mnmx.second != std::end(arr[i])) maxcol[i] = *(mnmx.second);
}
}
Live Demo
Your test data is guilty for not clearly showing you the defect.
The row minima occur in decreasing values, so that they get updated on every row.
And the row maxima also occur in decreasing values, so that the first one keeps winning.
As others pointed, your function finds the global minimum/maximum, no the per-row extrema.
Move the initialization of the min/max variable inside the outer loop.
As mentioned your code only shows the maximum element in the whole array.
Here is the code which will help you.
void findHighest(int A[][Cm], int n, int m)
{
int max[n];
max[0]=A[0][0];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
if (A[i][j] > max[i])
{
max[i] = A[i][j];
}
}
cout << i << " row's highest value " << max[i] << endl;
}
}
{
int i,j;
int arr[4][2]={(1,2),(3,4),(5,6),(7,8)};
int max;
max=arr[0][0];
for( int i=0; i<4; i++)
{
for(int j=0; j<2; j++)
{
if(max<arr[i][j])
{
max=arr[i][j];
}
}
}
int min;
min=arr[0][0];
for(int i=0; i<4; i++)
{
for(int j=0; j<2; j++)
{
if(min>arr[i][j])
{
min=arr[i][j];
}
}
}
cout<<"maximum number is:"<<max;
cout<<endl;
cout<<"Minimum Number is:"<<min;
}