ホームページ  >  記事  >  バックエンド開発  >  アルゴリズムを最適化する方法を教えてください

アルゴリズムを最適化する方法を教えてください

WBOY
WBOYオリジナル
2016-06-23 14:03:32793ブラウズ

第一希望と第二希望だけです。あと2回やります。その後の2回目のボランティアと基本的には同じです。 100 人の生徒のデータを実行するのに約 6 ~ 7 秒かかりました。最適化する方法についてアドバイスをお願いします~~ありがとうございます


if($_POST['cal'])
{
//------ - - - - - - - - - - - - - - - - 最初に選んだ - - - - - - - - - --------- ------------------
$sql = "select * from hos;"
$res = mysql_query($sql)or die (mysql_error());
$info = mysql_fetch_array($res)or die(mysql_error());
//echo $info['total'] // ループ 1
// ++++++++ ++++++++++++++++++++++++++++++++++++ ++++++++++ ++++++++++++//境界線
if($info['same']==0) //男女の区別がない場合and women
{
$hos_id = $info['id' ; = "stu where first='".$hos_id."' and get=0 ;"; の数を加算します。申請を希望する学生
$res_total = mysql_query($sql_total);
$info_total = mysql_fetch_array($res_total) //申請書を記入した学生の数を取得します
if($hos_total > $info_total['total' ])
{$sql1 = "stu where first='".$hos_id. "' and get=0 ORDER BY スコア DESC ;";}
else {$sql1 = "stu where first=' ".$hos_id."' and get=0 ORDER BY スコア DESC 制限 $hos_total;"; }
$res1 = mysql_query($sql1);
$info1 = mysql_fetch_array($res1);
do //ループ 2
{
$stu_id = $info1['id'];
$sql2 = "UPDATE stu SET result ='".$hos_id."',get=1 where id='".$stu_id."' ;"; res2 = mysql_query($sql2);
}while($info1 = mysql_fetch_array($res1)) // ループ 2 の終了
}
// +++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++ +++//境界線

else //男女を区別する場合-----$info ['same']==1;
$hos_id = $info['id'] / /病院ID番号
//男子SQL
$hos_total_men = $info['men']; //病院需要の合計 男子人数
$sql_total_men = "stu where first='".$ hos_id."' and sex='f' and get=0 ;" // 希望する男子学生の数を追加します
$info_total_men = mysql_fetch_array($res_total_men); {$sql1_men = " stu から id を選択します where first='".$hos_id."' and sex='m' and get=0 ORDER BY スコア DESC ;";}
else {$sql1_men = "stu から id を選択します where first='". $hos_id."'and sex='m' and get=0 ORDER BY スコア DESC 制限 $hos_total_men;";}
$res1_men = mysql_query($sql1_men);
$info1_men = mysql_fetch_array($res1_men) ;
do // ループ 2
{
// ボーイズアップデート
$stu_id_men = $info1_men['id'];
$sql2_men = "UPDATE stu SET result='".$hos_id."',get=1 where id ='".$ stu_id_men."' ;";
$res2_men = mysql_query($sql2_men);
}while($info1_men = mysql_fetch_array($res1_men));
//Girl SQL
$hos_total_wom = $info['wom ']; // 病院が必要とする女の子の総数
$sql_total_wom = "stu where first='".$hos_id."' and sex='f' and get=0 ; "; //これを希望する男子生徒を追加 生徒数
$res_total_wom = mysql_query($sql_total_wom);
$info_total_wom = mysql_fetch_array($res_total_wom); //申請書に記入した女子学生の数を取得します
if($hos_total_wom > $info_total_wom['total_wom'])
{$sql1_wom = "最初の = から ID を選択します'". $hos_id."' and sex='f' and get=0 ORDER BY スコア DESC ;";}
else {$sql1_wom = "stu where first='".$hos_id."' and sex ='f ' and get=0 ORDER BY スコア DESC 制限 $hos_total_wom;";}
$res1_wom = mysql_query($sql1_wom);
$info1_wom = mysql_fetch_array($res1_wom);
do //ループ 2
{
//女の子の更新
$stu_id_men = $info1_wom['id'];
$sql2_wom = "UPDATE stu SET result='".$hos_id."',get=1 where id='".$stu_id_wom."';";
$res2_wom = mysql_query($sql2_wom);
}while($info1_wom = mysql_fetch_array($res1_wom))
//ループ 2 の終了
}

}while($info = mysql_fetch_array($res));ループ 1 の終了
//------------------------------------------ --第一希望終了 ----------------------------------------



