国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

首頁 php教程 php手冊(cè) PHP 用數(shù)組降低程序的時(shí)間復(fù)雜度

PHP 用數(shù)組降低程序的時(shí)間復(fù)雜度

Jun 13, 2016 pm 12:20 PM
php 復(fù)雜度 對(duì) 應(yīng)用程序 提升 數(shù)組 時(shí)間 硬件 程序 設(shè)備 配置 降低 隨著

而隨著設(shè)備硬件配置的不斷提升,對(duì)中小型應(yīng)用程序來說,對(duì)算法的空間復(fù)雜度的要求也寬松了不少。不過,在當(dāng)今 Web2.0 時(shí)代,對(duì)應(yīng)用程序的時(shí)間復(fù)雜度卻有了更高的要求。

什么是算法的時(shí)間復(fù)雜度呢?概要來說,是指從算法中選取一個(gè)能代表算法的原操作,以原操作重復(fù)執(zhí)行的次數(shù)作為算法的時(shí)間量度。影響時(shí)間復(fù)雜度的因素有兩個(gè):一是原操作的執(zhí)行時(shí)間,二是原操作因控制結(jié)構(gòu)引起的執(zhí)行次數(shù)。要把算法的時(shí)間復(fù)雜度降下來,降低原操作的執(zhí)行次數(shù)是較為容易的方法,也是主要方法。本文所講述的方法,是通過巧用 PHP 的數(shù)組,降低原操作的執(zhí)行次數(shù),從而達(dá)到降低算法時(shí)間復(fù)雜度的需求,和大家分享。

算法的時(shí)間量度記作 T(n)=O(f(n)),它表示算法中基本操作重復(fù)執(zhí)行的次數(shù)是問題規(guī)模 n 的某個(gè)函數(shù) f(n),也就是說隨著問題規(guī)模 n 的增大,算法執(zhí)行時(shí)間的增長(zhǎng)率和 f(n) 的增長(zhǎng)率相同。多數(shù)情況下,我們把最深層循環(huán)內(nèi)的語句作為原操作來討論算法的時(shí)間復(fù)雜度,因?yàn)樗膱?zhí)行次數(shù)和包含它的語句的頻度相同。一般情況下,對(duì)一個(gè)問題只需選擇一種基本操作來討論算法的時(shí)間復(fù)雜度即可。有時(shí)也需要同時(shí)考慮多種基本操作。

在 Web 開發(fā)中,通常一個(gè)功能的執(zhí)行時(shí)間或響應(yīng)時(shí)間,不僅僅跟服務(wù)器的響應(yīng)能力、處理能力有關(guān),還涉及第三方工具的交互時(shí)間,如對(duì)數(shù)據(jù)庫的鏈接時(shí)間和對(duì)數(shù)據(jù)進(jìn)行存取的時(shí)間。因而在選定原操作是,需要綜合考慮應(yīng)用程序各方面的因素,以最大影響程序執(zhí)行時(shí)間的操作為原操作,來衡量算法的時(shí)間復(fù)雜度。也就是說,需要程序員在編寫代碼的時(shí)候,對(duì)重要操作的執(zhí)行時(shí)間能有基本的認(rèn)識(shí)。



我們先看一個(gè)例子,假設(shè) Web 程序的開發(fā)語言是 PHP,后臺(tái)采用 DB2 數(shù)據(jù)庫,PHP 通過 PEAR::DB 數(shù)據(jù)抽象層來實(shí)現(xiàn)對(duì)數(shù)據(jù)庫的訪問。

數(shù)據(jù)庫中有學(xué)生表 STUDENTS(見表 1),班級(jí)表 CLASSES(見表 2),學(xué)生成績(jī)表 SCORES(見表 3),需要在 Web 頁面中顯示出本次考試數(shù)學(xué)成績(jī)超過 90 分的同學(xué)姓名和所在班級(jí)。

表 1. STUDENTS Table

列名 描述
SID 學(xué)號(hào)
STUNAME 姓名
GENDER 性別
AGE 年齡
CLASSID 班級(jí)號(hào)
?

表 2. CLASSES Table

列名 描述
CLASSID 班級(jí)號(hào)
CLASSNAME 班級(jí)名
?

表 3. SCORES Table

列名 描述
SID 學(xué)生學(xué)號(hào)
COURSE 學(xué)科
SCORE 成績(jī)
?

根據(jù)個(gè)人編程習(xí)慣的不同,要解決這個(gè)問題,通常有兩種做法(訪問數(shù)據(jù)庫的操作用 PEAR::DB 的方式表示),參看方法 1、2。

