backtrack value which were chosen - c++

I have a c++ program which calculates maximum of a array provided no two consecutive elements of array can be taken.
For eg:
7 3 4 6 will result in a answer of 13 .Here we chose 7 and 6 for optimal maximum.
Here is my recursive program for it.
#include <iostream>
using namespace std;
int n;
int findMax(int x,int ar[])
{
if(x < n)
return max( ar[x]+findMax(x+2,ar), findMax(x+1,ar));
return 0;
}
int main(){
int ar[]={1,7,4,4,9,5,12};
n = sizeof(ar)/sizeof(ar[0]);
cout<<findMax(0,ar);
return 0;
}
However I am more interested in the indices of array which were chosen for this purpose by my program .How can I do that efficiently.
In the above program answer should be 1,4,6 as we chose 1st , 4th and 6th element of the array for the maximum.
Note: I am using 0 based indexing.
Thanks.

A recurrence relation R(k) for the maximum sum of the first k elements of the array (with no adjacent terms) is:
R(0) = 0, R(1) = max(0, a[0])
R(k) = max(a[k] + R(k-2), R(k-1))
This is almost the same recurrence you're using in your code, but in your code your function returns the maximum sum of elements k and later.
Anyway, you can build a table of these values in linear time using dynamic programming. In pseudocode:
R = new array of length n+1
R[0] = 0
R[1] = max(0, a[0])
for i = 2 .. n
R[i] = max(a[i-1] + R[i-2], R[i-1])
If you just want the maximum sum, you can return R[n]. But you can also reconstruct the indices easily. In pseudo-code:
indices(a, R):
result = new empty vector
i = n
while i > 0
if (i == 1 and a[0] > 0) or R[i] == a[i-1] + R[i-2]
result.push_back(i-1)
i -= 2
else
i -= 1
You'll have to reverse result to get the indices in increasing order.

This is definitely not the most effective solution but probably the one with least implementation effort:
#include <iostream>
#include <vector>
using namespace std;
int n;
pair<int, vector<int> > findMax(int x, int ar[])
{
if (x < n) {
pair<int, vector<int> > max1 = findMax(x + 2, ar);
const pair<int, vector<int> > max2 = findMax(x + 1, ar);
max1.first += ar[x];
max1.second.insert(max1.second.begin(), x);
return max1.first >= max2.first ? max1 : max2;
}
return make_pair(0, vector<int>());
}
ostream& operator<<(ostream &out, const vector<int> &vec)
{
const char *sep = "";
for (int value : vec) {
out << sep << value; sep = ", ";
}
return out;
}
int main()
{
int ar[]={1,7,4,4,9,5,12};
n = sizeof ar / sizeof *ar;
const pair<int, vector<int> > maxAr = findMax(0, ar);
cout << maxAr.first << '\n'
<< maxAr.second << '\n';
return 0;
}
Output:
28
1, 4, 6
Life demo on coliru
Thereby, the return value is extended with a std::vector<int> which holds the used indices beside of the current sum.
std::max() could be used if I would provide a suitable (overloadeded) operator<() for std::pair<int, std::vector<int> >. To not make things over-complicated, I just replaced std::max() by the resp. condition.

I think below code will satisfy your need.
#include<bits/stdc++.h>
using namespace std;
int n;
void findMax(int arr[], int in, pair< int, vector<int> > tempStore,
pair< int, vector<int> > &resStore) {
if(in >=n) {
if(resStore.first < tempStore.first) {
resStore.first = tempStore.first;
resStore.second = tempStore.second;
}
return;
}
findMax(arr, in+1, tempStore, resStore);
tempStore.first += arr[in];
tempStore.second.push_back(in);
findMax(arr, in+2, tempStore, resStore);
}
int main() {
int ar[]={1,7,4,4,9,5,12};
n = sizeof(ar)/sizeof(ar[0]);
pair< int, vector<int> > resStore, tempStore;
findMax(ar, 0,tempStore,resStore);
cout<<"Result Value: "<<resStore.first;
cout<<"\nResult Index:\n";
for(int i=0; i<resStore.second.size(); i++) {
cout<<resStore.second[i]<<" ";
}
return 0;
}