//- -------------------------------------- 第 2 の選択 -- -- -------------------------------------------
$s_sql = "選択 * from hos;";
$s_res = mysql_query($s_sql)or die(mysql_error());
$s_info = mysql_fetch_array($s_res)or die(mysql_error());
do{ //ループ 1
// + ++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++//境界線
if($s_info['same']==0) //男女の区別がない場合
{
$ s_hos_id = $s_info['id']; //病院ID番号
$s_hos_total = $s_info['total'] //病院に必要な人数
$s_sql_total = "select count(*); total from stu where Second= '".$s_hos_id."' and get=0 ;"; //申請を希望する学生の数を追加します
$s_res_total = mysql_query($s_sql_total);
$s_info_total = mysql_fetch_array($s_res_total) ); //第二希望レポートを取得 志望者数
$s_get_sql = "select count(*) as total from stu where result='".$s_hos_id."' ;";最初の選択が HOS_ID である生徒
$s_get_res = mysql_query( $s_get_sql);
if($s_get_info['total'] == $s_hos_total);
else
{
$ xuqiu2 = $s_hos_toal-$s_get_ info['total']; //必要な生徒数
if( $xuqiu2 > $s_info_total['total']){$s_sql1 = "stu where Second='から ID を選択します" .$s_hos_id."' and get=0 ORDER BY スコア DESC ;";}
else {$s_sql1 = "select id from stu where Second='".$s_hos_id."' and get=0 ORDER BY スコア DESC 制限 $ xuqiu2;";}
$s_res1 = mysql_query($s_sql1) ;
$s_info1 = mysql_fetch_array($s_res1);
do //ループ 2
{
$s_stu_id = $s_info1['id'];
$s_sql2 = 」 UPDATE stu SET result='".$s_hos_id."', get=1 where id='".$s_stu_id."' ;";
$s_res2 = mysql_query($s_sql2);
}while($s_info1 = mysql_fetch_array( $s_res1));
}
}// ループ 2 の終了



else // 男性と女性を区別する場合-----$info['same']==1
{
$s_hos_id = $s_info['id']; //病院ID番号
//男子用SQL
$s_hos_total_men = $s_info['men'] //病院が必要とする男子の総数
$s_sql_total_men = "select count( *) as total_men from stu where Second='".$s_hos_id."' and sex='m' and get=0 ;"; //応募したい男子学生の数を追加します
$s_res_total_men = mysql_query( $s_sql_total_men);$s_info_total_men = mysql_fetch_array($s_res_total_men); //申請書に記入した男子学生の数を取得します

$s_get_sql_men = "stu where result='".$s_hos_id."' と性別から合計として count(*) を選択します=' m ' ;"; //第一希望が HOS_ID である男子学生を取得
$s_get_res_men = mysql_query($s_get_sql_men);
$s_get_info_men = mysql_fetch_array($s_get_res_men);
if($s_get_info_men['total'] == $s_hos_total_men ; l1_men = "stu から ID を選択します ( Second='".$s_hos_id."' および sex='m' および get=0 ORDER BY スコア DESC ;";}
else {$s_sql1_men = "stu から ID を選択します) where Second='" .$s_hos_id."'and sex='m' および get=0 ORDER BY スコア DESC 制限 $xuqiu2_men;";}
$s_res1_men = mysql_query($s_sql1_men);
$s_info1_men = mysql_fetch_array($s_res1_men) ) ;
do / /ループ 2
{
// ボーイズアップデート
$s_stu_id_men = $s_info1_men['id'];
$s_sql2_men = "UPDATE stu SET result='".$s_hos_id."',get=1 id='". $s_stu_id_men."' ;";
$s_res2_men = mysql_query($s_sql2_men);
}while($s_info1_men = mysql_fetch_array($s_res1_men));
}


