#include <iostream>
#include <queue>
#include <algorithm>
#include <map>
using namespace std;
class Exchange {
public:
static int count; //靜態數據變量爲每個委託賦予獨一無二的id
static bool match(const Exchange &a, const Exchange &b)
{
return a.price >= b.price;
}
int id;
int direction;
int volum;
int price;
int num;
Exchange(int d, int v, int p)
{
count++;
direction = d;
volum = v;//委託量
price = p;
id = count;
num = 0; //交易量
}
static int chaxun(int id, map<int, int> &unfinished, map<int, int> &finished);
};
int Exchange::chaxun(int id, map<int, int> &unfinished, map<int, int> &finished)
{
map<int, int>::iterator i=unfinished.find(id);
if (i != unfinished.end())
return i->second;
else i = finished.find(id);
if (i != finished.end())
return i->second;
else return -1;
}
int Exchange::count = 0;
struct cmp1 {
bool operator()(const Exchange &a, const Exchange &b)const
{
if (a.price == b.price)
return a.id < b.id;
else
return a.price < b.price;
}
};
struct cmp2 {
bool operator()(const Exchange &a, const Exchange &b) const
{
if (a.price == b.price)
return a.id > b.id;
else
return a.price < b.price;
}
};
void update(Exchange a, Exchange b, priority_queue<Exchange, vector<Exchange>, cmp1> &input, priority_queue<Exchange, vector<Exchange>, cmp2> &output, map<int, int> &unfinished)
{
input.pop(); output.pop(); //優先級隊列的TOP元素爲只讀,修改內容需要先彈出,再修改,最後重新壓入
int temp = min(a.volum, b.volum);
unfinished[a.id] = a.volum -= temp;
a.num += temp;
unfinished[b.id] = b.volum -= temp;
b.num += temp;
input.push(a); output.push(b);
}
char inputc()
{
char a;
cin >> a;
return a;
}
void exchange(priority_queue<Exchange, vector<Exchange>, cmp1> &input, priority_queue<Exchange, vector<Exchange>, cmp2> &output, map<int, int> &unfinished, map<int, int> &finished)
{
int d, v, p;
cin >> d >> v >> p;
if (d != 0 && d != 1)
{
cout << "\t您的委託類型輸入有誤,請重新輸入:" << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
} //如果不清除緩存區,就有可能輸出多條錯誤提示
if (d == 0)
{
priority_queue<Exchange, vector<Exchange>, cmp1>::value_type a(d, v, p);
input.push(a);
unfinished[a.id] = a.volum;
}
if (d == 1)
{
priority_queue<Exchange, vector<Exchange>, cmp2>::value_type a(d, v, p);
output.push(a);
unfinished[a.id] = a.num;
}
if (input.empty() || output.empty())
return;
while (!input.empty() && !output.empty())
{
if (Exchange::match(input.top(), output.top()))
{
Exchange p1(input.top());
Exchange p2(output.top());
update(p1, p2, input, output, unfinished);
if (input.top().volum == 0)
{
unfinished.erase(input.top().id); //如果委託量爲零,則全部轉入已交易的映射中
finished[input.top().id] = input.top().num;
input.pop();
}
if (output.top().volum == 0)
{
unfinished.erase(output.top().id);
finished[output.top().id] = output.top().num;
output.pop();
}
}
else
{
cout << "\n";
cout << "\t交易進行完成" << endl;//委託隊列非空但不滿足繼續交易的條件
cout << "\n";
return;
}
}
cout << "\t交易進行完成" << endl; //有至少一方的委託隊列爲空,交易完成
}
int main()
{
priority_queue<Exchange, vector<Exchange>, cmp1>input;
priority_queue<Exchange, vector<Exchange>, cmp2>output;
map<int, int> finished; //用map存放已完成的交易信息,檢索速度很快
map<int, int> unfinished; //用map存放未完成的交易信息
cout << "\t歡迎使用本交易系統"<<endl;
while (1)
{ cout << "\t 查詢請按q\n\t 發出委託請按w\n\t 退出請按z"<<endl;
char temp = inputc();
if (temp == 'w')
{
cout << "\t確認發出委託請按y,返回上層請按n:"<<endl;
char t;
cin >> t;
if (t == 'y')
{
cout << "\t請輸入委託類型,委託量,委託價格:"<<endl;
exchange(input, output, unfinished, finished);
}
else if (t == 'n')
continue;
else
{
cout << "\t您的輸入有誤,請重新輸入:" << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');//如果不清除緩存區,就有可能輸出多條錯誤提示
continue;
}
}
else if (temp == 'q')
{
int id;
cout << "\t請輸入委託單號:" << endl;
cin >> id;
if (Exchange::chaxun(id, unfinished, finished) != -1)
{
cout << "\n";
cout << "\t第" << id << "單委託的交易量爲" << Exchange::chaxun(id, unfinished, finished) << endl;
cout << "\n";
}
else
cout << "\t並無此單,請重新輸入" << endl;
}
else if (temp == 'z')
{
cout << "\t謝謝使用,再見!"<<endl;
break;
}
else
{
cout << "\t您的輸入有誤,請重新輸入:" << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
continue;
}
}
return 0;
}