Related

How to find all possible combinations of adding two variables, each attached to a multiplier, summing up to a given number (cin)?

In my situation, a lorry has a capacity of 30, while a van has a capacity of 10. I need to find the number of vans/lorries needed to transport a given amount of cargo, say 100. I need to find all possible combinations of lorries + vans that will add up to 100.
The basic math calculation would be: (30*lorrycount) + (10*vancount) = n, where n is number of cargo.
Output Example
Cargo to be transported: 100
Number of Lorry: 0 3 2 1
Number of Van: 10 1 4 7
For example, the 2nd combination is 3 lorries, 1 van. Considering that lorries have capacity = 30 and van capacity = 10, (30*3)+(10*1) = 100 = n.
For now, we only have this code, which finds literally all combinations of numbers that add up to given number n, without considering the formula given above.
#include <iostream>
#include <vector>
using namespace std;
void findCombinationsUtil(int arr[], int index,
int num, int reducedNum)
{
int lorry_capacity = 30;
int van_capacity = 10;
// Base condition
if (reducedNum < 0)
return;
// If combination is found, print it
if (reducedNum == 0)
{
for (int i = 0; i < index; i++)
cout << arr[i] << " ";
cout << endl;
return;
}
// Find the previous number stored in arr[]
// It helps in maintaining increasing order
int prev = (index == 0) ? 1 : arr[index - 1];
// note loop starts from previous number
// i.e. at array location index - 1
for (int k = prev; k <= num; k++)
{
// next element of array is k
arr[index] = k;
// call recursively with reduced number
findCombinationsUtil(arr, index + 1, num,
reducedNum - k);
}
}
void findCombinations(int n)
{
// array to store the combinations
// It can contain max n elements
std::vector<int> arr(n); // allocate n elements
//find all combinations
findCombinationsUtil(&*arr.begin(), 0, n, n);
}
int main()
{
int n;
cout << "Enter the amount of cargo you want to transport: ";
cin >> n;
cout << endl;
//const int n = 10;
findCombinations(n);
return 0;
}
Do let me know if you have any solution to this, thank you.
An iterative way of finding all possible combinations
#include <iostream>
#include <vector>
int main()
{
int cw = 100;
int lw = 30, vw = 10;
int maxl = cw/lw; // maximum no. of lorries that can be there
std::vector<std::pair<int,int>> solutions;
// for the inclusive range of 0 to maxl, find the corresponding no. of vans for each variant of no of lorries
for(int l = 0; l<= maxl; ++l){
bool is_integer = (cw - l*lw)%vw == 0; // only if this is true, then there is an integer which satisfies for given l
if(is_integer){
int v = (cw-l*lw)/vw; // no of vans
solutions.push_back(std::make_pair(l,v));
}
}
for( auto& solution : solutions){
std::cout<<solution.first<<" lorries and "<< solution.second<<" vans" <<std::endl;
}
return 0;
}
We will create a recursive function that walks a global capacities array left to right and tries to load cargo into the various vehicle types. We keep track of how much we still have to load and pass that on to any recursive call. If we reach the end of the array, we produce a solution only if the remaining cargo is zero.
std::vector<int> capacities = { 30, 10 };
using Solution = std::vector<int>;
using Solutions = std::vector<Solution>;
void tryLoad(int remaining_cargo, int vehicle_index, Solution so_far, std::back_insert_iterator<Solutions>& solutions) {
if (vehicle_index == capacities.size()) {
if (remaining_cargo == 0) // we have a solution
*solutions++ = so_far;
return;
}
int capacity = capacities[vehicle_index];
for (int vehicles = 0; vehicles <= remaining_cargo / capacity; vehicles++) {
Solution new_solution = so_far;
new_solution.push_back(vehicles);
tryLoad(remaining_cargo - vehicles * capacity, vehicle_index + 1, new_solution, solutions);
}
}
Calling this as follows should produce the desired output in all_solutions:
Solutions all_solutions;
auto inserter = std::back_inserter(all_solutions)
tryLoad(100, 0, Solution{}, inserter);