//Girls SQL $s_hos_total_wom = $s_info['wom ']; //病院が必要とする女の子の総数
$s_sql_total_wom = "select count(*) as total_wom from stu where Second='".$s_hos_id."' and sex='f' and get=0 ;"; // 願書を提出した女子学生の数を加算します
$s_res_total_wom = mysql_query($s_sql_total_wom);
$s_info_total_wom = mysql_fetch_array($s_res_total_wom); _sql_wom = "select count(*) as total from stu where result='".$s_hos_id."' and sex='f' ;"; //第一希望が HOS_ID である女子学生を取得
$s_get_res_wom = mysql_query($s_get_sql_wom);
$s_get_info_wom = mysql_fetch_array( //あと何人の女子学生が必要ですか
if ($xuqiu2_wom > $s_info_total_wom['total_wom'])
{$s_sql1_wom = "stu where Second='".$s_hos_id."' and sex='f' and get=0 ORDER BY スコア DESC ;" ;}
else {$s_sql1_wom = "stu where Second='".$s_hos_id."'and sex='f' and get=0 ORDER BY スコア DESC 制限 $xuqiu2_wom ;";}
$s_res1_wom = mysql_query ($s_sql1_wom);
$s_info1_wom = mysql_fetch_array($s_res1_wom);
do //ループ 2
{
//ガールズアップデート
$s_stu_id_wom =女性['id']
$s_sql2_wom = "UPDATE stu SET result= '". $ s_hos_id."', get = 1 where id = '". $ s_stu_ID_WOM." ";";
$ s_res2_wom = mysql_qury ($ s_sql2_wom); _Fetch_array ($ s_res1_wom) );
}

}}

}} While ($ info = MySQL_FETCH_ARAY ($ Res)); 。 。しかし、目視で確認すると、それはジョイントテーブルであるはずです

長すぎてあまり読んでいません。 。 。しかし、目視で確認すると、リンク テーブルであるはずです
リンク リストはダブルテーブル クエリですか? ?どれくらい早くなるでしょうか

ああ、ちょっと見てみました。 。 。 。クエリ後に更新します。 。 。そうですね
最初の段落を取得するには、更新中のサブクエリに変更する必要があります $sql2 = "UPDATE stu SET result='".$hos_id."',get=1 where id='".$stu_id " ' ;";

前の内容を「update stu set result='$hos_id',get=1 where id in(select id)」に変更します
以上です。 。 。もちろん、要件に応じて変更する必要があります。 。 。
あなたのアイデアについて言及したかどうかはわかりませんが、結局のところ、あなたの意図がわかりません

ああ、見ました。 。 。 。クエリ後に更新します。 。 。そうですね


最初の段落を取得するには、更新中のサブクエリに変更する必要があります $sql2 = "UPDATE stu SET result='".$hos_id."',get=1 where id='".$stu_id. ' これらのループは行わないでください。
変更した後は間違いなく質的な飛躍になります
要件に従ってこれらのループを実行しないでください。それは間違いなく質的な飛躍です
ただし、テーブル全体をループする必要があります。各生徒の希望を調整します

update stu set result='$hos_id',get=1 where in ( select id) and get=0


$hos_id を必要なパラメータに変更し、SQL に移動して直接実行します

update stu set result='$hos_id',get=1 where in (select id) and get= 0

$hos_id を必要なパラメータに変更し、SQL に移動して直接実行できます

しませんわかりません~~ 参考に関連するコードを教えていただけますか?テーブル構造とテストデータ

2. コードが乱雑なのでフォーマットする必要があります。これはコードの最適化です
、一般的な考え方は、各学生に連絡可能かどうかを確認すること、そしてあなたのものは各病院に意欲的な学生がいるかどうかを確認することです。ネストされたループでは、サイクル数が最も多いループをできるだけ外側の層に配置する必要があります。これが最適化アルゴリズムです。実際には、コードをより適切に記述することができ、解決に役立ちます。問題