[ 方法 1 ]對(duì) STUDENTS, CLASSES, SCORES 三個(gè)表做聯(lián)合查詢,一次獲取滿足條件的學(xué)生信息和班級(jí)信息。PHP 算法描述如下:


				
$querystr = "select distinct S.STUNAME as STUNAME,C.CLASSNAME as CLASSNAME ".
   "from STUDENTS as S,CLASSES as C,SCORES as R ".
   "where S.SID=R.SID and S.CLASSID=C.CLASSID and R.COURSE='Math' ".
			"and R.SCORE>=90";		
$result = $db2handle->query( $querystr ); //從數(shù)據(jù)庫中獲取數(shù)據(jù)
while( $row=$result->fetchRow(DB_FETCHMODE_ASSOC) ){
 //讀取并顯示數(shù)據(jù)
 echo "StudentName=".$row['STUNAME']."\t ClassName=".$row['CLASSNAME']."\n"; 
}//Done

[ 方法 2 ]從 SCORES 表中找出滿足條件的學(xué)生學(xué)號(hào),然后從 STUDENTS 表中查找學(xué)生的姓名和班級(jí)編碼,最后在 CLASSES 表中獲取班級(jí)的名稱。PHP 算法描述如下:


				
$scorestr = "select distinct SID from SCORES where COURSE='Math' and SCORE>=90";
$scoredata = $db2handle->query( $scorestr ); 
//從數(shù)據(jù)庫中獲取滿足條件的學(xué)生學(xué)號(hào)
while( $score=$scoredata->fetchRow(DB_FETCHMODE_ASSOC) ){
 //讀取學(xué)生的學(xué)號(hào),并在STUDENTS表中查找學(xué)生的姓名和班級(jí)編號(hào)
 $studentstr = "select STUNAME,CLASSID from STUDENTS where SID='".$score['SID']."'";
 $studata =$db2handle->query( $studentstr);
 $stu=$studata->fetchRow(DB_FETCHMODE_ASSOC);
 //顯示學(xué)生的姓名
 echo "StudentName=".$stu['STUNAME']."\t ";
 //讀去學(xué)生的班級(jí)編號(hào),并在CLASSES表中查找該學(xué)生所在班級(jí)名稱
 $classstr = "select CLASSNAME from CLASSES where CLASSID='".$stu['CLASSID']."'";
 $classdata = $db2handle->query( $classstr);
 $class=$classdata ->fetchRow(DB_FETCHMODE_ASSOC);
 //顯示學(xué)生的班級(jí)
 echo "CLASSNAME=".$class['CLASSNAME']."\n";
}//end while for getting each student's ID. Done

對(duì)于這樣的算法描述,相信大家會(huì)有似曾相識(shí)的感覺。這也是大多程序員廣泛使用的算法。因?yàn)橐呀?jīng)習(xí)慣了將思維中的算法邏輯直接譯成代碼,而往往沒有時(shí)間和心思來斟酌算法的優(yōu)劣。這里來分析一下這兩種算法的時(shí)間復(fù)雜度。

因 Web 服務(wù)器讀取并顯示數(shù)據(jù)的時(shí)間相對(duì)較小,一般在 10ms 的數(shù)量級(jí),而從 DB2 數(shù)據(jù)庫里查詢并獲取數(shù)據(jù)的時(shí)間數(shù)量級(jí)會(huì)是 100ms 的數(shù)量級(jí),并且隨查詢數(shù)據(jù)量的增加而增加。所以查詢數(shù)據(jù)庫的操作可作為量度時(shí)間復(fù)雜度的原操作,以 STUDENTS 表和 SCORES 表中的數(shù)據(jù)量作為問題規(guī)模 n( 通常情況下,CLASSES 表的數(shù)據(jù)量較小且相對(duì)穩(wěn)定 )。

對(duì)于方法 1,隨著問題規(guī)模 n 的增大,訪問數(shù)據(jù)庫的次數(shù)為常量 1。因而,時(shí)間復(fù)雜度為 T(n)=O(1)。對(duì)于方法 2,假設(shè) SCORES 表中滿足條件的記錄有 m 個(gè),則原操作的執(zhí)行次數(shù)為 m+1。也就是說隨著數(shù)據(jù)規(guī)模 n 的增大,原操作的執(zhí)行次數(shù)成線性增長(zhǎng)。可見時(shí)間復(fù)雜度為 T(n)=O(n)??梢姡椒?1 的時(shí)間復(fù)雜度低。

