为对象向量实现快速排序算法

Implementing a quicksort algorithm for a vector of objects

本文关键字:快速排序 算法 实现 向量 对象      更新时间:2023-10-16

我被分配了一项任务,在我的C++程序中实现快速排序算法。家庭作业是从对象和继承开始的系列的一部分,但我们的讲师并没有真正向我们解释快速排序。

但是,我真的无法理解如何选择要排序的对象的向量以及如何设置下限和上限。

这是代码

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
#include <functional>
using namespace std;
template <typename T> T AskFor(string text) {
  cout << text << endl;
  T result;
  cin >> result;
  cin.clear();
  return result;
}
class Vehicle {
public:
  Vehicle(string producer, string model, int year)
    : model(model) {
      setProducer(producer);
      setYear(year);
  }
  void output() {
    cout << "  producer(vehicle): " << producer << endl;
    cout << "  model(vehicle): " << model << endl;
    cout << "  year(vehicle): " << year << endl;
  }
  void setProducer(const string producer) {
    if (isProducerValid(producer)) {
      this->producer = producer;
    }
  }
  string getProducer() const {
    return producer;
  }
  void setModel(const string model) {
    this->model = model;
  }
  string getModel() const {
    return model;
  }
  void setYear(const int year) {
    if (isYearValid(year)) {
      this->year = year;
    }
  }
  int getYear() const {
    return year;
  }
  static bool isYearValid(int year) {
    return year >= 1950 && year <= 2016;
  }
  static bool isProducerValid(string producer) {
    static string PRODUCERS[] { "Toyota", "Audi", "BMW", "Mercedes" };
    return find(begin(PRODUCERS), end(PRODUCERS), producer) != end(PRODUCERS);
  }
private:
  string producer;
  string model;
  int year;
};
class Vendor {
public:
    Vendor(string v_name, string address, string phone, vector<string> delivery)
        : v_name(v_name),
        address(address),
        delivery(delivery) {
        setPhone(phone);
    }
    void setVendorName(const string v_name) {
        this->v_name = v_name;
    }
    string getVendorName() const {
        return v_name;
    }
    void setAddress(const string address) {
        this->address = address;
    }
    string getAddress() const {
        return address;
    }
    void setPhone(const string phone) {
        this->phone = phone;
    }
    string getPhone() const {
        return phone;
    }
    void setDelivery(const vector<string> delivery) {
        this->delivery = delivery;
    }
    vector<string> getDelivery() const {
        return delivery;
    }
    static bool isPhoneNumber(string phone) {
        if (phone.empty()) {
            return false;
        }
        return all_of(begin(phone), end(phone), isdigit);
    }
private:
    string v_name;
    string address;
    string phone;
    vector<string> delivery;
};
class SparePart {
public:
  SparePart(string id, string name, Vehicle* v, int price, int time_to_replace,
            bool is_new = true, string description = "", string manual = "")
    : id(id),
      name(name),
      vehicle(v),
      price(price),
      time_to_replace(time_to_replace),
      is_new(is_new),
      description(description),
      manual(manual) {}
  double replacementPrice() {
    return price + time_to_replace * 20;
  }
  int warranty() const {
    return is_new ? 36 : 3;
  }
  virtual void output() {
    cout << "  ID: " << id << endl;
    cout << "  name: " << name << endl;
    vehicle->output();
    if (is_new) cout << "  new" << endl; 
    else {
      cout << "  recycled" << endl;
    }
    cout << "  description: " << description << endl;
    cout << "  manual: " << manual << endl;
  }
  virtual ~SparePart() = 0;
  void setId(const string id) {
    this->id = id;
  }
  string getId() const {
    return id;
  }
  void setName(const string name) {
    this->name = name;
  }
  string getName() const {
    return name;
  }
  void setDescription(const string description) {
    this->description = description;
  }
  string getDescription() const {
    return description;
  }
  void setManual(const string manual) {
    this->manual = manual;
  }
  string getManual() const {
    return manual;
  }
  void setPrice(const double price) {
    this->price = price;
  }
  double getPrice() const {
    return price;
  }
  void setIsNew(const bool is_new) {
     this->is_new = is_new;
  }
  void setTimeToReplace(const int time_to_replace) {
    this->time_to_replace = time_to_replace;
  }
  int getTimeToReplace() const {
    return time_to_replace;
  }
private:
  string id;
  string name;
  string description;
  string manual;
  double price;
  bool is_new;
  int time_to_replace;
  Vehicle* vehicle;
};
class AvailableSparePart : public SparePart {
public:
  AvailableSparePart(string id, string name, Vehicle* v, int price, int time_to_replace,
    int quantity, string location, bool is_new = true, string description = "", string manual = "")
    : SparePart(id, name, v, price, time_to_replace, is_new, description, manual),
      quantity(quantity),
      location(location) {}
  double price() {
    return replacementPrice();
  }
  int time() {
    return getTimeToReplace();
  }
  void output() {
    cout << "Available Spare Part" << endl;
    SparePart::output();
    cout << "  time: " << time() << endl;
    cout << "  price: " << price() << endl;
  }
  void setQuantity(const int quantity) {
    this->quantity = quantity;
  }
  int getQuantity() const {
    return quantity;
  }
  void setLocation(const string location) {
    this->location = location;
  }
  string getLocation() const {
    return location;
  }
private:
  int quantity;
  string location;
};
class ContractedSparePart : public SparePart {
public:
  ContractedSparePart(string id, string name, Vehicle* v, int price, int time_to_replace,
    int delivery_time, double delivery_price, Vendor* vendor, bool is_new = true,
    string description = "", string manual = "")
    : SparePart(id, name, v, price, time_to_replace, is_new, description, manual),
      delivery_time(delivery_time),
      delivery_price(delivery_price),
      vendor(vendor) {}
  double price() {
    return replacementPrice();
  }
  int time() {
    return getTimeToReplace() + delivery_time;
  }
  void output() {
    cout << "Contracted Spare Part" << endl;
    SparePart::output();
    cout << "  time: " << time() << endl;
    cout << "  price: " << price() << endl;
  }
  void setDeliveryTime(const int delivery_time) {
    this->delivery_time = delivery_time;
  }
  int getDeliveryTime() const {
    return delivery_time;
  }
  void setDeliveryPrive(const double delivery_price) {
    this->delivery_price = delivery_price;
  }
  double getDeliveryPrice() const {
    return delivery_price;
  }
private:
  Vendor* vendor;
  int delivery_time;
  double delivery_price;
};
enum class Action {
  ADD_VEHICLE,
  ADD_VENDOR,
  ADD_PART,
  ADD_PART_QUANTITY,
  LIST_PARTS,
  CALCULATE_COST,
  EXIT
};
Action menu() {
  string prompt = "Choose an option:n"
                  "1. Add a new vehiclen"
                  "2. Add a new vendorn"
                  "3. Add a new spare partn"
                  "4. Add part quantityn"
                  "5. List spare partsn"
                  "6. Calculate the cost of replacementn"
                  "7. Exit";
  while (true) {
    switch (AskFor<int>(prompt)) {
    case 1:
      return Action::ADD_VEHICLE; break;
    case 2:
      return Action::ADD_VENDOR; break;
    case 3:
      return Action::ADD_PART; break;
    case 4: 
      return Action::ADD_PART_QUANTITY; break;
    case 5:
      return Action::LIST_PARTS; break;
    case 6:
      return Action::CALCULATE_COST; break;
    case 7:
      return Action::EXIT; break;
    default:
      cout << "Please enter a number between 1 and 6" << endl;
    }
  }
}
struct PartAndNumber {
  PartAndNumber(SparePart* part, int number)
    : part(part), number(number) {}
  SparePart* part;
  int number;
};
void add_vehicle(vector<Vehicle*>& vehicles);
void add_vendor(vector < Vendor*>& vendors);
void add_part(vector<PartAndNumber*>& parts, const vector<Vehicle*>& vehicles, const vector<Vendor*>& vendors);
void add_available_part(vector<PartAndNumber*>& parts, Vehicle* vehicle);
void add_contracted_part(vector<PartAndNumber*>& parts, Vehicle* vehicle, const vector<Vendor*>& vendors);
void add_part_number(vector<PartAndNumber*>& parts);
void list_parts(const vector<PartAndNumber*>& parts);
void calculate_cost(const vector<PartAndNumber*>& parts);
int main() {
  vector<Vehicle*> vehicles;
  vector<PartAndNumber*> parts;
  vector<Vendor*> vendors;
  while (true) {
    Action action = menu();
    switch (action) {
    case Action::ADD_VEHICLE:
      add_vehicle(vehicles);
      break;
    case Action::ADD_VENDOR:
      add_vendor(vendors);
      break;
    case Action::ADD_PART:
      add_part(parts,vehicles,vendors);
      break;
    case Action::ADD_PART_QUANTITY:
      add_part_number(parts);
      break;
    case Action::LIST_PARTS:
      list_parts(parts);
      break;
    case Action::CALCULATE_COST:
      calculate_cost(parts);
      break;
    case Action::EXIT:
      return 0;
    }
  }
}
void add_vehicle(vector<Vehicle*>& vehicles) {
  string producer;
  while (true) {
    producer = AskFor<string>("New vehicle (producer): ");
    if (Vehicle::isProducerValid(producer)) {
      break;
    }
    cout << "Producer name is invalid. Try again." << endl;
  }
  string model = AskFor<string>("New vehicle (model):");
  int year;
  while (true) {
    year = AskFor<int>("New vehicle (year):");
    if (Vehicle::isYearValid(year)) {
      break;
    }
    cout << "Year is invalid. Try again." << endl;
  }
  vehicles.push_back(new Vehicle(producer, model, year));
  cout << "**************************************" << endl;
  cout << "The vehicle was added to the database" << endl;
  cout << "**************************************" << endl;
}
void add_vendor(vector <Vendor*>& vendors) {
  string v_name = AskFor<string>("New vendor (name): ");
  string address = AskFor<string>("New vendor (address): ");
  string phone;
  while (true) {
    phone = AskFor<string>("New vendor (phone):");
    if (Vendor::isPhoneNumber(phone)) {
      break;
    }
    else cout << "Phone is invalid. Try again." << endl;
  }
  vector<string> delivery;
  string del;
  do {
    cout << "New vendor(delivery) or q to stop: ";
    if (del != "") {
      delivery.push_back(del);
    }
  } while ((cin >> del) && del != "q");
  vendors.push_back(new Vendor(v_name, address, phone, delivery));
  cout << "**************************************" << endl;
  cout << "The vendor was added to the database" << endl;
  cout << "**************************************" << endl;
}
void add_part(vector<PartAndNumber*>& parts, const vector<Vehicle*>& vehicles, const vector<Vendor*>& vendors) {
  string prompt = "Choose the type of spare part : Available(1) or Contracted(2); or q to exit : ";
  do {
    string model = AskFor<string>("Vehicle model: ");
    Vehicle* vehicle = nullptr;
    for (auto v : vehicles) {
      if (v->getModel() == model) {
        vehicle = v;
        break;
      }
    }
    if (vehicle == nullptr) {
      cout << "Could not find a vehicle with this model." << endl;
      return;
    }
    switch (AskFor<char>(prompt)) {
      case '1':
      add_available_part(parts, vehicle);
      return;
      break;
    case '2':
      add_contracted_part(parts, vehicle, vendors);
      return;
      break;
    case 'q':
      return;
      break;
    default:
      cout << "No such option!";
    }
  } while (true);
}
void add_available_part(vector<PartAndNumber*>& parts, Vehicle* vehicle) {
  string id = AskFor<string>("New spare part(id): ");
  for (auto p : parts) {
    if (p->part->getId() == id) {
      cout << "Already available" << endl;
      return;
    }
  }
  string name = AskFor<string>("New spare part(name): ");
  int price = AskFor<int>("New spare part(price): ");
  int time_to_replace = AskFor<int>("New spare part(time to replace): ");
  bool is_new = AskFor<bool>("New spare part(1 for new, 0 for recycled): ");
  string description = AskFor<string>("New spare part(description): ");
  string manual = AskFor<string>("New spare part(manual): ");
  int quantity = AskFor<int>("New spare part(quantity): ");
  string location = AskFor<string>("New spare part(location): ");
  auto part = new AvailableSparePart(id, name, vehicle, price, time_to_replace, quantity, location, is_new, description, manual);
  parts.push_back(new PartAndNumber(part, 0));
  cout << "**************************************" << endl;
  cout << "The spare part was added to the database" << endl;
  cout << "**************************************" << endl;
}
void add_contracted_part(vector<PartAndNumber*>& parts, Vehicle* vehicle, const vector<Vendor*>& vendors) {
  string id = AskFor<string>("New spare part(id): ");
  for (auto p : parts) {
    if (p->part->getId() == id) {
      cout << "Already available" << endl;
      return;
    }
  }
  string v_name = AskFor<string>("New spare part(vendor name): ");
  Vendor* vendor = nullptr;
  for (auto v : vendors) {
    if (v->getVendorName() == v_name) {
      vendor = v;
      break;
    }
  }
  if (vendor == nullptr) {
    cout << "Could not find a vendor with this name." << endl;
    return;
  }
  string name = AskFor<string>("New spare part(name): ");
  int price = AskFor<int>("New spare part(price): ");
  int time_to_replace = AskFor<int>("New spare part(time to replace): ");
  bool is_new = AskFor<bool>("New spare part(1 for new, 0 for recycled): ");
  string description = AskFor<string>("New spare part(description): ");
  string manual = AskFor<string>("New spare part(manual): ");
  int delivery_time = AskFor<int>("New spare part(delivery time): ");
  double delivery_price = AskFor<double>("New spare part(delivery price): ");
  auto part = new ContractedSparePart(id, name, vehicle, price, time_to_replace, delivery_time, delivery_price, vendor, is_new, description, manual);
  parts.push_back(new PartAndNumber(part, 0));
  cout << "**************************************" << endl;
  cout << "The spare part was added to the database" << endl;
  cout << "**************************************" << endl;
}
void add_part_number(vector<PartAndNumber*>& parts) {
  string id = AskFor<string>("Spare part (id): ");
  for (auto p : parts) {
    if (p->part->getId() == id) {
      int parts_number = AskFor<int>("Number of parts: ");
      p->number = parts_number;
      cout << "***************************************************" << endl;
      cout << "The number of spare parts was added to the database" << endl;
      cout << "***************************************************" << endl;
      return;
    }
  }
  cout << "A spare part with this ID is not available."; 
}
void list_parts(const vector<PartAndNumber*>& parts) {
    double total_price = 0;
  for (auto p : parts) {
    p->part->output();
    cout << endl;
    double total_current_price = p->part->replacementPrice() * p->part->getTimeToReplace();
    total_price = +total_current_price;
  }
  quicksort(parts, , parts.back);
  cout << "The total price is" << total_price << endl;
}
void calculate_cost(const vector<PartAndNumber*>& parts) {
  string id = AskFor<string>("Spare part(id): ");
  for (auto p : parts) {
    if (p->part->getId() == id) {
      cout << "The cost for replacement is $" << p->part->replacementPrice() << endl;
      return;
    }
  }
  cout << "A spare part with this ID is not available.";
}
SparePart::~SparePart() {}
template <class Comparable>
void quicksort(vector<Comparable>& a)
{
    quicksort(a, 0, a.size() - 1);
}
template <class Comparable>
void quicksort(vector<Comparable>& a, double low, double high)
{
    if (low + 10 > high) {
        insertionSort(a);
    }
    else {
        double middle = (low + high) / 2;
        if (a[middle] < a[low]) swap(a[low], a[middle]);
        if (a[high] < a[low]) swap(a[low], a[high]);
        if (a[high] < a[middle]) swap(a[middle], a[high]);
        Comparable pivot = a[middle];
        swap(a[middle], a[high - 1]);

        int i, j;
        for (i = low, j = high - 1; ;) {
            while (a[++i] < pivot) {}
            while (pivot < a[--j]) {}
            if (i < j) swap(a[i], a[j]);
            else break;
        }
        swap(a[i], a[high - 1]);
        quicksort(a, low, i - 1);
        quicksort(a, i + 1, high); 
    }
}

谢谢你的帮助!

向量的元素是指针!最简单的方法是添加到类 PartAndNumber

operator<(const PartAndNumber *other)
{
    return this->part->id - other->part->id;
}