I want to erase the elements of a deque. When you have a deque that contain structs and you want to print the elements from back to front, but you don't want to print elements that have the same struct elements how do you do it?
I have a struct like this:
struct New_Array {
array<array<int,4>,4> mytable;
int h;
};
The deque is filled with elements from a previous procedure.
You want to print all the elements that are in the deque, but each table you print must have a unique "h". Only the first table you find with a specific "h" must be printed, the other tables with the same "h" should not be printed. I think this can be also inplemented with a "find" function.
The value of "h" that we will find starting from the back of the deque will be 0 and it will increase its value towards the front of the deque.
I have tried this:
void Find_Solution_Path(deque<New_Array> Mydeque)
{
while(Mydeque.size()>0)
{
New_Array y=Mydeque.back();
PrintBoard(y); //this is a function that prints the 4x4 array.
Mydeque.pop_back();
for(unsigned int i=0; i<Mydeque.size(); i++)
{
New_Array xxx=Mydeque[i];
if(xxx.h==y.h)
{
Mydeque.erase(Mydeque[i]);
}
}
}
}
I would not use a deque but a set. If you absolutely need the deque, create a set none the less. Define a < operator with an appropriate criterion < reflecting the uniqueness. You insert each printed element into the set. Before printing you check if the element is already present in the set (find).
HTH, Martin
One way is to use std::unique_copy.
#include <iostream>
#include <algorithm>
#include <iterator>
#include <deque>
struct New_Array {
array<array<int,4>,4> mytable;
int h;
// unique_copy needs this:
bool operator==(const New_Array& other) { return h == other.h; }
};
ostream& operator<<(ostream& out, const New_Array& v)
{
return out << v.h;
}
int main()
{
std::deque<New_Array> q;
New_Array temp;
// {1, 1, 2, 2, 3, 3}
temp.h = 1;
q.push_back(temp);
q.push_back(temp);
temp.h = 2;
q.push_back(temp);
q.push_back(temp);
temp.h = 3;
q.push_back(temp);
q.push_back(temp);
unique_copy(q.begin(), q.end(), ostream_iterator<New_Array>(cout, "\n"));
}
The range needs to be sorted for unique_copy to work properly. Sorting isn't needed in above case since we inserted elements in order.
I believe #Martin answer is probably the best solution. If you cannot change the signature for the function returning a deque, you can just construct a set from it and all the duplicates will automatically go away:
// First you need to declare a compare function for NewArray objects
struct NewArrayComp {
bool operator()(const NewArray& a1, const NewArray& a2) const {
return a1.h < a2.h;
}
};
// Then you can construct a set from the deque
deque<NewArray> dq;
// ...
std::set<NewArray, NewArrayComp> s(dq.begin(), dq.end());
// Finally you can just print the arrays (without duplicates)
for (const auto& a : s)
PrintBoard(a);
This solution has a O(n log n) complexity, while your code is O(n^2).
Additionally, if you do not want to pay the cost of duplicating the elements from the deque into the set you can use move semantics in C++11:
std::set<NewArray, NewArrayComp> s;
std::move(dq.begin(), dq.end(), std::inserter(s, s.begin()));
This will just move all the elements without making copies of them.
Related
To improve the readability, I'm trying to get out of the habit of reinventing the wheel.
Problem:
Consider a black-box function, Foo, which has an integer as input and output. We want to find the input that maximises the output. Consider that all the possible inputs belong to a single, contiguous range of integers; and that the range is small enough that we can try each one.
Speed is important, so we don't use containers. Even if the user has already created a container for all the possible inputs, it's still about 100x faster to calculate the next input (++input) than to get it from memory (cache misses).
Example:
Range: [5, 8)
Foo(5); // 19
Foo(6); // 72
Foo(7); // 31
We want to make a function that should return 6:
InputOfMaxOutputOnRange(5, 8, Foo); // 6
Custom solution:
template <typename T, typename Func>
T InputOfMaxOutputOnRange (T begin_range, T end_range, Func && Scorer)
{
// initialise:
auto max_o = Scorer(begin_range);
T i_of_max_o = begin_range;
// now consider the rest of the range:
++begin_range;
for (T i = begin_range; i < end_range; ++i)
{
auto output = Scorer(i);
if (max_o < output)
{
max_o = output;
i_of_max_o = i;
}
}
return i_of_max_o;
}
Question:
I use functions like this so often that I think there should be an STL way to do it. Is there?
C++20 ranges can do this:
template<typename T, typename F>
T argmax_iota(T begin, T end, F &&score) { // can't really think of a good name for this; maybe it doesn't even deserve its own function
return std::ranges::max(std::views::iota(begin, end), std::less{}, std::ref(score));
// over the values in the range [begin, end) produced by counting (iota)...
// find the one that produces the greatest value (max)...
// when passed to the projection function score...
// with those values under the ordering induced by std::less
}
Godbolt
iota does not store the whole range anywhere. Iterators into the range hold a single T value that is incremented when the iterator is incremented.
In general, the algorithms in the STL work on sequences of values, that are traversed by iterators. They tend to return iterators as well. That's the pattern that it uses.
If you're doing a lot of things like this, where your input "sequence" is a sequential list of numbers, then you're going to want an iterator that "iterates" over a sequence (w/o any storage behind it).
A little bit of searching turned up Boost.CountingIterator, which looks like it could do what you want. I'm confident that there are others like this as well.
Warning - completely untested code
auto iter = std::max_element(boost::counting_iterator<int>(5),
boost::counting_iterator<int>(8),
// a comparator that compares two elements
);
return *iter; // should be '6'
As others have observed, std::max_element is defined to get the largest element in a a range.
In your case, the "iterator" is an integer, and the result of dereferencing that iterator is...some result that isn't related to the input in an obvious (but apparently you have some way to getting it efficiently nonetheless).
This being the case, I'd probably define a specialized iterator class, and then use it with std::max_element:
#include <iostream>
#include <iterator>
#include <algorithm>
// your association function goes here. I've just done something
// where the relationship from input to output isn't necessarily
// immediately obvious
int association_function(int input) {
int a = input * 65537 + 17;
int b = a * a * a;
return b % 127;
}
class yourIterator {
int value;
public:
// create an iterator from an int value
explicit yourIterator(int value) : value(value) {}
// "Deference" the iterator (get the associated value)
int operator*() const { return association_function(value); }
// advance to the next value:
yourIterator operator++(int) {
yourIterator temp(value);
++value;
return temp;
}
yourIterator &operator++() {
++value;
return *this;
}
// compare to another iterator
bool operator==(yourIterator const& other) const { return value == other.value; }
bool operator!=(yourIterator const& other) const { return value != other.value; }
// get the index of the current iterator:
explicit operator int() const { return value; }
};
int main() {
// For demo, print out all the values in a particular range:
std::cout << "values in range: ";
std::copy(yourIterator(5), yourIterator(10), std::ostream_iterator<int>(std::cout, "\t"));
// Find the iterator that gives the largest value:
yourIterator max = std::max_element(yourIterator(5), yourIterator(10));
// print out the value and the index that gave it:
std::cout << "\nLargest element: " << *max << "\n";
std::cout << "index of largest element: " << static_cast<int>(max);
}
When I run this, I get output like this:
values in range: 64 90 105 60 33
Largest element: 105
index of largest element: 7
So, it seems to work correctly.
If you need to use this with a variety of different association functions, you'd probably want to pass that as a template parameter, to keep the iteration part decoupled from the association function.
// pass association as a template parameter
template <class Map>
class mappingIterator {
int value;
// create an instance of that type:
Map map;
public:
// use the instance to map from iterator to value:
int operator*() const { return map(value); }
Then you'd have to re-cast your association function into a form suitable for use as a template parameter, such as:
struct association_function {
int operator()(int input) const {
int a = input * 65537 + 17;
int b = a * a * a;
return b % 127;
}
};
Then in main you'd probably want to define a type for the iterator combined with an association function:
using It = mappingIterator<association_function>;
It max = std::max_element(It(5), It(10));
You can use std::max_element defined in <algorithm>.
This will return the iterator to the maximum element in a specified range. You can get the index using std::distance.
Example copied from cppreference.
std::vector<int> v{ 3, 1, -14, 1, 5, 9 };
std::vector<int>::iterator result;
result = std::max_element(v.begin(), v.end());
std::cout << "max element at: " << std::distance(v.begin(), result) << '\n';
I need to create a vector or similar list of pairs, where the first element of a pair is of class T, and the second element is a pointer to the next pair.
Illustration
template<class T>
std::vector<std::pair<T, T*>> createPointingVector(std::vector<T> vec) {
std::vector<std::pair<T, T*>> new_vec;
for (int i=0; i<vec.size(); i++){
new_vec.push_back(std::make_pair(vec[i], &(vec[i - 1])));
}
return new_vec;
}
I understand that std::vector<std::pair<T, T*>> is incorrect because the second element of the pair is not supposed to be of type *T but rather a recursive *std::pair<T, *std::pair<T, *std::pair<T, ...>>>.
Is it possible to fix my code or what are the other ways to achieve my goal, if any?
I strongly recommend rethinking using a bare vector.
My reason for that is that you need to guarantee that that the memory of the vector is never reallocated. Note that you also should in any case make sure that your vector is made sure to allocate all required memory from the start, either by initializing with empty elements or by using std::vector::reserve.
Otherwise, if you have a pointer already set and then change the capacity of the vector, the pointer becomes invalid, a good setup if you want undefined behaviour.
Therefore I strongly advise you to use a wrapper class around your vector, which makes sure no capacity change is ever called.
Now, if you do that, the thing is, why do you use actual pointers?
Consider using data of type std::vector<std::pair<T, size_t> >, with the second entry actually storing the position within the vector, rather than an actual pointer:
template<class T>
class PointingVector
{
public:
PointingVector(const std::vector<T>& vec);
private:
std::vector<std::pair<T, size_t> > data;
};
template<class T>
PointingVector<T>::PointingVector(const std::vector<T>& vec)
{
for (int i=0; i<vec.size()-1; i++)
{
data.push_back(std::make_pair(vec[i], i+1));
}
data.push_back(std::make_pair(vec.back(), 0)); // assuming that the last points to the first
}
After that, make sure that every additional method you add leaves the pointing consistent. Like should you write something similar to erase, make sure that all pairs are updated accordingly.
And the analogy to dereferencing is trivial:
template<class T>
std::pair<T, size_t>& PointingVector<T>::get(size_t index)
{
return data[index];
}
The important thing about my solution is that you can exclude possible bugs in regard to dangling pointers. Those are really bad, especially since they might not cause an error in test executions, given the nature of undefined behaviour. Worst thing in my solution is that the indices are wrong after calling a method that has a bug.
And if you want to introduce anything that changes the capacity of the vector, no problem, no need to redo any pointers. Just make sure the indices are changed accordingly. If you did this with pointers, your first step would probably be to create a list of indices anyway, so why not work with one directly.
Plus, as this solution has no (visible) pointers at all, you don't need to do any memory management.
Another solution: Ditch std::pair and define your own type:
template<class T>
struct Node
{
T data;
Node* next; // or a smart pointer type
Node(const T& data, Node* next) : data(data), next(next) {}
};
Then build up your vector like this:
template<class T>
std::vector<Node<T>*> createPointingVector(const std::vector<T>& vec)
{
std::vector<Node<T>*> new_vec;
for (int i=0; i<vec.size(); i++)
{
new_vec.push_back(new Node<T>(vec[i], nullptr));
}
for (int i=0; i<vec.size()-1; i++)
{
new_vec[i]->next = new_vec[i+1];
}
new_vec[vec.size()-1]->next = new_vec[0];
return new_vec;
}
Note that without smart pointers, you need to do memory management. I'd consider making next a weak_ptr<Node>, and have the vector be over shared_ptr<Node>. That way, the memory is automatically deallocated as soon as the vector gets deleted (assuming you have no other pointers active).
What you ask is doable, but according to the illustration found linked within your answer, the pointers should point one-up circularly inside the input vector, and not one-down, as is in your code example. What I mean is:
new_vec[0] = {vec[0], &vec[1]}
new_vec[1] = {vec[1], &vec[2]}
...
new_vec[N-1] = {vec[N-1], &vec[0]}
above, N = vec.size().
I attach a minimum working example:
#include <iostream>
#include <vector>
#include <utility> // std::pair, std::make_pair
template<class T>
std::vector<std::pair<T, T*> > createPointingVector(std::vector<T>& vec) { // important: make the parameter a reference
std::vector<std::pair<T, T*> > new_vec;
int vec_size = vec.size();
for (int i = 0; i < vec_size-1; i++)
new_vec.push_back( std::make_pair( vec[i], &(vec[i + 1]) ) ); // pointers assigned according to linked picture
new_vec.push_back( std::make_pair( vec[vec_size-1], &vec[0] ) );
return new_vec;
}
int main()
{
std::vector<int> input = {1,2,3,4};
std::vector<std::pair<int,int*> > sol = createPointingVector(input);
for (auto i : sol)
std::cout << i.first << " -> " << *(i.second) << std::endl;
return 0;
}
Is there container adaptor in std or Poco that allows to specify size of it and where I can push element and in case if it will be full new element will be added in place of older one (or will be added at the end but first element will be deleted and all rest elements will be moved on one position back).
For instance imagine that container with size = 3.
I am pushing 4 elements [1, 2, 3, 4] consequentially into it and as a result I am getting that container with [2, 3, 4] or [4, 2, 3].
the structure you're looking for is called a circular buffer. C++ doesn't offer a container that represents that kind of structure, but it can be written pretty easily when you use a vector as the underlaying container.
In order to get an idea of how to actually implement it, you could look here, where the OP asked about a similar structure, but operating on bools. The only difference between your problem and his is that you actually need a templated class, so it would look something like this:
template <typename T>
class circularBuffer {
vector<T> data;
unsigned int lastEntryPos;
// methods to access "data"
};
You could also add a second template parameter indicating the size of the underlaying vector, and set it in the constructor:
template <typename T, size_type size>
class circularBuffer {
// ...
circularBuffer(): data(size), lastEntryPos(0){};
};
you can use a container list or vector, then before insert element, check container's size, if meet the count, popup old element, then push new one.
each time, you can iterate list in reverse sequence to get the element as their insert sequence.
#include <iostream>
#include <string>
#include <list>
using namespace std;
int main()
{
list<int> q;
for(int m = 0; m < 10; m++)
{
if(q.size() < 3)
q.push_front(m);
else
{
q.pop_back();
q.push_front(m);
}
}
for(auto x = q.rbegin(); x != q.rend(); x++)
std::cout << *x;
return 0;
}
output 789
For example, let's say I want to pass the values (1,2),(2,3),(3,4), etc. into a function and have it return a list of numbers, whatever they may be, i.e. 1, 3, 5, 3, 6 after some operations. What is the best way to achieve this result in C++? After moving from python it seems a lot more difficult to do it here, any help?
In general, you would use the std::vector container and its method push_back. You can then return the vector (return it by value, don't bother allocating it dynamically since your compiler probably supports move-semantics).
std::vector<int> func(
const std::tuple<int, int>& a, const std::tuple <int, int>& b)
{
std::vector<int> ret;
ret.push_back(...);
ret.push_back(...);
return ret;
}
I'm not saying this is the best way but I think it is pretty good, also from the memory-copying prospective, note I avoid returning a vector (expensive since it invokes the operator= implicitly):
#include <vector>
using namespace std;
/**
* Meaningful example: takes a vector of tuples (pairs) values_in and returns in
* values_out the second elements of the tuple whose first element is less than 5
*/
void less_than_5(const vector<pair<int, int> >& values_in, vector<int>& values_out) {
// clean up the values_out
values_out.clear();
// do something with values_in
for (vector<pair<int, int> >::iterator iter = values_in.begin(); iter != values_in.end(); ++iter) {
if (iter->first < 5) {
values_out.push_back(iter->second);
}
}
// clean up the values_out (again just to be consistent :))
values_out.clear();
// do something with values_in (equivalent loop)
for (int i = 0; i < values_in.size(); ++i) {
if (values_in[i].first < 5) {
values_out.push_back(values_in[i].second);
}
}
// at this point values_out contains all second elements from values_in tuples whose
// first is less than 5
}
void function(const std::vector<std::pair<int,int>> &pairs,
std::vector<int> &output) {
/* ... */
}
I have an array of edges, which is defined as a C-style array of doubles, where every 4 doubles define an edge, like this:
double *p = ...;
printf("edge1: %lf %lf %lf %lf\n", p[0], p[1], p[2], p[3]);
printf("edge2: %lf %lf %lf %lf\n", p[4], p[5], p[6], p[7]);
So I want to use std::sort() to sort it by edge length. If it was a struct Edge { double x1, y1, x2, y2; }; Edge *p;, I would be good to go.
But in this case, the double array has a block size that is not expressed by the pointer type. qsort() allows you to explicitly specify the block size, but std::sort() infers the block-size by the pointer type.
For performance reasons (both memory-usage and CPU), let's say that it's undesirable to create new arrays, or transform the array somehow. For performance reasons again, let's say that we do want to use std::sort() instead of qsort().
Is it possible to call std::sort() without wasting a single CPU cycle on transforming the data?
Possible approach:
An obvious approach is to try to force-cast the pointer:
double *p = ...;
struct Edge { double arr[4]; };
Edge *p2 = reinterpret_cast<Edge*>(p);
std::sort(...);
But how do I make sure the data is aligned properly? Also, how do I make sure it will always be aligned properly on all platforms and architectures?
Or can I use a typedef double[4] Edge;?
How about having a reordering vector? You initialize vector with 1..N/L, pass std::sort a comparator that compares elements i1*L..i1*L+L to i2*L..i2*L+L, and when your vector is properly sorted, reorder the C array according to new order.
In response to comment: yes things get complicated, but it may just be good complication! Take a look here.
You can use a "stride iterator" for this. A "stride iterator" wraps another iterator and an integer step size. Here's a simple sketch:
template<typename Iter>
class stride_iterator
{
...
stride_iterator(Iter it, difference_type step = difference_type(1))
: it_(it), step_(step) {}
stride_iterator& operator++() {
std::advance(it_,step_);
return *this;
}
Iter base() const { return it_; }
difference_type step() const { return step_; }
...
private:
Iter it_;
difference_type step_;
};
Also, helper functions like these
template<typename Iter>
stride_iterator<Iter> make_stride_iter(
Iter it,
typename iterator_traits<Iter>::difference_type step)
{
return stride_iterator<Iter>(it,step);
}
template<typename Iter>
stride_iterator<Iter> make_stride_iter(
stride_iterator<Iter> it,
typename iterator_traits<Iter>::difference_type step)
{
return stride_iterator<Iter>(it.base(),it.step() * step);
}
should make it fairly easy to use stride iterators:
int array[N*L];
std::sort( make_stride_iter(array,L),
make_stride_iter(array,L)+N );
Implementing the iterator adapter all by yourself (with all operators) is probably not a good idea. As Matthieu pointed out, you can safe yourself a lot of typing if you make use of Boost's iterator adapter tools, for example.
Edit:
I just realized that this doesn't do what you wanted since std::sort will only exchange the first element of each block. I don't think there's an easy and portable solution for this. The problem I see is that swapping "elements" (your blocks) cannot be (easily) customized when using std::sort. You could possibly write your iterator to return a special reference type with a special swap function but I'm not sure whether the C++ standard guarantees that std::sort will use a swap function that is looked up via ADL. Your implementation may restrict it to std::swap.
I guess the best answer is still: "Just use qsort".
For the new question, we need to pass in sort() a kind of iterator that will not only let us compare the right things (i.e. will make sure to take 4 steps through our double[] each time instead of 1) but also swap the right things (i.e. swap 4 doubles instead of one).
We can accomplish both by simply reinterpreting our double array as if it were an array of 4 doubles. Doing this:
typedef double Edge[4];
doesn't work, since you can't assign an array, and swap will need to. But doing this:
typedef std::array<double, 4> Edge;
or, if not C++11:
struct Edge {
double vals[4];
};
satisfies both requirements. Thus:
void sort(double* begin, double* end) {
typedef std::array<double, 4> Edge;
Edge* edge_begin = reinterpret_cast<Edge*>(begin);
Edge* edge_end = reinterpret_cast<Edge*>(end);
std::sort(edge_begin, edge_end, compare_edges);
}
bool compare_edges(const Edge& lhs, const Edge& rhs) {
// to be implemented
}
If you're concerned about alignment, can always just assert that there's no extra padding:
static_assert(sizeof(Edge) == 4 * sizeof(double), "uh oh");
I don't remember exactly how to do this, but if you can fake anonymous functions, then you can make a comp(L) function that returns the version of comp for arrays of length L... that way L becomes a parameter, not a global, and you can use qsort. As others mentioned, except in the case where your array is already sorted, or backwards or something, qsort is going to be pretty much just as fast as any other algorithm. (there's a reason it's called quicksort after all...)
It's not part of any ANSI, ISO, or POSIX standard, but some systems provide the qsort_r() function, which allows you to pass an extra context parameter to the comparison function. You can then do something like this:
int comp(void *thunk, const void *a, const void *b)
{
int L = (int)thunk;
// compare a and b as you would normally with a qsort comparison function
}
qsort_r(array, N, sizeof(int) * L, (void *)L, comp);
Alternatively, if you don't have qsort_r, you can use the callback(3) package from the ffcall library to create closures at runtime. Example:
#include <callback.h>
void comp_base(void *data, va_alist alist)
{
va_start_int(alist); // return type will be int
int L = (int)data;
const void *a = va_arg_ptr(alist, const void*);
const void *b = va_arg_ptr(alist, const void*);
// Now that we know L, compare
int return_value = comp(a, b, L);
va_return_int(alist, return_value); // return return_value
}
...
// In a function somewhere
typedef int (*compare_func)(const void*, const void*);
// Create some closures with different L values
compare_func comp1 = (compare_func)alloc_callback(&comp_base, (void *)L1);
compare_func comp2 = (compare_func)alloc_callback(&comp_base, (void *)L2);
...
// Use comp1 & comp2, e.g. as parameters to qsort
...
free_callback(comp1);
free_callback(comp2);
Note that the callback library is threadsafe, since all parameters are passed on the stack or in registers. The library takes care of allocating memory, making sure that memory is executable, and flushing the instruction cache if necessary to allow dynamically generated code (that is, the closure) to be executed at runtime. It supposedly works on a large variety of systems, but it's also quite possible that it won't work on yours, either due to bugs or lack of implementation.
Also note that this adds a little bit of overhead to the function call. Each call to comp_base() above has to unpack its arguments from the list passed it (which is in a highly platform-dependent format) and stuff its return value back in. Most of the time, this overhead is miniscule, but for a comparison function where the actual work performed is very small and which will get called many, many times during a call to qsort(), the overhead is very significant.
std::array< std::array<int, L>, N > array;
// or std::vector< std::vector<int> > if N*L is not a constant
std::sort( array.begin(), array.end() );
I'm not sure if you can achieve the same result without a lot more work. std::sort() is made to sort sequences of elements defined by two random access iterators. Unfortunately, it determines the type of the element from the iterator. For example:
std::sort(&array[0], &array[N + L]);
will sort all of the elements of array. The problem is that it assumes that the subscripting, increment, decrement, and other indexing operators of the iterator step over elements of the sequence. I believe that the only way that you can sort slices of the array (I think that this is what you are after), is to write an iterator that indexes based on L. This is what sellibitze has done in the stride_iterator answer.
namespace
{
struct NewCompare
{
bool operator()( const int a, const int b ) const
{
return a < b;
}
};
}
std::sort(array+start,array+start+L,NewCompare);
Do test with std::stable_sort() on realistic data-sets - for some data mixes its substantially faster!
On many compilers (GCC iirc) there's a nasty bite: the std::sort() template asserts that the comparator is correct by testing it TWICE, once reversed, to ensure the result is reversed! This will absolutely completely kill performance for moderate datasets in normal builds. The solution is something like this:
#ifdef NDEBUG
#define WAS_NDEBUG
#undef NDEBUG
#endif
#define NDEBUG
#include <algorithm>
#ifdef WAS_NDEBUG
#undef WAS_NDEBUG
#else
#undef NDEBUG
#endif
Adapted from this excellent blog entry: http://www.tilander.org/aurora/2007/12/comparing-stdsort-and-qsort.html
Arkadiy has the right idea. You can sort in place if you create an array of pointers and sort that:
#define NN 7
#define LL 4
int array[NN*LL] = {
3, 5, 5, 5,
3, 6, 6, 6,
4, 4, 4, 4,
4, 3, 3, 3,
2, 2, 2, 2,
2, 0, 0, 0,
1, 1, 1, 1
};
struct IntPtrArrayComp {
int length;
IntPtrArrayComp(int len) : length(len) {}
bool operator()(int* const & a, int* const & b) {
for (int i = 0; i < length; ++i) {
if (a[i] < b[i]) return true;
else if (a[i] > b[i]) return false;
}
return false;
}
};
void sortArrayInPlace(int* array, int number, int length)
{
int** ptrs = new int*[number];
int** span = ptrs;
for (int* a = array; a < array+number*length; a+=length) {
*span++ = a;
}
std::sort(ptrs, ptrs+number, IntPtrArrayComp(length));
int* buf = new int[number];
for (int n = 0; n < number; ++n) {
int offset = (ptrs[n] - array)/length;
if (offset == n) continue;
// swap
int* a_n = array+n*length;
std::move(a_n, a_n+length, buf);
std::move(ptrs[n], ptrs[n]+length, a_n);
std::move(buf, buf+length, ptrs[n]);
// find what is pointing to a_n and point it
// to where the data was move to
int find = 0;
for (int i = n+1; i < number; ++i) {
if (ptrs[i] == a_n) {
find = i;
break;
}
}
ptrs[find] = ptrs[n];
}
delete[] buf;
delete[] ptrs;
}
int main()
{
for (int n = 0; n< NN; ++n) {
for (int l = 0; l < LL; ++l) {
std::cout << array[n*LL+l];
}
std::cout << std::endl;
}
std::cout << "----" << std::endl;
sortArrayInPlace(array, NN, LL);
for (int n = 0; n< NN; ++n) {
for (int l = 0; l < LL; ++l) {
std::cout << array[n*LL+l];
}
std::cout << std::endl;
}
return 0;
}
Output:
3555
3666
4444
4333
2222
2000
1111
----
1111
2000
2222
3555
3666
4333
4444
A lot of these answers seem like overkill. If you really have to do it C++ style, using jmucchiello's example:
template <int Length>
struct Block
{
int n_[Length];
bool operator <(Block const &rhs) const
{
for (int i(0); i < Length; ++i)
{
if (n_[i] < rhs.n_[i])
return true;
else if (n_[i] > rhs.n_[i])
return false;
}
return false;
}
};
and then sort with:
sort((Block<4> *)&array[0], (Block<4> *)&array[NN]);
It doesn't have to be any more complicated.