那么方法 1 的問題在哪里?主要因?yàn)榉椒?1 會(huì)增大數(shù)據(jù)庫負(fù)載,也就是原操作的執(zhí)行時(shí)間受問題規(guī)模 n 的影響比較大。假設(shè) STUDENTS,CLASSES,SCORES 的記錄數(shù)分別為 X, Y, Z。那么在執(zhí)行聯(lián)合查詢操作時(shí),在數(shù)據(jù)庫中會(huì)形成一個(gè)記錄數(shù)為 X*Y*Z 的矩陣,然后在這個(gè)矩陣中查找滿足條件的記錄數(shù),最后獲取記錄的 STUNAME 信息和 CLASSNAME。這樣,任何一個(gè)表中的數(shù)據(jù)增加,都會(huì)造成矩陣表中記錄的成倍增加。



主要思路 :在所需數(shù)據(jù)中存在相對(duì)簡(jiǎn)單且數(shù)據(jù)量穩(wěn)定的情況下,利用 PHP 數(shù)組 (Array) 的下標(biāo) (Index) 可以為字符串 (String) 的特點(diǎn),巧妙的將數(shù)據(jù)臨時(shí)存放到數(shù)組中。這樣可以通過下標(biāo) (Index) 快速獲取所需值,從而降低對(duì)數(shù)據(jù)庫的查詢次數(shù),進(jìn)而降低算法的時(shí)間復(fù)雜度。

[ 方法 3 ]從 CLASSES 表中獲取 CLASSID 和 CLASSNAME 的對(duì)應(yīng)關(guān)系存放到 ClassArray 一維數(shù)組中,從 STUDENTS 表中獲取 SID 和 STUNAME 以及 CLASSID 的對(duì)應(yīng)關(guān)系存放到 StuArray 二維數(shù)組中。之后從 SCORES 表中找出滿足條件的學(xué)生學(xué)號(hào),從 StuArray 數(shù)組中讀取學(xué)生的姓名和班級(jí)編號(hào),從 ClassArray 中讀取班級(jí)的名稱。PHP 算法描述如下:


				
$ClassArray = Array();
$StuArray = Array();
$classstr = "select CLASSID,CLASSNAME from CLASSES";
$classdata = $db2handle->query( $classstr);
while( $class=$classdata ->fetchRow(DB_FETCHMODE_ASSOC) ){
 //生成ClassArray數(shù)組,下標(biāo)Index以CLASSID命名,對(duì)應(yīng)的值為CLASSNAME
 $ClassArray[$class['CLASSID']] = $class['CLASSNAME'];
}//end while $ClassArray
$stustr="select SID,STUNAME,CLASSID from STUDENTS";
$studata = $db2handle->query( $stustr);
while( $stu=$studata ->fetchRow(DB_FETCHMODE_ASSOC) ){
 //生成StuArray數(shù)組,下標(biāo)Index以SID命名,對(duì)應(yīng)的值為STUNAME和CLASSID
 $StuArray[$stu ['SID']]['STUNAME'] = $stu['STUNAME'];
 $StuArray[$stu ['SID']]['CLASSID'] = $stu['CLASSID'];
}//end while $StuArray
$scorestr = "select distinct SID from SCORES where COURSE='Math' and SCORE>=90";
$scoredata = $db2handle->query( $scorestr ); 
//從數(shù)據(jù)庫中獲取滿足條件的學(xué)生學(xué)號(hào)
while( $score=$scoredata->fetchRow(DB_FETCHMODE_ASSOC) ){
 //讀取學(xué)生的學(xué)號(hào),并從StuArray中讀取學(xué)生的姓名,從ClassArray中讀取班級(jí)名稱
 echo "StudentName=".$StuArray[ $score['SID'] ]['STUNAME']."\t ";
 echo "CLASSNAME=".$ClassArray[ $StuArray[ $score['SID'] ]['CLASSID'] ]."\n";
}//end while for getting each student's ID. Done

改進(jìn)后方法的時(shí)間復(fù)雜度仍為 T(n)=O(1)。和方法 1 相比,方法 3 不必?fù)?dān)心因某一個(gè)表中的記錄增加而引起的數(shù)據(jù)庫查詢代價(jià)的成倍增加。和方法 2 相比,時(shí)間復(fù)雜度降低的同時(shí),也沒有影響算法空間復(fù)雜度。可謂一舉兩得。