コードを簡略化してみました~~今後も専門家の指導を受けながら最適化していきます。計算は以前より 4 倍速くなりました。ただし、それでも 1 ~ 2 秒かかります~~最適化を続けます
for($i=1;$i402e64cd64602c10eb3b772de53312ac$info['men']){$sql.="limit $m_total "; ($sql);}
else if($num_minfo['total']==$info['men' ]){$sql.="limit 0 ";}
else
{
$ m_need=$info['men']-$num_minfo['total'];
$sql.="and sex='m' 制限 $m_need ";
mysql_query($sql) }
$sql1 = " stu set result=$id,get=1 where id in (select id ORDER BY スコア DESC) and $key= $id and get=0 ";
$num_wsql = "stu where result= からの合計として count(id) を選択します$id と sex='f'";
$num_wres = mysql_query($num_wsql);
$num_winfo = mysql_fetch_array ($num_wres);
if($num_winfo['total']>$info['wom']) {$sql1.="limit $f_total " ;mysql_query($sql);}
else if($num_winfo[ 'total']==$info['wom']){$sql1.="limit 0 "; ($sql);}
else
{
$w_need=$info['wom']-$num_minfo[ 'total']
$sql1.="and sex='f' 制限 '$w_need' "; mysql_query($sql1);
}

}
}
}
}

//---- ------------------------- -----------------------最終かつ即時配布----- ------- ----------------------
$l_sql = "select * from hos; "; $ $ L_res = mysql_query ($ l_sql) または die (mysql_error ()) ; $ l_id = $ l_info ['id']; //病院ID番号
$l_total = $l_info['total'] //病院が必要とする人数の合計
$l_get_sql = "select count(*) stu からの合計 where result='".$ l_id."';";
$l_get_res = mysql_query($l_get_sql);
$l_get_info = mysql_fetch_array($l_get_res); //結果が病院 ID である学生の数
if($l_get_info['total'] == $l_total){}
else
{
$xuqiu4 = $l_total-$ l_get_info ['total']; //必要な生徒数
$sql = "update stu set result='$l_id',get=1 where id in(select id ORDER BY スコア DESC) and get=0 limit $xuqiu4 " ;
mysql_query($sql);
}
}while($l_info = mysql_fetch_array($l_res));

少し眠いので、コードを数行入力しました

投稿者のリクエストは次のようになります。学生が受験できる病院は 3 つありますが、これらの病院は、受験を申請した学生から順に受験できるようになります。一部の病院には制限があります。男性と女性の数は異なりますが、そうでない人もいます。

// 录取所有学生function fetchAllStu(){    // 志愿批次列表    $batch_list = array("first", "second", "third");    // 涉及多个更新操作,需要事务处理    mysql_query("start transaction");    $sql = "select * from hos";    $res = mysql_query($sql) or die(mysql_error());    while($info = mysql_fetch_array($res))    {        foreach ($batch_list as $val)        {            if(empty($info['same']))            {                // 不分男女录取                $need_cnt = $info['total'] - getStuCount($info['id']);                if(!fetchHosStu($val, $info['id'], $need_cnt))                {                    mysql_query("rollback");                    return false;                }            }            else            {                // 录取男生                $m_need_cnt = $info['men'] - getStuCount($info['id'], 'm');                if(!fetchHosStu($val, $info['id'], $m_need_cnt, 'm'))                {                    mysql_query("rollback");                    return false;                }                                // 录取女生                $f_need_cnt = $info['wom'] - getStuCount($info['id'], 'f');                if(!fetchHosStu($val, $info['id'], $f_need_cnt, 'f'))                {                    mysql_query("rollback");                    return false;                }            }        }    }    mysql_query("commit");    return true;}// 录取指定医院的学生function fetchHosStu($index, $hos_id, $num_limit, $sex=null) {    global $field_list;        $sub_condition = '';    if (isset($sex))     {        if(!isValidSex($sex))        {            return false;        }        $sub_condition = "where sex='{$sex}'";    }    // 只有人没录取满才能继续录取    if($num_limit > 0)    {        $cond = array();        $cond[] = "id in (select id from stu {$sub_condition} order by score desc limit {$num_limit}) and get=0";        $cond[] = "{$index}={$hos_id}";                // 拼接SQL        $condition = "where ". implode(' and ', $cond);        $sql = "update stu set result={$hos_id},get=1 where {$condition}";        //echo $sql;        return mysql_query($sql);    }    return false;}// 判断是否是合法的性别function isValidSex($sex) {    return in_array(strtolower($sex), array('f', 'm'));}// 取得医院已录取学生数function getStuCount($hos_id, $sex=null) {    $cond = array();    if (isset($sex))     {        if(!isValidSex($sex))        {            return false;        }        $cond[] = "sex='{$sex}'";    }    $cond[] = "result={$hos_id}";        // 拼接SQL    $condition = "where ". implode(' and ', $cond);    $sql = "select count(1) as total from stu {$condition}";    //echo $sql;    $res = mysql_query($sql);    $info = mysql_fetch_array($res);    return $info['total'];}fetchAllStu();


