Returning unique() function in C++ - c++

I came across the following function, which sorts an array passed down by main(), removes duplicates, and returns the number of unique elements. It's the last bit I'm having a hard time wrapping my head around.
int reduce(long ar[], int n) {
sort(ar, ar + n);
return unique(ar, ar + n) - ar; // ???
}
To my understanding unique() returns a pointer to the end of the segment that stores the unique values in the array. But I don't see why subtracting the array name from the iterator results in an int that equals the number of unique elements, or why unique(ar, ar+n) can't be typecasted to int to achieve the same result.

why unique(ar, ar+n) can't be typecasted to int to achieve the same result.
Because, as you said, unique returns a pointer. A pointer is a memory address, not an index. So casting a pointer to an int is meaningless.
why subtracting the array name from the iterator results in an int that equals the number of unique elements
Subtracting two pointers (into the same array) evaluates to the number of elements between them.*
* As pointed out by #Nawaz in comments below, this result is signed. So (p1 - p2) == -(p2 - p1).

Say you have an array like this:
{1, 2, 2, 3, 4, 4, 5}
After calling std::unique, you'll probably end up with this (thank-you, Nawaz), with the elements past the new end left as they used to be before the call:
{1, 2, 3, 4, 5, 4, 5}
^
std::unique returns an iterator to the new end of the array, so where the arrow is. From there it makes logical sense that subtracting the beginning of the array would return the number of unique elements. If you want to be a bit more explicit, you can use return std::distance(ar, std::unique(ar, ar + n));, which also works when the iterator doesn't support subtraction.

Related

H­ow d­oes List::in­sert w­ork with a­rr­a­ys­

I am on youtube looking over tutorials. One had a block of code using the list library as such:
int arr1[5]{ 1,2,3,4,5 };
list<int> list1;
list1.insert(list1.begin(), arr1, arr1 + 5);
My question is, how can one use an array like this? Last I checked, arr1 is an array not a pointer that you use to loop through elements. How does the insert function work?
When an array is used by name, it's name references to first element of the array. For an array arr whenever you say arr[x], [] is defined in terms of pointers. It means start at a pointer referencing arr and move x steps ahead. A size of each step is the sizeof datatype your array is made up of. Thus,arr[x] can also be written as *(arr + x), dereferencing the pointer after x steps.
Now speaking of your list insertion, it means copy all the elements between pointers arr and arr + 5 to the list.
arr1 can be used as a pointer to the beginning of the array, because it gets converted automatically.

How do you delete an element from an array in C++? [duplicate]

