I'm trying to pull off a gapped insertion sort in C++, known as a Library sort. I understand the concept, but I'm having trouble pulling it off going from a regular old insertion sort. I don't know how I'd account for the gaps in the array. I've been using the integer 0 to specify a gap. The code I have so far is below, which is a working insertion sort modified abit. How would you go about implementing a library sort? I went through 20 pages of google, and I have not seen a single actual example of code, in any programming language.
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <vector>
using namespace std;
vector<int> librarySort(int arr[20])
{
int j,tmp;
vector<int> array;
for (int i=0;i<20;i++)
{
array.push_back(0);
array.push_back(arr[i]);
}
for (int i=0;i<40;i++) { cout << array[i] << ",";}
cout << endl;
for (int i = 1; i < 40; i++)
{
j = i;
while (j > 0 && array[j - 1] > array[j])
{
tmp = array[j];
array[j] = array[j - 1];
array[j - 1] = tmp;
j--;
}
}
for (int i=0;i<40;i++) { cout << array[i] << ",";}
return array;
}
int main()
{
srand(time(0));
int array[20]= {0};
for (int i=0;i<20;i++)
{
int n=rand()%19+1;
tmp=array[i];
array[i]=array[n];
array[n]=tmp;
}
for (int i=0;i<20;i++) { cout << array[i] << ",";}
cout << endl;
librarySort(array);
}
Here you have a complete description and implementation. The gap is defined as whatever value that you will not use. If you were using pointers, NULL is a good option.
In general cases you must create an auxiliary array to the one that has the original data. In this case:
#define MAX 20
#define MAX2 100//The size of the gapped array must be bigger
#define EMPTY -1//Use this constant instead of zeros.
bool isEmpty(int index, int gappedArray[MAX2]) {
return gappedArray[index]>=0;
}
vector<int> libSort(int arr[MAX]) {
int aux[MAX];
for(int i=0;i<MAX;i++) aux = i;
//Add your library sort algorithm here
//However instead of comparing arr[i] with arr[j], compare arr[aux[i]] with arr[aux[j]]
//Then, when you are going to insert sorted values, insert aux[pos], not arr[pos]
}
Here you have library sort pseudocode:
Rebalance(Array S, Integer iniLen, Integer finLen)
k = finLen-1
step = finLen/iniLen
for j=iniLen-1 to 0:
S[k] = S[j]
S[j] = NONE
k = k-step
end for
LibrarySort(Array A, Integer n, Float epsilon, Array S)
goal = 1
pos = 0
sLen = (Integer)(1+epsilon)*n
while pos<n://For each round do this:
for i=1 to goal://Insert 'goal' elements to the sorted array S
//Search a position to insert A[pos]
insPos = binarySearch(A[pos], S, sLen)
if not IS_EMPTY(S[insPos]):
//Move elements to the right or the left in order to free
//insPos
freeSpace(insPos, S, sLen)
end if
S[insPos] = A[pos]//Insert new element
pos = pos + 1
if pos>n://All elements have been inserted
return LibrarySort
end if
end for
prevLen = sLen
sLen = min( (2+2*epsilon)*goal, (1+epsilon)*n )
//Rebalance array S
Rebalance(S, prevLen, sLen)
goal = goal * 2
end while
Related
I have two arrays in my C++ code. array1 has all elements but array2 has the same elements but with a few missing. I am trying to find out the elements that are missing in array2. Instead of showing the missing elements, it is showing elements which are also present in both the arrays and multiple times.
string array1[] = { "aaa","bbb","ccc","ddd" };
string array2[] = { "aaa","bbb","ccc" };
for (i = 0; i <= 3; i++)
{
for (int j = 0; j <= 2; j++)
{
if (array1[i] == array2[j])
continue;
else
cout << array1[i] << endl;
}
}
'''
I tried using nested for loops to try to compare every element from array1 with all the elements of array2. If a match is found, the loop is supposed to skip and move on to the next iteration and if a match has not been found, it should display the element that was not found in array2.
You implemented the logic of your code a little bit wrong.
So, first iterate over all elements from array1.
Then, check, if the current element is in the array2. For this you can use a flag.
If it is not in, then print it.
There are even standard functions in the C++ algorithm library availabe.
But let's ge with the below solution:
#include <iostream>
#include <string>
using namespace std;
int main() {
string array1[] = { "aaa","bbb","ccc","ddd" };
string array2[] = { "aaa","bbb","ccc" };
for (int i = 0; i <= 3; i++)
{
bool isPresent = false;
for (int j = 0; j <= 2; j++)
if (array1[i] == array2[j])
isPresent = true;
if (not isPresent)
std::cout << array1[i] << '\n';
}
}
Completely new to C++. Programmed selection sort on 1D array of arbitrary length. Want to allow user to keep inputting integers into console to make an array of desired length, to be subsequently sorted.
Can only seem to make arrays of length 2 using a while loop for adding elements. Code and example of erroneous result when inputting 6, 2, 3, and 9 shown below.
Script:
// Preprocessor directives and namespace declaration
#include <iostream>
#include <vector>
using namespace std;
// Function
void SelectionSort(int *arr, int len)
{
// Loop through index j in arr
for (int j = 0; j < len; j++) {
// Assume element j is minimum, and initialise minIndex
int min = arr[j];
int minIndex = j;
// Loop through comparisons to determine actual minimum
// (of elements after and including j)
for (int i = j; i < len; i++)
{
if (min > arr[i])
{
min = arr[i];
minIndex = i;
}
}
// Swap minimum with element j
int temp = arr[j];
arr[j] = min;
arr[minIndex] = temp;
}
// Display resulting array
for (int i = 0; i + 1 < len; i++)
{
cout << arr[i] << ", ";
}
cout << arr[len - 1] << endl;
}
// Main
int main()
{
// Explain program to user
cout << "Sort 1D array of user-inputted length/contents" << endl;
cout << "To finish array, enter -999" << endl;
// Initialise dynamic array
vector<int> vDyn (1);
vDyn[0] = 0;
cout << "Enter first element of array: ";
int firstElement = 0;
cin >> firstElement;
vDyn[0] = firstElement;
// Loop to define elements until desired length reached
bool keepGoing = true;
while (keepGoing == true)
{
cout << "Enter another element: ";
int newElement = 0;
cin >> newElement;
if (newElement != -999)
{
vDyn.push_back(newElement);
} else
{
keepGoing = false;
}
}
// Convert vector to array (dynamic to static)
int* v = &vDyn[0];
// Get array length
int len = sizeof(v) / sizeof(v[0]);
// Run SelectionSort function
SelectionSort(v, len);
return 0;
}
Terminal:
Sort 1D array of user-inputted length/contents
To finish array, enter -999
Enter first element of array: 6
Enter another element: 2
Enter another element: 3
Enter another element: 9
Enter another element: -999
2, 6
This declaration
int len = sizeof(v) / sizeof(v[0]);
is equivalent to the declaration
int len = sizeof( int * ) / sizeof( int );
because the variable v is declared like
int* v = &vDyn[0];
The size of a pointer is equal usually to 4 or 8 bytes. So the variable length will have the value either 1 or 2 and does not depend on the number of elements stored in the vector..
Instead you should use for example
size_t len = vDyn.size();
You could declare the function like
void SelectionSort(int *arr, size_t len);
and call it like
SelectionSort( vDyn.data(), vDyn.size() );
Also as in C++ there is standard function std::swap declared in the header <utility> then instead of this code snippet
// Swap minimum with element j
int temp = arr[j];
arr[j] = min;
arr[minIndex] = temp;
you could just write
if ( j != minIndex ) std::swap( arr[j], arr[minIndex] );
And the inner for loop could look like
for ( size_t i = j + 1; i < len; i++)
^^^^^
In fact your function SelectionSort is a C function. A C++ function should be more general and use iterators. In this case it could sort arrays along with other containers.
Here is a demonstration program that shows a more general function called for an array based on a vector.
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
template <typename ForwardIterator>
void SelectionSort( ForwardIterator first, ForwardIterator last )
{
for ( ; first != last; ++first )
{
auto current_min = first;
for ( auto next = std::next( first ); next != last; ++next )
{
if ( *next < *current_min ) current_min = next;
}
if ( current_min != first )
{
std::iter_swap( current_min, first );
}
}
}
int main()
{
std::vector<int> v = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
for ( const auto &item : v )
{
std::cout << item << ' ';
}
std::cout << '\n';
SelectionSort( v.data(), v.data() + v.size() );
for ( const auto &item : v )
{
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
In general you need also to write an overloaded function that accepts also a comparison function.
// Convert vector to array (dynamic to static)
int* v = &vDyn[0];
This line doesn't convert the array to anything. You merely take address of the first element in the vector.
If you want to take an underlying c-array from std::vector you are supposed to use data property of it.
Also, since the array is decayed into a pointer, it no longer contains data of its size. You should rely on std::vector properties (i.e. std::vector::size) to pass this information forward
I am a C++ student. And I need to solve this problem: "Write a program that receives a number and an array of the size of the given number. The program must find all the duplicates of the given numbers, push-back them to a vector of repeating elements, and print the vector". The requirements are I'm only allowed to use the vector library and every repeating element of the array must be pushed to the vector only once, e.g. my array is "1, 2, 1, 2, 3, 4...", the vector must be "1 ,2".
Here's what I've done so far. My code works, but I'm unable to make it add the same duplicate to the vector of repeating elements only once.
#include <iostream>
#include <vector>
int main() {
int n;
std::cin >> n;
int* arr = new int[n];
std::vector<int> repeatedElements;
for(int i = 0; i < n; ++i) {
std::cin >> arr[i];
}
for(int i = 0; i < n; ++i) {
bool foundInRepeated = false;
for(int j = 0; j < repeatedElements.size(); ++j) {
if(arr[i] == repeatedElements[j]) {
foundInRepeated = true;
break;
}
}
if(foundInRepeated) {
continue;
} else {
for(int i = 0; i < n; ++i) {
int count = 1;
for(int j = i + 1; j < n; ++j) {
if(arr[i] == arr[j]) {
++count;
}
}
if(count > 1) {
repeatedElements.push_back(arr[i]);
}
}
}
}
for(int i = 0; i < repeatedElements.size(); ++i) {
std::cout << repeatedElements[i] << " ";
}
std::cout << std::endl;
}
Consider what you're doing here:
if(foundInRepeated) {
continue;
} else {
for(int i = 0; i < n; ++i) { // why?
If the element at some index i (from the outer loop) is not found in repeatedElements, you're again iterating through the entire array, and adding elements that are repeated. But you already have an i that you're interested in, and hasn't been added to the repeatedElements. You only need to iterate through j in the else branch.
Removing the line marked why? (and the closing brace), will solve the problem. Here's a demo.
It's always good to follow a plan. Divide the bigger problem into a sequence of smaller problems is a good start. While this often does not yield an optimal solution, at least it yields a solution, which is more or less straightforward. And which subsequently can be optimized, if need be.
How to find out, if a number in the sequence has duplicates?
We could brute force this:
is_duplicate i = arr[i+1..arr.size() - 1] contains arr[i]
and then write ourselves a helper function like
bool range_contains(std::vector<int>::const_iterator first,
std::vector<int>::const_iterator last, int value) {
// ...
}
and use it in a simple
for (auto iter = arr.cbegin(); iter != arr.cend(); ++iter) {
if (range_contains(iter+1, arr.cend(), *iter) && !duplicates.contains(*iter)) {
duplicates.push_back(*iter);
}
}
But this would be - if I am not mistaken - some O(N^2) solution.
As we know, sorting is O(N log(N)) and if we sort our array first, we will
have all duplicates right next to each other. Then, we can iterate over the sorted array once (O(N)) and we are still cheaper than O(N^2). (O(N log(N)) + O(N) is still O(N log(N))).
1 2 1 2 3 4 => sort => 1 1 2 2 3 4
Eventually, while using what we have at our disposal, this could yield to a program like this:
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
using IntVec = std::vector<int>;
int main(int argc, const char *argv[]) {
IntVec arr; // aka: input array
IntVec duplicates;
size_t n = 0;
std::cin >> n;
// Read n integers from std::cin
std::generate_n(std::back_inserter(arr), n,
[](){
return *(std::istream_iterator<int>(std::cin));
});
// sort the array (in ascending order).
std::sort(arr.begin(), arr.end()); // O(N*logN)
auto current = arr.cbegin();
while(current != arr.cend()) {
// std::adjacent_find() finds the next location in arr, where 2 neighbors have the same value.
current = std::adjacent_find(current,arr.cend());
if( current != arr.cend()) {
duplicates.push_back(*current);
// skip all duplicates here
for( ; current != (arr.cend() - 1) && (*current == *(current+1)); current++) {
}
}
}
// print the duplicates to std::cout
std::copy(duplicates.cbegin(), duplicates.cend(),
std::ostream_iterator<int>(std::cout, " "));
return 0;
}
I'm trying to delete all elements of an array that match a particular case.
for example..
if(ar[i]==0)
delete all elements which are 0 in the array
print out the number of elements of the remaining array after deletion
what i tried:
if (ar[i]==0)
{
x++;
}
b=N-x;
cout<<b<<endl;
this works only if i want to delete a single element every time and i can't figure out how to delete in my required case.
Im assuming that i need to traverse the array and select All instances of the element found and delete All instances of occurrences.
Instead of incrementing the 'x' variable only once for one occurence, is it possible to increment it a certain number of times for a certain number of occurrences?
edit(someone requested that i paste all of my code):
int N;
cin>>N;
int ar[N];
int i=0;
while (i<N) {
cin>>ar[i];
i++;
}//array was created and we looped through the array, inputting each element.
int a=0;
int b=N;
cout<<b; //this is for the first case (no element is deleted)
int x=0;
i=0; //now we need to subtract every other element from the array from this selected element.
while (i<N) {
if (a>ar[i]) { //we selected the smallest element.
a=ar[i];
}
i=0;
while (i<N) {
ar[i]=ar[i]-a;
i++;
//this is applied to every single element.
}
if (ar[i]==0) //in this particular case, we need to delete the ith element. fix this step.
{
x++;
}
b=N-x;
cout<<b<<endl;
i++;
}
return 0; }
the entire question is found here:
Cut-the-sticks
You could use the std::remove function.
I was going to write out an example to go with the link, but the example form the link is pretty much verbatim what I was going to post, so here's the example from the link:
// remove algorithm example
#include <iostream> // std::cout
#include <algorithm> // std::remove
int main () {
int myints[] = {10,20,30,30,20,10,10,20}; // 10 20 30 30 20 10 10 20
// bounds of range:
int* pbegin = myints; // ^
int* pend = myints+sizeof(myints)/sizeof(int); // ^ ^
pend = std::remove (pbegin, pend, 20); // 10 30 30 10 10 ? ? ?
// ^ ^
std::cout << "range contains:";
for (int* p=pbegin; p!=pend; ++p)
std::cout << ' ' << *p;
std::cout << '\n';
return 0;
}
Strictly speaking, the posted example code could be optimized to not need the pointers (especially if you're using any standard container types like a std::vector), and there's also the std::remove_if function which allows for additional parameters to be passed for more complex predicate logic.
To that however, you made mention of the Cut the sticks challenge, which I don't believe you actually need to make use of any remove functions (beyond normal container/array remove functionality). Instead, you could use something like the following code to 'cut' and 'remove' according to the conditions set in the challenge (i.e. cut X from stick, then remove if < 0 and print how many cuts made on each pass):
#include <iostream>
#include <vector>
int main () {
// this is just here to push some numbers on the vector (non-C++11)
int arr[] = {10,20,30,30,20,10,10,20}; // 8 entries
int arsz = sizeof(arr) / sizeof(int);
std::vector<int> vals;
for (int i = 0; i < arsz; ++i) { vals.push_back(arr[i]); }
std::vector<int>::iterator beg = vals.begin();
unsigned int cut_len = 2;
unsigned int cut = 0;
std::cout << cut_len << std::endl;
while (vals.size() > 0) {
cut = 0;
beg = vals.begin();
while (beg != vals.end()) {
*beg -= cut_len;
if (*beg <= 0) {
vals.erase(beg--);
++cut;
}
++beg;
}
std::cout << cut << std::endl;
}
return 0;
}
Hope that can help.
If you have no space bound try something like that,
lets array is A and number is number.
create a new array B
traverse full A and add element A[i] to B[j] only if A[i] != number
assign B to A
Now A have no number element and valid size is j.
Check this:
#define N 5
int main()
{
int ar[N] = {0,1,2,1,0};
int tar[N];
int keyEle = 0;
int newN = 0;
for(int i=0;i<N;i++){
if (ar[i] != keyEle) {
tar[newN] = ar[i];
newN++;
}
}
cout<<"Elements after deleteing key element 0: ";
for(int i=0;i<newN;i++){
ar[i] = tar[i];
cout << ar[i]<<"\t" ;
}
}
Unless there is a need to use ordinary int arrays, I'd suggest using either a std::vector or std::array, then using std::remove_if. See similar.
untested example (with c++11 lambda):
#include <algorithm>
#include <vector>
// ...
std::vector<int> arr;
// populate array somehow
arr.erase(
std::remove_if(arr.begin(), arr.end()
,[](int x){ return (x == 0); } )
, arr.end());
Solution to Cut the sticks problem:
#include <climits>
#include <iostream>
#include <vector>
using namespace std;
// Cuts the sticks by size of stick with minimum length.
void cut(vector<int> &arr) {
// Calculate length of smallest stick.
int min_length = INT_MAX;
for (size_t i = 0; i < arr.size(); i++)
{
if (min_length > arr[i])
min_length = arr[i];
}
// source_i: Index of stick in existing vector.
// target_i: Index of same stick in new vector.
size_t target_i = 0;
for (size_t source_i = 0; source_i < arr.size(); source_i++)
{
arr[source_i] -= min_length;
if (arr[source_i] > 0)
arr[target_i++] = arr[source_i];
}
// Remove superfluous elements from the vector.
arr.resize(target_i);
}
int main() {
// Read the input.
int n;
cin >> n;
vector<int> arr(n);
for (int arr_i = 0; arr_i < n; arr_i++) {
cin >> arr[arr_i];
}
// Loop until vector is non-empty.
do {
cout << arr.size() << endl;
cut(arr);
} while (!arr.empty());
return 0;
}
With a single loop:
if(condition)
{
for(loop through array)
{
if(array[i] == 0)
{
array[i] = array[i+1]; // Check if array[i+1] is not 0
print (array[i]);
}
else
{
print (array[i]);
}
}
}
I'm wondering if something is wrong with my code especially the vector implementation?
Well,I was just exposed to the use of vector yesterday by people here.
In my college,I only learnt array.So,the usage of vector is kinda new to me.
To my understanding,vector is basically a dynamic array.-Correct me if I were wrong
Well,so lets go with my code.I got the following error: "Vector subscript out of range" after inputting n value.
EDIT:Fixed my earlier issue.Thanks to #quantdev .Now I noticed that my values aren't sorted.
#include<iostream>
#include<vector>
using namespace std;
//Function prototype
void Insertion_sort(vector<int> AR, int n);
void random_store(int val, vector<int> &aVec);
int main()
{
int nvalue;
vector<int> int_vector;
cout << "How many numbers would you like to generate?\n";
cin >> nvalue;//get input from user
random_store(nvalue, int_vector);//pass user input into random() function
system("pause");
return 0;
}
void random_store(int val, vector<int> &aVec)//store randomly generated value
{
int num;//represent random integer output
for (int i = 0; i < val; i++)
{
aVec.push_back(rand() % val + 1);//push each generated value into vector
}
Insertion_sort(aVec,val);//Pass the vector into a function to perform sorting
cout << " \n The sorted array is as follows \n ";
for (int i = 1; i <= val; i++)//Print sorted array
{
cout << " \n Element " << i << " : " << aVec[i] << endl;//will loop from aVec 1st array till n value
}
}
void Insertion_sort(vector<int> AR, int n)//insertion sort function
{
int j, val;//iterate through entire list
for (int i = 1; i < n; i++)
{
val = AR[i];
j = i - 1;
while (j >= 0 && AR[j] > val){
AR[j + 1] = AR[j];
j = j - 1;
}
AR[j + 1] = val;
}
} // end of insertion sort function
The problem is that your vector contains val values, so indexes are in [0, val-1], but within this loop :
for (int i = 1; i <= val; i++)
The last iteration will try to access the element at index val+1, which is out of bounds (it also misses the first element, at index 0)
Change it to :
for (int i = 0; i < val; i++)
And since indexes are of type std::size_t :
for (std::size_t i = 0; i < val; i++)
Note:
Your sort function takes a vector by value, sorting a copy of the vector. You probably want to pass by reference instead :
void Insertion_sort(vector<int>& AR, int n)