2

クラスがあります

class Zaposlenik { 
private:
    string prezime; 
    string funkcija; 
    double placa; 
public:
    bool operator==(const string& prezime) const; 
    bool operator<(const string &prezime) const; 
    bool operator<(const Zaposlenik &other) const; 

二分探索には文字列付きの演算子を使用し、ソートには Zaposlenik 付きの operator< を使用します

ヘッダー クラスを変更できません。.cpp でしかコードを記述できません。

私も持っています

class Firma { 
private: 
vector<Zaposlenik> zaposlenici; 
public: 
void sort();

そのクラスも変更できません。.cpp を作成する必要があります。2 .cpp を自動グレーディング サーバーにアップロードします。このサーバーは、500,000 Zaposlenik をベクター zaposlenici に入力し、2,000,000 回の検索を実行します。

qsort と bsearch を使用しましたが、遅すぎました。アップロードするときに 3 秒より長くすることはできません。

私はオーバーロードされた演算子を書きましたが、それらは問題ないと思いますが、どうやらqsortの方が高速になる可能性があります。

ベクターは文字列prezimeでソートされており、名前は「aaaa」から「ZZZZ」までなので大小の4文字の組み合わせ。

string funkcija;double placa; 並べ替えには何の意味もありません。

誰かがqsortよりも速いソートを教えてもらえますか? メインを制御することはできず、メンバーが作成されたときにメンバーを数えることはできないことに注意してください。

PSクラスには他の関数がありますが、この部分には意味がありません。Bsearch の機能もありますが、それは信じられないほど高速です。

4

4 に答える 4

9

三つのこと:

  • std::sortの代わりに使用std::qsortします。比較演算子の呼び出しをインライン化できるため高速です (ヘッダーで定義するか、リンク時の最適化を有効にする場合)。

  • クラスをオーバーライドswapして、一時変数を介してコピーするのではなく、効率的にスワップできるようにします。ただし、ヘッダーを変更する必要があります (プライベート変数にアクセスする必要があるため)。

  • ソートされた文字列は固定長 4 であるため、別のソート アルゴリズムが役立ちます。実装がかなり簡単な古典的な選択肢は、基数ソートです。あなたのコメントのいくつかから判断すると、あなたの教授はあなたにこれを実装してほしいと思っているようです。

于 2013-04-29T13:12:05.460 に答える
3

500 000 Zaposlenik をベクトル zaposlenici に入力し、2 000 000 検索を実行する自動グレーディング サーバー。qsort と bsearch を使用しましたが、遅すぎました。

明確にするために、bsearch を呼び出すたびに qsort を呼び出していませんよね? 二分探索は、リストが既にソートされている場合にのみ高速になるためです。すべての検索の前にリストをソートすると、最悪のパフォーマンスが得られます。

あなたが概説した制約 (すべての文字列の長さは 4 文字です) を考慮してstd::sort、カスタム バケット ソートと比較してテストしたところ、100 万個の要素で、バケット ソートは 8 倍高速でした。ヒント: 4 文字の文字列は 4 * 6 = 24 ビットでエンコードできるため、カウントには 16.777.216 バケットが必要です。

于 2013-04-29T23:39:08.453 に答える
1

ここでの問題は、実際にはクラス ヘッダーの制限です。ボトルネックは、ソート中のスワッピング操作または語彙文字列比較 (あるいはその両方) のいずれかであると思われます。クラス定義をまったく変更できない場合、実装に多くのヘルパー コードを追加する必要があり、すべてが必要以上に複雑になるため、それを改善するのは難しいでしょう。

とにかく、私が提案するアプローチは次のとおりです。文字列に基づいてソートしているため、 Trie の特殊なバージョンを自分で実装すると、辞書順でシーケンスをソートするときに Trie のパフォーマンスを打ち負かすことはできません。このデータ構造全体を .cpp ファイルに実装し、Firma::sortメソッドでインスタンス化できます。

速度に重点を置いているように見えるので、おそらくメモリ消費に関してトレードオフを喜んで行うでしょう。したがって、Treap の各ノードstd::vector<std::shared_ptr<Trie>>を、長さ 256 に初期化する (すべてのスロットを に初期化するnullptr) または のいずれかとして実装しますstd::array<std::shared_ptr<Trie>,256>。基本的に、各文字列をデータ構造に挿入してから、それらをすべて再度読み取ります。このアプローチは、結合されたすべての文字列の合計サイズにおいて線形です (したがって、最適です)。


補足: 各ノードの 256 スロット テーブルは、Trie をトラバースするとき (つまり、Firma::zaposleniciメンバーを書き込むとき) に 256 の定数係数が発生することに注意してください。ASCII を扱っている場合は、テーブル サイズを 128 に減らすか、個々のバイトをハーフバイトに分割して、256 ではなく 2*16 のオーバーヘッドが発生するようにすることができます。

編集: a..z および A..Z の文字のみに遭遇することがわかっている場合、基本アルファベットのサイズは 256 ではなく 2*26 = 52 です。したがって、Trie の各ノードのルックアップ テーブルには、サイズは 52 です (つまり、各ノードは最大 52 の子ノードを持つことができます)。

于 2013-04-29T13:16:13.227 に答える