How do I remove an element of an array and shift the remaining elements down. So, if I have an array,
array[]={1,2,3,4,5}
and want to delete 3 and shift the rest so I have,
array[]={1,2,4,5}
How would I go about this in the least amount of code?
You just need to overwrite what you're deleting with the next value in the array, propagate that change, and then keep in mind where the new end is:
int array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
// delete 3 (index 2)
for (int i = 2; i < 8; ++i)
array[i] = array[i + 1]; // copy next element left
Now your array is {1, 2, 4, 5, 6, 7, 8, 9, 9}. You cannot delete the extra 9 since this is a statically-sized array, you just have to ignore it. This can be done with std::copy:
std::copy(array + 3, // copy everything starting here
array + 9, // and ending here, not including it,
array + 2) // to this destination
In C++11, use can use std::move (the algorithm overload, not the utility overload) instead.
More generally, use std::remove to remove elements matching a value:
// remove *all* 3's, return new ending (remaining elements unspecified)
auto arrayEnd = std::remove(std::begin(array), std::end(array), 3);
Even more generally, there is std::remove_if.
Note that the use of std::vector<int> may be more appropriate here, as its a "true" dynamically-allocated resizing array. (In the sense that asking for its size() reflects removed elements.)
You can use memmove(), but you have to keep track of the array size yourself:
size_t array_size = 5;
int array[5] = {1, 2, 3, 4, 5};
// delete element at index 2
memmove(array + 2, array + 3, (array_size - 2 - 1) * sizeof(int));
array_size--;
In C++, though, it would be better to use a std::vector:
std::vector<int> array;
// initialize array...
// delete element at index 2
array.erase(array.begin() + 2);
std::copy does the job as far as moving elements is concerned:
#include <algorithm>
std::copy(array+3, array+5, array+2);
Note that the precondition for copy is that the destination must not be in the source range. It's permissible for the ranges to overlap.
Also, because of the way arrays work in C++, this doesn't "shorten" the array. It just shifts elements around within it. There is no way to change the size of an array, but if you're using a separate integer to track its "size" meaning the size of the part you care about, then you can of course decrement that.
So, the array you'll end up with will be as if it were initialized with:
int array[] = {1,2,4,5,5};
You can't achieve what you want with arrays. Use vectors instead, and read about the std::remove algorithm. Something like:
std::remove(array, array+5, 3)
will work on your array, but it will not shorten it (why -- because it's impossible). With vectors, it'd be something like
v.erase(std::remove(v.begin(), v.end(), 3), v.end())
Depending on your requirements, you may want to use stl lists for these types of operations. You can iterate through your list until you find the element, and erase the element. If you can't use lists, then you'll have to shift everything yourself, either by some sort of stl algorithm or manually.
If you are most concerned about code size and/or performance (also for WCET analysis, if you need one), I think this is probably going to be one of the more transparent solutions (for finding and removing elements):
unsigned int l=0, removed=0;
for( unsigned int i=0; i<count; i++ ) {
if( array[i] != to_remove )
array[l++] = array[i];
else
removed++;
}
count -= removed;
Just so it be noted: If the requirement to preserve the elements order is relaxed it is much more efficient to replace the element being removed with the last element.
Programming Hub randomly provided a code snippet which in fact does reduce the length of an array
for (i = position_to_remove; i < length_of_array; ++i) {
inputarray[i] = inputarray[i + 1];
}
Not sure if it's behaviour that was added only later. It does the trick though.
It reduces length indeed. However, if we speak about int arrays, there is a difference between length and size.
Size tells us about a capacity of a given array, how much we can store in it.
Length of an array tells us about how many items are there actually.
This question is bit old.
Try using standard library provided containers. These are designed by experts and very well tested. Moreover future developments of standard library algorithms are designed to suite these standard library containers.
If for some reason you have to stick to array, then try using std::array
std::array<int, 5> array = { 1,2,3,4,5 };
//std::remove - The elements that are not deleted are moved to the front of the array,
//and returns the iterator of the element from where it can be completely erased.
auto itr = std::remove(array.begin(), array.end(), 3);
//New array with new size
std::array<int,4> newArray;
std::copy(array.begin(), itr, newArray.begin());
The same thing can be done without using std::array also. But as said earlier for many other benifits prefer to go with std::array
int array[] = { 1,2,3,4,5 };
auto itr = std::remove(std::begin(array), std::end(array), 3);
int newArray[4];
std::copy(std::begin(array), itr, std::begin(newArray));

To delete multiple elements in array c++ with the shift [duplicate]

How do I remove an element of an array and shift the remaining elements down. So, if I have an array,
array[]={1,2,3,4,5}
and want to delete 3 and shift the rest so I have,
array[]={1,2,4,5}
How would I go about this in the least amount of code?
You just need to overwrite what you're deleting with the next value in the array, propagate that change, and then keep in mind where the new end is:
int array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
// delete 3 (index 2)
for (int i = 2; i < 8; ++i)
array[i] = array[i + 1]; // copy next element left
Now your array is {1, 2, 4, 5, 6, 7, 8, 9, 9}. You cannot delete the extra 9 since this is a statically-sized array, you just have to ignore it. This can be done with std::copy:
std::copy(array + 3, // copy everything starting here
array + 9, // and ending here, not including it,
array + 2) // to this destination
In C++11, use can use std::move (the algorithm overload, not the utility overload) instead.
More generally, use std::remove to remove elements matching a value:
// remove *all* 3's, return new ending (remaining elements unspecified)
auto arrayEnd = std::remove(std::begin(array), std::end(array), 3);
Even more generally, there is std::remove_if.
Note that the use of std::vector<int> may be more appropriate here, as its a "true" dynamically-allocated resizing array. (In the sense that asking for its size() reflects removed elements.)
You can use memmove(), but you have to keep track of the array size yourself:
size_t array_size = 5;
int array[5] = {1, 2, 3, 4, 5};
// delete element at index 2
memmove(array + 2, array + 3, (array_size - 2 - 1) * sizeof(int));
array_size--;
In C++, though, it would be better to use a std::vector:
std::vector<int> array;
// initialize array...
// delete element at index 2
array.erase(array.begin() + 2);
std::copy does the job as far as moving elements is concerned:
#include <algorithm>
std::copy(array+3, array+5, array+2);
Note that the precondition for copy is that the destination must not be in the source range. It's permissible for the ranges to overlap.
Also, because of the way arrays work in C++, this doesn't "shorten" the array. It just shifts elements around within it. There is no way to change the size of an array, but if you're using a separate integer to track its "size" meaning the size of the part you care about, then you can of course decrement that.
So, the array you'll end up with will be as if it were initialized with:
int array[] = {1,2,4,5,5};
You can't achieve what you want with arrays. Use vectors instead, and read about the std::remove algorithm. Something like:
std::remove(array, array+5, 3)
will work on your array, but it will not shorten it (why -- because it's impossible). With vectors, it'd be something like
v.erase(std::remove(v.begin(), v.end(), 3), v.end())
Depending on your requirements, you may want to use stl lists for these types of operations. You can iterate through your list until you find the element, and erase the element. If you can't use lists, then you'll have to shift everything yourself, either by some sort of stl algorithm or manually.
If you are most concerned about code size and/or performance (also for WCET analysis, if you need one), I think this is probably going to be one of the more transparent solutions (for finding and removing elements):
unsigned int l=0, removed=0;
for( unsigned int i=0; i<count; i++ ) {
if( array[i] != to_remove )
array[l++] = array[i];
else
removed++;
}
count -= removed;
Just so it be noted: If the requirement to preserve the elements order is relaxed it is much more efficient to replace the element being removed with the last element.
Programming Hub randomly provided a code snippet which in fact does reduce the length of an array
for (i = position_to_remove; i < length_of_array; ++i) {
inputarray[i] = inputarray[i + 1];
}
Not sure if it's behaviour that was added only later. It does the trick though.
It reduces length indeed. However, if we speak about int arrays, there is a difference between length and size.
Size tells us about a capacity of a given array, how much we can store in it.
Length of an array tells us about how many items are there actually.
This question is bit old.
Try using standard library provided containers. These are designed by experts and very well tested. Moreover future developments of standard library algorithms are designed to suite these standard library containers.
If for some reason you have to stick to array, then try using std::array
std::array<int, 5> array = { 1,2,3,4,5 };
//std::remove - The elements that are not deleted are moved to the front of the array,
//and returns the iterator of the element from where it can be completely erased.
auto itr = std::remove(array.begin(), array.end(), 3);
//New array with new size
std::array<int,4> newArray;
std::copy(array.begin(), itr, newArray.begin());
The same thing can be done without using std::array also. But as said earlier for many other benifits prefer to go with std::array
int array[] = { 1,2,3,4,5 };
auto itr = std::remove(std::begin(array), std::end(array), 3);
int newArray[4];
std::copy(std::begin(array), itr, std::begin(newArray));

Inserting a sub-array into a vector

The following statement inserts part of an array into an empty vector. It then prints the last elemnt inserted which is 14 in this case. My question is, how is the final array element that is inserted being determined with this syntax? How is "myArray+3" returning the third element in the array to the function?
vector <int> myVector(10);
int myArray[5] = {3,9,14,19,94};
myVector.insert(myVector.begin(), myArray, myArray+3);
cout << myVector.at(2) << endl;
For starters the vector is not empty. It has 10 elements initialized by zeroes.
vector <int> myVector(10);
As for these arguments
myArray, myArray+3
then they specify a range in the array the following way
[&myArray[0], &myArray[3])
^^^ ^^^
That means that the elements pointed to by these pointers
&myArray[0], &myArray[1], &myArray[2]
will be included in the vector. That is the second value of the range specifies elements before the value.
The element pointed to by the pointer &myArray[3] (that is by the pointer myArray + 3) will not be inserted to the vector.
Compare for example. If an array has N elements then the range of acceptable indices for its element is
[0, N-1]
^^^ ^^^
that can be also specified like
[0, N)
^^^ ^^^
Arrays in C++ are laid out in a contiguous fashion, so that the address of the array is the same as the address of the first element of the array, followed by the address of the next, and the next, etc.
Now when you do myArray + 3, this is actually saying, "Go to the first element and get the third element from the start position".
So if you had done (myArray + 1) + 3, this will mean to first from the first position to the second, and using your new position as a reference point, move three positions from there.
How does it know where to go? Simply by taking the size in bytes of a single element of the array and multiplying that by the distance you wanted to move forward, and then adding this value to the address of the reference position, and voila! You have gotten to the nth element of the array.

Simple Deque initialization question

I have used the following code to insert some data in a deque.
int data[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
deque<int> rawData (data, data + sizeof(data) / sizeof(int));
But I dont understand this part of the code,
data + sizeof(data) / sizeof(int)
What does it mean?
Let's take that bit by bit.
data is the iterator showing where to start. It's an array, but in C and C++ arrays decay to pointers on any provocation, so it's used as a pointer. Start taking in data from data on, and continue until the end iterator.
The end iterator is a certain amount past the start iterator, so it can be expressed as data + <something>, where <something> is the length. The start iterator is an int [] that is treated as an int *, so we want to find the length in ints. (In C and C++, pointers increment by the length of the pointed-to type.)
Therefore, sizeof(data) / sizeof(int) should be the length of the array. sizeof(data) is the total size of the array in bytes. (This is one of the differences between arrays and pointers: arrays have a defined size, while pointers point to what might be the start of an array of unknown size.) sizeof(int) is the total size of an int in bytes, and so the quotient is the total size of array in ints.
We want the size of array in ints because array decays into an int *, and so data + x points to the memory location x ints past data. From a beginning and a total size, we find the end of data, and so we copy everything in data from the beginning to the end.
That's a pointer to the imaginary element beyond the last element of the array. The sizeof(data)/sizeof(data[0]) yields the number of elements in data array. deque constructor accepts "iterator to the first element" and "iterator beyond the last element" (that's what end() iterator yields). This construct effectively computes the same as what .end() iterator would yield.