雖然此優(yōu)化方法簡(jiǎn)單易用,但并不是說它是萬能的。使用時(shí)需要考慮“度”的問題。假設(shè) STUDENTS 表的數(shù)據(jù)量很大,那么生成 StuArray 的時(shí)候?qū)ο到y(tǒng)內(nèi)存的消耗就增加,這樣算法的空間復(fù)雜度就會(huì)受到影響。另外,當(dāng)數(shù)據(jù)量足夠大時(shí),影響算法執(zhí)行時(shí)間的主要因素就發(fā)生了變化,需要重新選擇原操作。針對(duì) STUDENTS 表記錄數(shù)大,CLASSES 表記錄少且穩(wěn)定的情景,可以考慮用嵌套查詢和數(shù)組相結(jié)合的方式,對(duì)算法進(jìn)行優(yōu)化。這里給出方法 4,以供參考。

[ 方法 4 ]從 CLASSES 表中獲取 CLASSID 和 CLASSNAME 的對(duì)應(yīng)關(guān)系存放到 ClassArray 一維數(shù)組中。從 SCORES 表中查詢滿足條件的學(xué)生學(xué)號(hào),作為查詢 STUDENTS 表的查詢條件,獲取學(xué)生的 STUNAME 和 CLASSID。之后從 ClassArray 中讀取班級(jí)的名稱。PHP 算法描述如下:


				
$ClassArray = Array();
$classstr = "select CLASSID,CLASSNAME from CLASSES";
$classdata = $db2handle->query( $classstr);
while( $class=$classdata ->fetchRow(DB_FETCHMODE_ASSOC) ){
 //生成ClassArray數(shù)組,下標(biāo)Index以CLASSID命名,對(duì)應(yīng)的值為CLASSNAME
 $ClassArray[$class['CLASSID']] = $class['CLASSNAME'];
}//end while $ClassArray
$stustr = "select STUNAME,CLASSID from STUDENTS where SID in ".
   "(select distinct SID from SCORES where COURSE='M' and SCORE>=90)";
$studata = $db2handle->query( $stustr); 
//從數(shù)據(jù)庫中獲取滿足條件的學(xué)生姓名和班級(jí)編號(hào)
while( $stu=$studata ->fetchRow(DB_FETCHMODE_ASSOC) ){
 //讀取學(xué)生的姓名,并從ClassArray中讀取班級(jí)名稱
 echo "StudentName=".$stu ['STUNAME']."\t ";
 echo "CLASSNAME=".$ClassArray[ $stu ['CLASSID'] ]."\n";
}//end while for getting each student's Info. Done


方法 3 和方法 4 中引用了數(shù)組這個(gè)小技巧,巧妙地降低了算法的時(shí)間復(fù)雜度。在實(shí)際應(yīng)用程序中,算法邏輯要復(fù)雜得多,對(duì)算法的優(yōu)化需要綜合考慮多方面的因素。需要提出的是,本文所述的方法不僅適用于 PHP 應(yīng)用程序。如果編程語言的數(shù)組支持以字符串作為下標(biāo),就可以考慮采用本文提出的方法:巧用數(shù)組的下標(biāo)來降低算法的時(shí)間復(fù)雜度。對(duì)于不支持字符串做數(shù)組下標(biāo)的編程語言,可以考慮使用建立哈希表來達(dá)到同樣的效果。

本站聲明
本文內(nèi)容由網(wǎng)友自發(fā)貢獻(xiàn),版權(quán)歸原作者所有,本站不承擔(dān)相應(yīng)法律責(zé)任。如您發(fā)現(xiàn)有涉嫌抄襲侵權(quán)的內(nèi)容,請(qǐng)聯(lián)系admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費(fèi)脫衣服圖片

Undresser.AI Undress

Undresser.AI Undress

人工智能驅(qū)動(dòng)的應(yīng)用程序,用于創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用于從照片中去除衣服的在線人工智能工具。

Clothoff.io

Clothoff.io

AI脫衣機(jī)

Video Face Swap

Video Face Swap

使用我們完全免費(fèi)的人工智能換臉工具輕松在任何視頻中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費(fèi)的代碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

功能強(qiáng)大的PHP集成開發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級(jí)代碼編輯軟件(SublimeText3)

如何在PHP中獲取當(dāng)前的會(huì)話ID? 如何在PHP中獲取當(dāng)前的會(huì)話ID? Jul 13, 2025 am 03:02 AM

在PHP中獲取當(dāng)前會(huì)話ID的方法是使用session_id()函數(shù),但必須先調(diào)用session_start()才能成功獲取。1.調(diào)用session_start()啟動(dòng)會(huì)話;2.使用session_id()讀取會(huì)話ID,輸出類似abc123def456ghi789的字符串;3.若返回為空,檢查是否遺漏session_start()、用戶是否首次訪問或會(huì)話是否被銷毀;4.會(huì)話ID可用于日志記錄、安全驗(yàn)證和跨請(qǐng)求通信,但需注意安全性。確保正確開啟會(huì)話后即可順利獲取ID。