私には編集権限がないので、いくつか説明を追加する必要があります:

1. 入場操作が途中で失敗すると、深刻な結果が生じます (それは楽しいでしょう)。もし私たちの大学入学試験の入学システムにこの問題があったとしたら)。したがって、 * を格納するには INNODB テーブルを使用する必要があり、更新操作の整合性を確保するにはトランザクションを使用する必要があります。
2. ここでは、ポスターをバッチで更新する必要があると想定しています。そのような制限がない場合は、さらに最適化できます。
3.53 行目は役に立たないので、削除してください
4. 元の投稿者にいくつかの提案を与えます。コードはコード形式で投稿してください。テキスト形式は本当に人々を夢中にさせます。同様のコードをできるだけ関数にカプセル化するようにしてください。私たちは編集者ではなくプログラマーです。関数本体のコードは 100 行以内に収めるようにしてください。100 万語の小説には複数の段落が存在します。

編集権限がないので、いくつか説明を追加する必要があります:

1. 入学操作が途中で失敗すると、その結果は深刻になります (大学入学試験ができたら楽しいでしょう)。入学システムにはこの問題がありました)。したがって、 * を格納するには INNODB テーブルを使用する必要があり、更新操作の整合性を確保するにはトランザクションを使用する必要があります。
2. ここでは、ポスターをバッチで更新する必要があると想定しています。そのような制限がない場合は、さらに最適化できます。
3.53 行目は役に立たないので、削除してください
4. 元の投稿者にいくつかの提案を与えます。コードをコード形式で記述してください...
コード内で関数を直接呼び出すだけで十分かどうかお聞きしたいのですが?初めて投稿するので下手ですみません。

データベーステーブル構造を添付します~~

関数を呼び出しても結果はありません。私の操作の問題なのかわかりません~~~

74行目に何か問題があります、余分な場所があります。

削除されたSQLを開いて確認できます。

関数呼び出しは