Dijkstra shortest path algorithm error

I wrote the following code to implement the Dijkstra's shortest path algorithm:
#include <iostream>
#include <queue>
#include <utility>
#include <vector>
#include <functional>
#include <list>
#include <cstring>
int findPath(std::vector<std::list<std::pair<int, int>>> graph, int x, int y) {
int n = graph.size();
std::priority_queue < std::pair<int, int>, std::vector<std::pair<int, int>>, std::greater<std::pair<int, int>>> pq;
pq.push(std::pair<int, int>(0, x));
int *visited = new int[n + 1]{};
int *distance = new int[n + 1];
memset(distance, -1, sizeof(*distance) * (n + 1));
distance[x] = 0;
int current;
while (!pq.empty()) {
current = pq.top().second;
pq.pop();
if (current == y) {
return distance[y];
}
if (!visited[current]) {
visited[current] = 1;
for (std::list<std::pair<int, int>>::iterator it = graph[current].begin(); it != graph[current].end(); it++) {
if (!visited[it->first]) {
if (distance[it->first] == -1 || distance[it->first] > distance[current] + it->second) {
distance[it->first] = distance[current] + it->second;
pq.push(std::pair<int, int>(distance[it->first], it->first));
}
}
}
}
}
return distance[y];
}
int main()
{
std::ios::sync_with_stdio(false);
int n;
int m;
int x;
int y;
std::cin >> n >> m >> x >> y;
int a;
int b;
int c;
std::vector<std::list<std::pair<int, int>>> graph(n + 1);
for (int i = 0; i < m; ++i) {
std::cin >> a >> b >> c;
graph[a].push_back(std::pair<int, int>(b, c));
}
std::cout << findPath(graph, x, y) << std::endl;
return 0;
}
The input is N - number of vertexes, M - number of edges, x, y - 2 vertexes.
Then you have M lines of a, b, c which implies that you have a path from a to b with distance c.
Also you can have multiple edges from one vertex to another.
The goal is to find the shortest path from x to y. (-1 if there is no path)
I am using a priority queue of pairs (first one is the current distance to the vertex, and the second is the vertex).
The code works for some tests and gives a wrong answer for the rest (its from a judge system, so I can't see what the tests are).
I looked at it for an hour and I can't seem to find why it is not working.
I would be grateful if you can find the mistake, and why is it not working.
A sample input:
5 5 1 5
1 2 1
1 3 2
2 4 4
3 4 4
4 5 5
Output:
10
EDIT: There seems to be no error in the code. The task was ambiguous in the way that if there is a path from a to b, there is one from b to a. That was the error.

Remove repeated elements and give a Range Sum

I have a question regarding already asked this question:
SPOJ DQUERY : TLE Even With BIT?
What if I would like to not consider the repeated element to count when I make a range query?
following is an example:
Input
Line 1: n (1 ≤ n ≤ 10^6).
Line 2: n numbers a1, a2, ..., an (-10^9 ≤ ai ≤ ).
Line 3: q (1 ≤ q ≤ 10^6), the number of d-queries.
In the next q lines, each line contains 2 numbers i, j
representing a d-query (1 ≤ i ≤ j ≤ n).
Output
For each d-query (i, j), print the number of distinct elements in the
subsequence ai, ai+1, ..., aj in a single line.
Example
Input
9
1 2 3 2 4 1 2 3 4
3
1 9
2 4
5 9
2 7
Output
0 //Explanation: all elements have been repeated.
1 //Explanation: only 3 has not repeated.
3 //Explanation: only 4 is repeated, so count only 1, 2 and 3.
3 //Explanation: only 2 is repeated, so count only 3, 4 and 1.
what could it be the necessary changes which should have done in #kraskevich 's answer(which is an efficient solution for that particular case)? I tried to add 0 in BIT, instead of -1 in above-mentioned solution, which does not help for all types of queries. Can anybody get me an idea?
I finally made it using MOs Algorithm. Following will work as expected.
/** For the given set of queries find the Unique element
* count of an array using MO's Algorithum. */
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <unordered_map>
using namespace std;
struct Query // struct for storing the queries
{
int Left;
int Right;
int Index;
};
inline void Add(const int i, int &ans, vector<int> &Arr, vector<int> &countArray)
{
++countArray[Arr[i]];
if(countArray[Arr[i]] == 1)
ans += countArray[Arr[i]];
if(countArray[Arr[i]] == 2)
ans -= countArray[Arr[i]];
}
inline void Remove(const int i, int &ans, vector<int> &Arr, vector<int> &countArray)
{
--countArray[Arr[i]];
if(countArray[Arr[i]] == 1)
ans += countArray[Arr[i]];
if(countArray[Arr[i]] == 0)
ans -= countArray[Arr[i]];
}
int main()
{
int _size; cin >> _size;
vector<int> Arr; Arr.reserve(_size);
copy_n(istream_iterator<int>(cin), _size, back_inserter(Arr));
//copy(Arr.cbegin(), Arr.cend(), ostream_iterator<int>(cout, "\t"));
int id = -1;
int sqrt_n = sqrt(_size);
int Q; cin >> Q;
vector<Query> qArr(Q);
unordered_map<int, int> Map;
for (int i = 0; i < _size; ++i)
{
if (Map.count(Arr[i]) == 0)
Map[Arr[i]] = ++id;
Arr[i] = Map[Arr[i]];
}
// read queries
for (int i = 0; i < Q; ++i)
{
int L,R;
cin >> L >> R;
qArr[i].Left = L-1;
qArr[i].Right = R-1;
qArr[i].Index = i;
}
// sort the queries according to(MO's Algorithum)
sort(qArr.begin(),qArr.end(),
[&](const Query &lhs, const Query &rhs)->bool
{
return ( (lhs.Left/sqrt_n == rhs.Left/sqrt_n) ?
lhs.Right < rhs.Right: // Qs with same Left case
(lhs.Left / sqrt_n) < (rhs.Left / sqrt_n) ); // Qs with diff values case
});
int currStart = 0;
int currEnd = 0;
int tempAnswer= 0;
vector<int> Answer(Q);
vector<int> countArray(_size);
for (int i = 0; i < Q; ++i)
{
int L = qArr[i].Left;
int R = qArr[i].Right;
/** Remove extra elements of previous range. For
* example if previous range is [0, 3] and current
* range is [2, 5], then a[0] and a[1] are subtracted */
while (currStart < L)
{
Remove(currStart, tempAnswer, Arr, countArray);
++currStart;
}
/** Add Elements of current Range */
while (currStart > L)
{
Add(currStart - 1, tempAnswer, Arr, countArray);
--currStart;
}
while (currEnd <= R)
{
Add(currEnd, tempAnswer, Arr, countArray);
++currEnd;
}
/** Remove elements of previous range. For example
* when previous range is [0, 10] and current range
* is [3, 8], then a[9] and a[10] are subtracted */
while (currEnd > R + 1)
{
Remove(currEnd - 1, tempAnswer, Arr, countArray);
--currEnd;
}
Answer[qArr[i].Index] = tempAnswer;
}
for(const auto &it: Answer) cout<<it<<endl;
return 0;
}

Finding the lowest missing integer in a vector containing positive and negative int's?

I'm writing an operation to find the lowest missing element of a vector, V = 1..N + 1. This has to be performed in O(N) time complexity.
Solution One:
std::vector<int> A {3,4,1,4,6,7};
int main()
{
int max_el = *std::max_element(A.begin(), A.end()); //Find max element
std::vector<int> V(max_el);
std::iota(V.begin(), V.end(), 1) //Populate V with all int's up to max element
for(unsigned into i {0}; i < A.size(); i++)
{
int index = A[i] - 1;
if(A[i] == V[index]) //Search V in O(1)
{
V[index] = max_el; //Set each to max_el, leaving the missing int
}
}
return *std::min_element(V.begin(), V.end()); //Find missing int as its the lowest (hasn't been set to max_el)
}
//Output: 2
This works completely fine.
However, I'm now trying to get this to work with vector containing negative int's.
Solution Two:
My logic is to take the same approach, however 'weight' the indexes given the size of the vector and the number of negative int's in the vector:
std::vector<int> A {-1, -4, -2, 0, 3, 2, 1}
int main()
{
int max_el = *std::max_element(A.begin(), A.end());
int min_el = *std::min_element(A.begin(), A.end());
int min_el_abs = abs(min_el); //Convert min element to absolute
int total = min_el_abs + max_el;
std::vector<int> V(total + 1);
std::iota(V.begin(), V.end(), min_el);
int index;
//Find amount of negative int's
int first_pos;
for(unsigned int i {0}; i < A.size(); i++)
{
if(A[i] >= 0) {first_pos = i; break;}
}
for(unsigned int i {0}; i < A.size(); i++)
{
if(A[i] <= 0) //If negative
{
index = (A.size() - first_pos) - abs(A[i]);
} else
{
index = (A[i] + 1) + first_pos;
}
if(A[i] == V[index])
{
V[index] = 0;
}
}
return *std::min_element(V.begin(), V.end());
}
//Output: -3
Solution Two fails to compare the values of the two vectors (A and V), as calculating the index with the above methods with a positive int doesn't work.
1) How can I get my Solution 2 to work with unordered vector's of negative int's?
2) How can I edit my Solution 2 to work with vectors of positive as well as vectors with negative int's?
Your first solution seems O(max(N,M)), where I consider N the number of elements in vector A and M the size of vector V (or max(Ai)), but you are looping through both vectors multiple times (with std::min_element, std::max_element, the for loop, the allocation of V and std::iota too).
Besides, once corrected a couple of typos (a missing ; and an into instead of int), your program returns the value found... from main(), which is a bit odd.
Your first algorithm always searches for the lowest missing value in the range [1, max value in A], but it can be generalized to find the lowest missing element in the range [min(Ai), max(Ai)], even for negative numbers.
My approach is similar to that of L.Senioins, but I've used different library functions trying to minimize the number of loops.
#include <iostream>
#include <vector>
#include <utility>
#include <algorithm>
template <class ForwardIt>
typename std::iterator_traits<ForwardIt>::value_type
lowest_missing(ForwardIt first, ForwardIt last)
{
if ( first == last )
throw std::string {"The range is empty"};
// find both min and max element with one function
auto result = std::minmax_element(first, last);
// range is always > 0
auto range = *result.second - *result.first + 1;
if ( range < 2 )
throw std::string {"Min equals max, so there are no missing elements"};
std::vector<bool> vb(range); // the initial value of all elements is false
for (auto i = first; i != last; ++i)
vb[*i - *result.first] = true;
// search the first false
auto pos = std::find(vb.cbegin(), vb.cend(), false);
if ( pos == vb.cend() ) // all the elements are true
throw std::string {"There are no missing elements"};
return std::distance(vb.cbegin(), pos) + *result.first;
}
template <class ForwardIt>
void show_the_first_missing_element(ForwardIt first, ForwardIt last)
{
try
{
std::cout << lowest_missing(first, last) << '\n';
}
catch(const std::string &msg)
{
std::cout << msg << '\n';
}
}
int main() {
std::vector<int> a { 1, 8, 9, 6, 2, 5, 3, 0 };
show_the_first_missing_element(a.cbegin(), a.cend());
std::vector<int> b { -1, -4, 8, 1, -3, -2, 10, 0 };
show_the_first_missing_element(b.cbegin(), b.cend());
show_the_first_missing_element(b.cbegin() + b.size() / 2, b.cend());
std::vector<int> c { -2, -1, 0, 1, 2, 3 };
show_the_first_missing_element(c.cbegin(), c.cend());
std::vector<int> d { 3, 3, 3 };
show_the_first_missing_element(d.cbegin(), d.cend());
std::vector<int> e;
show_the_first_missing_element(e.cbegin(), e.cend());
return 0;
}
The results outputted for my test cases are:
4
2
-1
There are no missing elements
Min equals max, so there are no missing elements
The range is empty
My solution is to make a bool vector (or char vector just to avoid compilation warnings about casting to bool) which has the size of all possible elements. All elements are initialized to 0 and later are assigned to 1 which indicates that the element is not missing. All you need to do then is to find an index of the first 0 element which is the lowest missing element.
#include <vector>
#include <algorithm>
#include <iostream>
std::vector<int> A{ -1, 0, 11, 1, 10, -5 };
int main() {
if (A.size() > 1) {
int max_el = *std::max_element(A.begin(), A.end());
int min_el = *std::min_element(A.begin(), A.end());
int range = abs(max_el - min_el) + 1;
std::vector<int> V(range, 0);
for (size_t i = 0; i < A.size(); i++)
V[A[i] - min_el] = 1;
if (*std::min_element(V.begin(), V.end()) == 0)
std::cout << std::distance(V.begin(), std::find(V.begin(), V.end(), 0)) + min_el;
else
std::cout << "There are no missing elements" << std::endl;
}
else
std::cout << "There are no missing elements" << std::endl;
std::cin.get();
}
I'm going to try give my own question an answer, after spending sometime thinking about this:
int main()
{
std::vector<int> A {-3, -1, 0, 1, 3, 4};
auto relative_pos = std::minmax_elment(A.begin(), A.end());
std::vector<bool> Litmus( *(relative_pos.second) - *(relative_pos.first), false); //Create vector of size max val - min val)
auto lowest_val = *(relative_pos.first);
for(auto x : A)
{
Litmus[i - lowest_val] = true;
}
auto pos = std::find(Litmus.begin(), Litmus.end(), false); //Find the first occurring false value
std::cout<< (pos - Litmus.begin()) + lower<<std::endl; //Print the val in A relative to false value in Litmus
}
This solution works with negative numbers and is linear.
#include <vector>
#include <iostream>
#include <string>
#include <algorithm>
#include <numeric>
int solution(vector<int> &A) {
std::vector<int>::iterator it = std::max_element(A.begin(),A.end());
try
{
sort(A.begin(),A.end());
std::vector<int>::iterator it = std::unique(A.begin(),A.end());
A.resize(std::distance(A.begin(),it));
for(int i = 0, j = 1; i < A.size(); i++)
{
if( A[i] != j)
{
return j;
}
j++;
}
}
catch(exception &e)
{
std::cout<<e.what()<<std::endl;
}
return ++(*it);
}