php從字符串獲取子字符串 php從字符串獲取子字符串 Jul 13, 2025 am 02:59 AM

要從PHP字符串中提取子字符串,可使用substr()函數(shù),其語法為substr(string$string,int$start,?int$length=null),若未指定長(zhǎng)度則截取至末尾;處理多字節(jié)字符如中文時(shí)應(yīng)使用mb_substr()函數(shù)以避免亂碼;若需根據(jù)特定分隔符截取字符串,可使用explode()或結(jié)合strpos()與substr()實(shí)現(xiàn),例如提取文件名擴(kuò)展名或域名。

如何將字符串分為PHP中的數(shù)組 如何將字符串分為PHP中的數(shù)組 Jul 13, 2025 am 02:59 AM

在PHP中,最常用的方法是使用explode()函數(shù)將字符串拆分為數(shù)組。該函數(shù)通過指定的分隔符將字符串分割成多個(gè)部分并返回?cái)?shù)組,語法為explode(separator,string,limit),其中separator為分隔符,string為原字符串,limit為可選參數(shù)控制最大分割數(shù)量。例如$str="apple,banana,orange";$arr=explode(",",$str);結(jié)果為["apple","bana

JavaScript數(shù)據(jù)類型:原始與參考 JavaScript數(shù)據(jù)類型:原始與參考 Jul 13, 2025 am 02:43 AM

JavaScript的數(shù)據(jù)類型分為原始類型和引用類型。原始類型包括string、number、boolean、null、undefined和symbol,其值不可變且賦值時(shí)復(fù)制副本,因此互不影響;引用類型如對(duì)象、數(shù)組和函數(shù)存儲(chǔ)的是內(nèi)存地址,指向同一對(duì)象的變量會(huì)相互影響。判斷類型可用typeof和instanceof,但需注意typeofnull的歷史問題。理解這兩類差異有助于編寫更穩(wěn)定可靠的代碼。

如何檢查數(shù)組是否在JavaScript中包含一個(gè)值 如何檢查數(shù)組是否在JavaScript中包含一個(gè)值 Jul 13, 2025 am 02:16 AM

在JavaScript中檢查數(shù)組是否包含某個(gè)值,最常用方法是includes(),它返回布爾值,語法為array.includes(valueToFind),例如fruits.includes('banana')返回true;若需兼容舊環(huán)境,則使用indexOf(),如numbers.indexOf(20)!==-1返回true;對(duì)于對(duì)象或復(fù)雜數(shù)據(jù),應(yīng)使用some()方法進(jìn)行深度比較,如users.some(user=>user.id===1)返回true。

在C中使用std :: Chrono 在C中使用std :: Chrono Jul 15, 2025 am 01:30 AM

std::chrono在C 中用于處理時(shí)間,包括獲取當(dāng)前時(shí)間、測(cè)量執(zhí)行時(shí)間、操作時(shí)間點(diǎn)與持續(xù)時(shí)間及格式化解析時(shí)間。1.獲取當(dāng)前時(shí)間使用std::chrono::system_clock::now(),可轉(zhuǎn)換為可讀字符串但系統(tǒng)時(shí)鐘可能不單調(diào);2.測(cè)量執(zhí)行時(shí)間應(yīng)使用std::chrono::steady_clock以確保單調(diào)性,并通過duration_cast轉(zhuǎn)換為毫秒、秒等單位;3.時(shí)間點(diǎn)(time_point)和持續(xù)時(shí)間(duration)可相互操作,但需注意單位兼容性和時(shí)鐘紀(jì)元(epoch)

如何將會(huì)話變量傳遞給PHP中的另一頁? 如何將會(huì)話變量傳遞給PHP中的另一頁? Jul 13, 2025 am 02:39 AM

在PHP中,要將一個(gè)會(huì)話變量傳到另一個(gè)頁面,關(guān)鍵在于正確開啟會(huì)話并使用相同的$_SESSION鍵名。1.每個(gè)頁面使用session變量前必須調(diào)用session_start(),且放在腳本最前面;2.在第一個(gè)頁面設(shè)置session變量如$_SESSION['username']='JohnDoe';3.在另一頁面同樣調(diào)用session_start()后通過相同鍵名訪問變量;4.確保每個(gè)頁面都調(diào)用session_start()、避免提前輸出內(nèi)容、檢查服務(wù)器上session存儲(chǔ)路徑可寫;5.使用ses

See all articles