if($_POST['cal']){    // 调用放这里}

74 行目に何か問題があり、余分な where があります。

削除されたSQLを開いて確認できます。

関数呼び出しは
PHP code?1234if($_POST['cal']){ // 呼び出しはここに配置されます}
出力 SQL は
select count(1) as total from stu where sex=' m' と result =1
stu set result=1,get=1 where id in (stu から ID を選択 where sex='m' order by スコア記述制限 4) と get=0 と first=1 を更新します
まだ結果はありません~何もしないで更新してください~

a403983161 へ
あなたは元の投稿者ですか?それともベスト?
質問がある場合は、自分で投稿してください。なぜ他の人の投稿で問題を起こすのですか?

a403983161

元の投稿者ですか?それともベスト?
問題があるなら自分で投稿してください、他の人の投稿で迷惑をかけませんか?
元の投稿者~~アカウントを変更しました。もう 1 つは、QQ を使用してログインする必要があります ~ ちょっと面倒です

それで、誰か (ustb など) があなたを助けてくれたら、ポイントでどのように感謝しますか?

それで、誰か(ustb など)があなたを助けてくれた場合、ポイントでどのように感謝しますか?

時間が来たら別の番号を使用します。これは私がよく使用するアカウントです。必要なときに割り当てます

実行後に機能しない場合は、トランザクションがロールバックされている可能性があります。一部を切り取って再度テストしてください。

実行しても効果がない場合は、トランザクションがロールバックされている可能性がありますので、トランザクション部分をコメントアウトして再度テストしてください。

ああ、やってみます

先生、実行してもうまくいかない場合は、トランザクション部分がロールバックされている可能性がありますので、トランザクション部分をコメントアウトして再度テストしてみてください。

まだ機能しません。それぞれに個別に注釈を付けましたが、まだ機能しません。ご都合がよければQQにメッセージを残していただければ詳しくお聞きします〜

楼主,如果你执行之后没有效果,有可能是事务回滚了,你可以将事务的部分注释掉,再测试一下。
大神,问题还没解决,求指教。

非得要把代码一行不漏的贴出来才行么?

$conn = mysql_connect("localhost", "test", "test");mysql_select_db("test", $conn);mysql_set_charset("utf8", $conn);// 录取所有学生function fetchAllStu(){    // 志愿批次列表    $batch_list = array("first", "second", "third");    // 涉及多个更新操作,需要事务处理    mysql_query("start transaction");    $sql = "select * from hos";    $res = mysql_query($sql) or die(mysql_error());    while($info = mysql_fetch_array($res))    {        foreach ($batch_list as $val)        {            if(empty($info['same']))            {                // 不分男女录取                $need_cnt = $info['total'] - getStuCount($info['id']);                if(!fetchHosStu($val, $info['id'], $need_cnt))                {                    mysql_query("rollback");                    return false;                }            }            else            {                // 录取男生                $m_need_cnt = $info['men'] - getStuCount($info['id'], 'm');                if(!fetchHosStu($val, $info['id'], $m_need_cnt, 'm'))                {                    mysql_query("rollback");                    return false;                }                // 录取女生                $f_need_cnt = $info['wom'] - getStuCount($info['id'], 'f');                if(!fetchHosStu($val, $info['id'], $f_need_cnt, 'f'))                {                    mysql_query("rollback");                    return false;                }            }        }    }    mysql_query("commit");    return true;}// 录取指定医院的学生function fetchHosStu($index, $hos_id, $num_limit, $sex=null){    $sub_condition = '';    if (isset($sex))    {        if(!isValidSex($sex))        {            return false;        }        $sub_condition = "where sex='{$sex}'";    }    // 只有人没录取满才能继续录取    if($num_limit > 0)    {        $cond = array();        $cond[] = "{$index}={$hos_id}";        // 拼接SQL        $condition = implode(' and ', $cond);        $sql = "update stu set result=1,get=1 where get=0 and {$condition} order by score desc limit {$num_limit}";        //echo $sql;        return mysql_query($sql);    }    return false;}// 判断是否是合法的性别function isValidSex($sex){    return in_array(strtolower($sex), array('f', 'm'));}// 取得医院已录取学生数function getStuCount($hos_id, $sex=null){    $cond = array();    if (isset($sex))    {        if(!isValidSex($sex))        {            return false;        }        $cond[] = "sex='{$sex}'";    }    $cond[] = "result={$hos_id}";    // 拼接SQL    $condition = "where ". implode(' and ', $cond);    $sql = "select count(1) as total from stu {$condition} for update";    //echo $sql;    $res = mysql_query($sql);    $info = mysql_fetch_array($res);    return $info['total'];}fetchAllStu();

说明一下:
1.有一个bug修复了,在getStuCount函数中,select语句需要锁记录,以免发生数量变更。
2.更新语句去掉子查询,直接用score排序即可。

以上程序在我本地调试通过,10条记录耗时约0.02秒,应该比楼主之前的效率要高很多了。

说明一下:
1.有一个bug修复了,在getStuCount函数中,select语句需要锁记录,以免发生数量变更。
2.更新语句去掉子查询,直接用score排序即可。

以上程序在我本地调试通过,10条记录耗时约0.02秒,应该比楼主之前的效率要高很多了。
大神,麻烦到你真不好意思的。毕竟水平比较低,刚初学没多久。代码我在本地测试了一下,我大概是100条记录。时间是0.2秒左右,但是结果还是没出来,不知道是什么原因呢?

额滴神呀,上面的代码只是用于更新,取数据并显示出来你自己就能写,你好歹写两行吧,不然我就全写完了。。。

额滴神呀,上面的代码只是用于更新,取数据并显示出来你自己就能写,你好歹写两行吧,不然我就全写完了。。。
更新不了呢~~数据库里的表信息还是原来的。取数据显示出来我原来就写了的。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。