How to make double sort integer arrays using C++?

I have 3-column integer arrays, whose last 2 elements are for sorting. For example
10 0 1
11 0 2
12 1 2
13 0 1
I want them to become:
10 0 1
13 0 1
11 0 2
12 1 2
The arrays are first sorted according to the 2nd column, and then again according to 3rd column.
I have over 3000 rows, so I need something also fast. How can you do this in c++?
Note: The array will be allocated dynamically using the following templates:
template <typename T>
T **AllocateDynamic2DArray(int nRows, int nCols){
T **dynamicArray;
dynamicArray = new T*[nRows];
for( int i = 0 ; i < nRows ; i++ ){
dynamicArray[i] = new T[nCols];
for ( int j=0; j<nCols;j++){
dynamicArray[i][j]= 0;
}
}
return dynamicArray;
}
in main,
int ** lineFilter = AllocateDynamic2DArray(2*numberOfLines,3);
you can use std::sort(); however, this is complicated by your array being 2D.
In general, std::sort() can't eat 2D arrays; you have to create a class to cast around the compiler warnings and complaints:
#include <iostream>
#include <algorithm>
int data[4][3] = {
{10,0,1},
{11,0,2},
{12,1,2},
{13,0,1}
};
struct row_t { // our type alias for sorting; we know this is compatible with the rows in data
int data[3];
bool operator<(const row_t& rhs) const {
return (data[1]<rhs.data[1]) || ((data[1]==rhs.data[1]) && (data[2]<rhs.data[2]));
}
};
int main() {
std::sort((row_t*)data,(row_t*)(data+4));
for(int i=0; i<4; i++)
std::cout << i << '=' << data[i][0] << ',' << data[i][1] << ',' << data[i][2] << ';' << std::endl;
return 0;
}
It becomes much easier if you use a std::vector to hold your items that really are of type row_t or such. Vectors are dynamically sized and sortable.
I think this should work:
template<typename T>
struct compareRows {
bool operator() (T * const & a, T * const & b) {
if (a[1] == b[1])
return a[2] < b[2];
else
return a[1] < b[1];
}
};
std::sort(dynamicArray, dynamicArray+nrows, compareRows<int>());
Use a functor to implement the comparison between the rows. The sort will take pointers to the beginning of each row and swap them according to the contents of the rows. The rows will stay in the same places in memory.
OK, the OP has a three-column integer arrays, which is not straightforward to sort, because you can't assign arrays.
One option is to have arrays of structs, where the struct contains one element for each column, write a custom compare routine and use std::sort.
Another option is to pretend we have such an array of structs and employ the evilness of reinterpret_cast, like below:
#include <algorithm>
#include <iostream>
struct elt_t
{
int e0;
int e1;
int e2;
};
int
compare (const elt_t &a, const elt_t &b)
{
if (a.e1 == b.e1)
return a.e2 < b.e2;
else
return a.e1 < b.e1;
}
int a [10][3] =
{
{ 10, 0, 1 },
{ 11, 0, 2 },
{ 12, 1, 2 },
{ 13, 0, 1 }
};
int
main ()
{
std::sort (reinterpret_cast<elt_t *>(&a[0]),
reinterpret_cast<elt_t *>(&a[4]), compare);
int i, j;
for (i = 0; i < 4; ++i)
std::cout << a [i][0] << ", " << a [i][1] << ", " << a [i][2] << std::endl;
return 0;
}
Of course, whether or not this is standards compliant is highly debatable :)
EDIT:
With the added requirement for the matrix to by dynamically allocated, you can use an array of std::vector, or a vector of std::vector:
#include <algorithm>
#include <iostream>
#include <vector>
int
compare (const std::vector<int> &a, const std::vector<int> &b)
{
if (a[1] == b[1])
return a[2] < b[2];
else
return a[1] < b[1];
}
std::vector<int> *
make_vec (unsigned int r, unsigned int c)
{
std::vector<int> *v = new std::vector<int> [r];
/* Don't care for column count for the purposes of the example. */
v [0].push_back (10); v [0].push_back (0); v [0].push_back (1);
v [1].push_back (11); v [1].push_back (0); v [1].push_back (2);
v [2].push_back (12); v [2].push_back (1); v [2].push_back (2);
v [3].push_back (13); v [3].push_back (0); v [3].push_back (1);
return v;
}
int
main ()
{
std::vector<int> *v = make_vec (4, 3);
std::sort (&v[0], &v[4], compare);
int i, j;
for (i = 0; i < 4; ++i)
std::cout << v[i][0] << ", " << v [i][1] << ", " << v [i][2] << std::endl;
delete [] v;
return 0;
}
use this for the second column and then for the third. Now it works for single dim arrays
int *toplace(int *start, int *end)
{
int *i = start+1, *j= end-1;
while(i<=j)
{
while(*i<=*start && i<=j) {i++;}
while(*j>=*start && i<=j) {j--;}
if (i<j) std::swap(*i++,*j--);
}
std::swap(*start,*(i-1));
return i-1;
}
void quicksort(int *start, int *end)
{
if (start >= end) return;
int *temp = start;
temp = toplace(start,end);
quicksort(start,temp);
quicksort(temp+1,end);
}
You can do this using the bubble sort algorithm (http://en.wikipedia.org/wiki/Bubble_sort)
Basically iterate through all records, comparing the current record, with the next. If the current record's 2nd column is higher then swap these records. If the current record's 2nd column is equal but the 3rd column is higher, then swap also.
Continue iterating until no more swaps are made.
To use your example:
10 0 1
11 0 2
12 1 2 (swap with next)
13 0 1
10 0 1
11 0 2(swap with next)
13 0 1
12 1 2
10 0 1
13 0 1
11 0 2
12 1 2
And done!