Problems implementing a quicksort - c++

I'm trying to implement a quicksort and am having some trouble. Ultimately, the sort will alphabetize a string vector and in turn synchronize a second vector with it so they stay matched (which should be easy since it's just repeating the same line with a different vector argument.)
At first when I compiled and ran the program, it was just generating the same output as before. I realized that this was because when I declared the vectors I didn't use the object.member notation. I modified it, and now I'm getting a compiler error.
in function int main
in lookup_member, at cp/search.c:1288
Obviously, there's a problem when it's trying to look at the vectors, but I'm not sure what.
I got my implementation of the quicksort code from Quick Sort (MathBits.com).
I am not sure what's wrong. Here's the code.
#include "std_lib_facilities.h"
struct Name_pairs
{
vector<string>names;
vector<double>ages;
void quicksort(vector<string>& num, int top, int bottom);
void divide(vector<string>& array, int top, int bottom);
bool test();
string read_names();
double read_ages();
void print();
};
string Name_pairs::read_names()
{
string name;
cout << "Enter name: ";
cin >> name;
names.push_back(name);
return name;
}
double Name_pairs::read_ages()
{
double age;
cout << "Enter corresponding age: ";
cin >> age;
ages.push_back(age);
cout << endl;
return age;
}
int Name_pairs::divide(vector<string>& array, int top, int bottom)
{
string x = array[top];
int i = top-1;
int j = bottom-1;
string temp;
do{
do
{
j--;
} while(x>array[j]);
do
{
i++;
} while(x<array[i]);
if(i<j)
{
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
} while(i<j);
return j;
}
void Name_pairs::quicksort(vector<string>& num, int top, int bottom) // top is subscript of beginning of vector.
{
int middle;
if(top < bottom)
{
middle = divide(num, top, bottom);
quicksort(num, top, middle);
quicksort(num, middle+1, bottom);
}
return;
}
void Name_pairs::print()
{
for(int i = 0; i < (names.size()-1) && i < (ages.size()-1); ++i)
cout << names[i] << " , " << ages[i] << endl;
}
int main()
{
Name_pairs np;
vector<string>names;
vector<double>ages;
cout << "Enter names and ages. Use 0 to cancel.\n";
bool finished = false;
while(!finished){
finished = "0" == np.read_names();
finished = 0 == np.read_ages();
}
np.quicksort(names, 0, (names.size()-2));
np.print();
keep_window_open();
}

If you're trying to define additional vector variables within main, then the lines
np.vector<string>names; // error possibly here?
np.vector<double>ages;
Should be:
vector<string> names;
vector<double> ages;
You're redefining your struct members, or so it seems. But I don't see where you'd actually use those. Also, size() returns an unsigned variable of some sort, so you may need to cast it, or change the way you're comparing it to prevent compiler errors/warnings.
It's also worth noting, that if you want a couple more vectors declared within main() then it's good practice to name them something unique instead of having them share names with the struct members. Also, your main() doesn't have a return (needs to return int).

Get rid of the following lines in main() which are apparently causing your compiler to crash:
np.vector<string>names; // error possibly here?
np.vector<double>ages;
Then, a couple of your function definitions need to have their signatures changed:
int divide(vector<string>& array, int top, int bottom)
and
void quicksort(vector<string>& num, int top, int bottom)
need to change to
int Name_pairs::divide(vector<string>& array, int top, int bottom)
void Name_pairs::quicksort(vector<string>& num, int top, int bottom)
so they are seen as part of the Name_pairs struct instead of free functions.

I got it working. The final code: Pushes back data and sorts both in synchronization,
#include "std_lib_facilities.h"
struct Name_pairs
{
vector<string>names;
vector<double>ages;
void quicksort(vector<string>& num, vector<double>& num2, int top, int bottom);
int divide(vector<string>& array, vector<double>& array2, int top, int bottom);
bool test();
string read_names();
double read_ages();
void print();
};
string Name_pairs::read_names()
{
string name;
cout << "Enter name: ";
cin >> name;
names.push_back(name);
return name;
}
double Name_pairs::read_ages()
{
double age;
cout << "Enter corresponding age: ";
cin >> age;
ages.push_back(age);
cout << endl;
return age;
}
int Name_pairs::divide(vector<string>& array, vector<double>& array2, int top, int bottom)
{
string x = array[top];
int i = top-1;
int j = bottom+1;
string temp;
double temp2;
do{
do
{
j--;
} while(x<array[j]);
do
{
i++;
} while(x>array[i]);
if(i<j)
{
temp = array[i];
temp2 = array2[i];
array[i] = array[j];
array2[i] = array2[j];
array[j] = temp;
array2[j] = temp2;
}
} while(i<j);
return j;
}
void Name_pairs::quicksort(vector<string>& num, vector<double>& num2, int top, int bottom)
{
int middle;
if(top < bottom)
{
middle = divide(num, num2, top, bottom);
quicksort(num, num2, top, middle);
quicksort(num, num2, middle+1, bottom);
}
return;
}
void Name_pairs::print()
{
for (int i = 0; i < (names.size()-1) && i < (ages.size()-1); ++i)
cout << names[i] << " , " << ages[i] << endl;
}
int main(){
Name_pairs np;
cout << "Enter names and ages. Use 0 to cancel.\n";
bool finished = false;
while(!finished){
finished = "0" == np.read_names();
finished = 0 == np.read_ages();}
np.quicksort(np.names, np.ages, 0, (np.names.size()-2));
np.print();
keep_window_open();
}
(This was listed as an answer in the edits (to the original question) from the OP. It should have been posted as an answer, and I'm reposting it here.)

The following lines in main() should be deleted:
np.vector<string>names; // error possibly here?
np.vector<double>ages;
They already exist as part of instantiating Name_pairs.
Also, remove the parameter names from quicksort since it isn't really necessary and will make your code not function the way you think it should. The names you want to sort are members of Name_pairs. The ones you declared in main() are not the ones you read in with read_names().
EDIT: Actually, it might be easier for you if you declare a single vector with a struct that contains the age and name and sort that array. The entirety of your program implies that you want to sort the names and then print out each name with the associated age, but you only sort the name array.
EDIT2: And from the other answers, I think you need to learn more about how to declare member functions before you can fully solve this problem.

If you don't mind extra memory used but a little higher speed you could use a structure or pair in witch the int is the index in the second vector which you set before you sort.
Or if you don't actually need the vector operator[] and you can just iterate over the elements you could use a map.

Related

C++ beginner declaring a function involving array of structures

There is a few lines of my code that I would like to define as a function because I plan to use it multiple times. portion of code is as follows:
// loop within loop used to reorder with highest price at the top
for(i=0;i<x;i++){
for(t=i;t<x;t++){
if(f[i].price < f[t].price) {
temp = f[i].price;
f[i].price = f[t].price;
f[t].price = temp;
}
}
}
I hope to be able to enter new values for x and f each time I call the function. I have included all of my code below. If I'm unclear about my objective in anyway please feel free to ask. I apologize in advance for the improper terminology I am new to this. Thank you
#include <iostream>
using namespace std;
struct List
{
char name[10];
int price;
};
int main()
{
//x represents number of structures within array!
int x;
cout << "How many items would you like to list under the fruit menu?\n";
cin >> x;
//array of structures fruit
struct List f[x];
int i;
//input values into structure
for (i = 0; i < x; i++) {
cout << "\nEnter fruit name, and price.\n";
cin >> f[i].name;
cin >> f[i].price;
};
//variables for reordering
int temp;
int t;
// loop within loop used to reorder with highest price at the top
for(i=0;i<x;i++){
for(t=i;t<x;t++){
if(f[i].price < f[t].price) {
temp = f[i].price;
f[i].price = f[t].price;
f[t].price = temp;
}
}
}
//Output of menus
//fruit Menu
cout << "\n\nFruit Menu";
for (i = 0; i < x; i++) {
cout << "\n" << f[i].name << " $" << f[i]. price;
};
return 0;
}
I suppose it is an assignment that says "implement your own sort function for sorting an array of fruits", so I take the data structure "array of fruits" as given. You can, of course, change this to vector<struct Fruit> as well, but that's a different topic.
Maybe the following fragments help you finishing your code. It contains functions for entering, sorting, and printing the array with some samples how to deal with the parameters and the calls. You'll have to finalise the code.
Have fun!
#include <iostream>
using namespace std;
struct Fruit
{
char name[10];
int price;
};
// enter up to nrOfFruis; return number of fruits actually entered
int enterFruits(struct Fruit *fruits, int maxNrOfFruits) {
int entered = 0;
while (entered < maxNrOfFruits) {
cin >> fruits[entered].name;
entered++;
}
return entered;
}
void sortFruits(struct Fruit* fruits, int nrOfFruits) {
// your sort code goes here
// example for swaping two elements:
Fruit temp = fruits[0];
fruits[0] = fruits[1];
fruits[1] = temp;
}
void printFruits(struct Fruit *fruits, int nrOfFruits) {
cout << "\n\nFruit Menu";
for (int i = 0; i < nrOfFruits; i++) {
cout << "\n" << fruits[i].name << " $" << fruits[i]. price;
};
}
int main()
{
// Your task: put a proper loop and exit condition arround the following lines...
int x;
cout << "How many items would you like to list under the fruit menu?\n";
cin >> x;
struct Fruit fruits[x];
int entered = enterFruits(fruits, x);
sortFruits(fruits, entered);
printFruits(fruits, entered);
return 0;
}
You cannot allocate an array on the stack if you do not know it's size at compile time. Therefore, you need to dynamically allocate memory for it(you also need to remember to delete it):
//x represents number of structures within array!
int x;
cout << "How many items would you like to list under the fruit menu?\n";
cin >> x;
//array of structures fruit
struct List * f = new List[x];
//...
delete [] f;
Alternatively, you could do it the C++ way, using vector, having the vector elements on the stack:
int x;
std::cin>>x;
std::vector<A> v(x);
for( size_t i = 0; i < x; i++)
{
std::cin >> v[i].x;
}
If you just want to pass an array to a function you can do so like this:
void sortArray(struct List list[]);
void sortArray(struct List* list, int n); // n = size of array
may be better to just use std::vector or some other list container instead. :)
Sounds like you want a function that receives an array t and index x, and you want to mutate the array in the function?
C++ is "pass by value", so to mutate the array you have to have your function take a reference (or pointer) to the array so that you're mutating the original array and not a copy of it, so just have your function signature like this: func(T& t, int x) (assuming T is the type of array t).

ld returned 1 error exit status C++

I keep getting "undefined reference to 'x'" where x is the function prototypes. I have the functions mapped out but the main still needs work just fyi. I just want to fix the ld return error 1 before pressing on but I can't seem to pin point the issue.
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;
//Symbolic Constants
const int MAX=11;
//Function Prototypes
int buildQuizArray(int);
void printArray(string,int,int);
double calcQuizAverage(int,int);
void sortArray(int,int);
int main ()
{
int quizScores[MAX];
int compQuiz;
int tempArray[MAX];
int average;
compQuiz = buildQuizArray(quizScores[MAX]);
quizScores[MAX]=tempArray[MAX];
average = calcQuizAverage(quizScores[MAX], compQuiz);
cout<<endl<<"Your quiz average is "<<average<<endl;
printArray ("Quiz Scores", tempArray[MAX], compQuiz);
sortArray(tempArray[MAX], compQuiz);
}
int buildQuizArray(int quizArray[])
{
int numQuiz, input, a;
a=0;
numQuiz=1;
cout << "Enter your score for quiz "<<numQuiz<<" (-1 to quit): ";
cin >> input;
while (input != -1)
{
quizArray[a] = input;
a++;
numQuiz++;
cout<< "Enter your score for quiz "<<numQuiz<<" (-1 to quit): ";
cin >> input;
}
return a+1;
}
void printArray(string reportTitle, int quizArray[], int numberOfQuizzes)
{
int a;
cout<< reportTitle <<endl<<"-----------"<<endl;
for (a=0; a<numberOfQuizzes; a++)
{
cout<< "Quiz " << a <<": " << setw(2) <<quizArray[a] <<"/10"<<endl;
}
}
double calcQuizAverage(int quizArray[], int numberOfQuizzes)
{
int sum, lowSum, avg, a;
a = 0;
sum = 0;
lowSum = quizArray[0] + quizArray[1];
for (a=0; a< numberOfQuizzes; a++)
{
sum += quizArray[a];
}
if (numberOfQuizzes <= 2)
{
avg = sum / (10 * numberOfQuizzes) * 100;
}
else
{
(sum - lowSum) / (10 * (numberOfQuizzes - 2)) * 100;
}
return avg;
}
void sortArray(int quizArray[], int numberOfQuizzes)
{
int min, a, b, temp;
for (a=0; a<numberOfQuizzes; a++)
{
min = a;
}
for(b=a+1; b<numberOfQuizzes; a++)
{
if (quizArray[a] < quizArray[min])
{
min = b;
}
}
temp = quizArray[a];
quizArray[a]=quizArray[min];
quizArray[min]=temp;
}
You declare:
int buildQuizArray(int);
But you define:
int buildQuizArray(int quizArray[]) ...
int[] is not the same as int.
Also: You are passing an int to the functions when you call them, though; note that e.g. quizScores[MAX] is the MAXth element of quizScores and is an int, which is actually beyond the end of that array, and really isn't what you want to be doing.
If I had to guess how you got here I'd guess that you had just about everything right, but you had unknowingly declared your prototypes incorrectly (int instead of int[]), so you then tacked [MAX] on to the arrays you were passing to functions just to get it to compile, then ran into the inevitable linker problem that led you here. If that's what you did, it wasn't quite the right approach.
What you really mean to do is:
For your functions that take arrays, declare them properly:
int buildQuizArray (int[]);
Pass the array pointer itself to the function when calling it:
buildQuizArray(quizScores);
Leave your declarations as-is, they look fine (syntax-wise).

C++ Splitting an array into 2 separate arrays

I need to write a program that takes a given array and then splits it into two separate arrays with one array's elements being the positive elements of the main array and the other's elements being the negative elements of the main array.
After doing my best with the code, I got about a million lines of errors when trying to compile it. Is there a problem with how I am deleting the three dynamically allocated arrays? What huge error is preventing compiling?
Here is my code:
#include <iostream>
using namespace std;
void count(int ARRAY[], int SIZE, int& NEG, int& POS);
void split(int ARRAY[], int SIZE, int& NEG_ARRAY, int NEG, int& POS_ARRAY, int POS);
void print_array(int ARRAY[], int SIZE);
int main()
{
int SIZE(0);
int* ARRAY;
cout << "Enter number of elements: ";
cin >> SIZE ;
ARRAY = new int[SIZE];
int x(0);
int numEle(0);
cout << "Enter list: " << endl;
while (numEle < SIZE)
{
ARRAY[numEle] = x;
numEle++;
cin >> x;
}
int POS(0), NEG(0);
count(ARRAY, SIZE, NEG, POS);
int* NEG_ARRAY;
NEG_ARRAY = new int[NEG];
int* POS_ARRAY;
POS_ARRAY = new int[POS];
split(ARRAY, SIZE, NEG_ARRAY, NEG, POS_ARRAY, POS);
cout << "Negative elements: " << endl;
cout << print_array(NEG_ARRAY, NEG) << endl;
cout << "Non-negative elements: " << endl;
cout << print_array(POS_ARRAY, POS) << endl;
delete [] ARRAY;
delete [] NEG_ARRAY;
delete [] POS_ARRAY;
return 0;
}
void count(int ARRAY[], int SIZE, int& NEG, int& POS)
{
for (int x=0; x < SIZE; x++)
{
if (ARRAY[x] >= 0)
{
POS = POS + 1;
}
if (ARRAY[x] < 0)
{
NEG = NEG + 1;
}
}
}
void split(int ARRAY[], int SIZE, int& NEG_ARRAY, int NEG, int& POS_ARRAY, int POS)
{
NEG = POS = 0;
for (int x = 0; x < SIZE; x++)
{
if (ARRAY[x] < 0)
{
NEG_ARRAY[NEG++] = ARRAY[x];
}
else
{
POS_ARRAY[POS++] = ARRAY[x];
}
}
}
void print_array(int ARRAY[], int SIZE)
{
for (int i = 0; i < SIZE; i++)
{
cout << ARRAY[i] << " ";
}
cout << endl;
}
The code is supposed to read in the array and display a new negative and a new positive array. Thanks in advance!
There is a bunch of errors in your code. The worst one is passing the arrays by references in the declaration and definition of the split function. Change both to void split(int ARRAY[], int SIZE, int *NEG_ARRAY, int NEG, int *POS_ARRAY, int POS);, and most of the errors will be gone.
The rest is from the two lines in which you print the array in your main:
cout<<print_array(NEG_ARRAY, NEG) <<endl;
You don't want to print the function, you want to use the function to print inside it (which you do correctly). You need to change the calls to simply:
print_array(NEG_ARRAY, NEG);
And that'll make your code compile.
Hovewer there's one more error, which will make the whole app work in an improper way. In the place you input the values, you need to get the input from cin before inputting it in the array. Like this:
while(numEle<SIZE) {
cin>>x;
ARRAY[numEle] = x ;
numEle++;
}
You have the following bugs:
void split(int ARRAY[], int SIZE, int&NEG_ARRAY, int NEG, int&POS_ARRAY, int POS);
change to :
void split(int ARRAY[], int SIZE, int*NEG_ARRAY, int NEG, int*POS_ARRAY, int POS);
also the :
void split(int ARRAY[], int SIZE, int&NEG_ARRAY, int NEG, int&POS_ARRAY, int POS){..}
change to :
void split(int ARRAY[], int SIZE, int*NEG_ARRAY, int NEG, int*POS_ARRAY, int POS){..}
and
cout<<print_array(NEG_ARRAY, NEG) <<endl
cout<<print_array(NEG_ARRAY, POS) <<endl;
to :
print_array(NEG_ARRAY, NEG);
print_array(NEG_ARRAY, POS);
After fixed these bugs, it can compile and run well.
First of all, using a std::vector is almost always nicer than using dynamically allocated C arrays. You don't get the horrible mixture of pointers and square bracket array access, and you don't need to pass round extra size variables.
Secondly, the standard library has some nice algorithms to help do what you want to do. Let's assume that you write the given numbers into a vector called vec. You can then use std::partition to move all the elements less than zero to the first half of the vector, and all the elements greater than or equal to zero to the second half, like so:
inline bool less_than_zero(int a)
{
return a < 0;
}
std::vector<int>::iterator midpoint = std::partition(vec.begin(),
vec.end(),
less_than_zero);
(There are other ways of specifying the predicate, but a simple function definition like this is easiest for demonstration purposes.)
The returned iterator points to the first item in the vector which is non-negative. So now you can easily copy the values into two new vectors:
std::vector<int> negative(vec.begin(), midpoint);
std::vector<int> positive(midpoint, vec.end());
And that's it!

C++ Dynamic Array of Objects Sorting by Property

I'm trying to implement selection sort as a member function within class, to sort the objects of the class where the number of total players are being got by user input, also the names and scores of the players are being got by user too.
I'll sort the player objects by the property of their scores, which is a class member, being got by user input.
My problem is, i got stuck within the main where i can't call the class' member function sort for the array of objects.
class Player{
private:
string name;
int score;
public:
void setStatistics(string, int) // simple setter, not writing the whole function
void sortPrint(int, Player []);
int getScore(){ return score; }
void print(){ cout << name << " " << score << endl; }
};
void Player::sortPrint(int n, Player arr[]){
int i, j, minIndex;
Player tmp;
for (i = 0; i < n - 1; i++) {
int maxIndex = i;
for (j = i + 1; j < n; j++)
{
if (arr[j].getScore() > arr[minIndex].getScore())
{
minIndex = j;
}
}
if (minIndex != i) {
tmp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = tmp;
}
for(int i=0; i<n; i++){
arr[i].print(); // not sure with this too
}
}
};
int main(){
int n,score;
string name;
cout << "How many players ?" << endl;
cin >> n;
Player **players;
players = new Player*[n];
for(int i=0;i<n;i++) {
cout << "Player's name :" << endl;
cin >> name;
cout << "Player's total score:" << endl;
cin >> score;
players[i] = new Player;
players[i]->setStatistics(name,score);
}
for(int i=0; i<n;i++){
players->sortPrint(n, players); // error here, dont know how to do this part
}
// returning the memory here, didn't write this part too.
}
Try to replace void Player::sortPrint(int n, Player arr[]) with void Player::sortPrint(int n, Player*) and call function like players->sortPrint(n, *players)
Your problem is, that players is a pointer to array of Player, and arrays do not have member functions of the containees. As Player::sortPrint does not depend on the object itself, declare it as static and call it like Player::sortPrint(n, players);
Unless you have a very good reason not to, you should use std::sort rather than your own sorting algorithm. You should use a comparison function which compares the score of each player.
The following should work in C++03:
bool comparePlayerScores(const Player* a, const player* b)
{
return (a->getScore() < b->getScore());
}
// Returns the players sorted by score, in a new std::vector
std::vector<Player*> getSortedPlayers(Player **players, int num_players)
{
std::vector<Player*> players_copy(players, players + num_players);
std::sort(players_copy.begin(), players_copy.end(), comparePlayerScores);
return players_copy;
}
void printSorted(Player **players, int num_players)
{
std::vector<Player*> sorted_players = getSortedPlayers(players, num_players);
// Could use iterators here, omitting for brevity
for (int i = 0; i < num_players; i++) {
sorted_players[i]->print();
}
}
(Alternatively, you could define an operator< on your Player class which compares scores, which would let you store players in a std::set or std::map.)

Sorting with two vectors

I'm wondering if it's possible if you have, for example, a vector<string> and a vector<double> with corresponding pairs, to sort the vector<string> alphabetically while keeping the pairs matched up.
I know this can be done by creating a class that holds both values and just sorting that, but I'd rather keep two separate vectors.
Any ideas?
Final Code:
#include "std_lib_facilities.h"
struct Name_pairs
{
vector<string>names;
vector<double>ages;
void quicksort(vector<string>& num, vector<double>& num2, int top, int bottom);
int divide(vector<string>& array, vector<double>& array2, int top, int bottom);
bool test();
string read_names();
double read_ages();
void print();
};
string Name_pairs::read_names()
{
string name;
cout << "Enter name: ";
cin >> name;
names.push_back(name);
return name;
}
double Name_pairs::read_ages()
{
double age;
cout << "Enter corresponding age: ";
cin >> age;
ages.push_back(age);
cout << endl;
return age;
}
int Name_pairs::divide(vector<string>& array, vector<double>& array2, int top, int bottom)
{
string x = array[top];
int i = top-1;
int j = bottom+1;
string temp;
double temp2;
do{
do
{
j--;
}while(x<array[j]);
do
{
i++;
}while(x>array[i]);
if(i<j)
{
temp = array[i];
temp2 = array2[i];
array[i] = array[j];
array2[i] = array2[j];
array[j] = temp;
array2[j] = temp2;
}
}while(i<j);
return j;
}
void Name_pairs::quicksort(vector<string>& num, vector<double>& num2, int top, int bottom) // top is subscript of beginning of vector
{
int middle;
if(top < bottom)
{
middle = divide(num, num2, top, bottom);
quicksort(num, num2, top, middle);
quicksort(num, num2, middle+1, bottom);
}
return;
}
void Name_pairs::print()
{
for(int i = 0; i < (names.size()-1) && i < (ages.size()-1); ++i)
cout << names[i] << " , " << ages[i] << endl;
}
int main(){
Name_pairs np;
cout << "Enter names and ages. Use 0 to cancel.\n";
bool finished = false;
while(!finished){
finished = "0" == np.read_names();
finished = 0 == np.read_ages();}
np.quicksort(np.names, np.ages, 0, (np.names.size()-2));
np.print();
keep_window_open();}
If you manually sort them yourself, you can just swap the corresponding items in the double array along with the items in the string array that you would normally do. Or, you could have a third array:
vector<unsigned int> indices;
That just indexes into the string/double array, and sort that array instead (swapping based on the values in the string array).
You could create an auxiliary vector:
vector<unsigned int> indices;
Initialize it to to 0,1,2,...n-1, where n is the size of your vectors, and have the sort algorithm sort it using a functor that looks at the vector<string>, i.e., when asked to compare index1 and index2, the functor will look up the corresponding strings and compare them instead. Once you have indices sorted, you can easily sort your two arrays to conform to it in linear time.
Edit: I didn't see Jim Buck's second suggestion. My answer is just an expanded version of that.
Although the indices idea is effectively the same, you can in fact define a random access iterator type that knows the two vectors, and moves them (through assignment) in sync. The value_type of that iterator would be pair. In functional programming, you'd call this a "zip" (but not a zipper).
It's definitely not worth the hassle unless you're VERY tight on space. If you have the space, actually zipping the two vectors into a single vector of pairs, or using the indices approach, are both easier.
If you're able to get it right the first time, copy/pasting a 10 line quicksort with the obvious modifications will be the fastest way to what you want.
Ed's note: there is an already-written Zip Iterator available in Boost, as pointed out in this newer answer to the same question: "Locking" two vectors and sorting them
If you intend to use std::sort, you will need to use a datastructure like a pair.
You can, of course, manually sort the vectors, and essentially reimplement std::sort.
This question really depends on a great number of other questions, such as:
How many items will be in the vectors?
How critical is performance?
Do you REALLY want to implement your own sort algorithm?
Implementing a quicksort should be fairly painless, and will allow you to avoid moving the data around.