1. <bdo id="8zfej"></bdo>
    <li id="8zfej"><meter id="8zfej"><th id="8zfej"></th></meter></li>

    南京中博教育

    全國咨詢電話:17368476151

    三分鐘了解中博教育
    當(dāng)前位置:南京中博教育 > 學(xué)習(xí)園地 > 編程技巧

    編程有哪些技巧

    來源:南京北大青鳥? ? ? 作者:南京中博教育 ? ??

    編程有哪些技巧呢?其實啊,有很多人都不值得編程也是需要技巧的,學(xué)會技巧然后在學(xué)編程,你會發(fā)現(xiàn)事半功倍,即使是學(xué)編程,掌握了技巧,你也會覺得不那么枯燥乏味。慢慢得,

    編程有哪些技巧呢?其實啊,有很多人都不值得編程也是需要技巧的,學(xué)會技巧然后在學(xué)編程,你會發(fā)現(xiàn)事半功倍,即使是學(xué)編程,掌握了技巧,你也會覺得不那么枯燥乏味。慢慢得,你也會學(xué)著自己總結(jié)編程技巧,找尋其中的樂趣,越來越深入,越來越透徹,就會變得越來越專業(yè)!
     

    for循環(huán)

    1.for循環(huán)變量初始化

    在c語言中,我們常常這樣使用for語句:

    for (int i = 0; i < strlen(s); i++)
     

    這看起來似乎很完美,代碼也很漂亮,讓我們再看看另一種寫法:

    for (int i = 0, len = strlen(s); i < len; i++)
     

    二者唯一的不同在于后者用len變量將字符串s的長度保存了,在條件判斷時直接將i與len比較。第二種方法用一個額外變量len避免了每次條件判斷都要重復(fù)執(zhí)行函數(shù)strlen(s),而執(zhí)行該函數(shù)是非常耗時的(假設(shè)字符串的長度為n,函數(shù)執(zhí)行的復(fù)雜度為O(n)),尤其是當(dāng)for循環(huán)體的語句比較少,字符串比較長的時候。在很多l(xiāng)eetcode題目中,兩種不同的寫法需要的運行時間相差巨大。

    同樣在C++、Java中,這種寫法for (int i = 0; i < s.length(); i++),也是不值得推薦的,盡管C++編譯時期有的編譯器會將length()函數(shù)用內(nèi)聯(lián)或者一個確定的變量來替代,Java也會將其用“屬性”來替代,但我仍然傾向于使用后者。

    有意思的是,在Python的語法中,for循環(huán)用這種方式來表示:

    for i in range(len(s))
     

    這就避免了重復(fù)去求字符串s的長度,這種方法既有語義感,又獲得了高性能。

    1.變量定義位置(for循環(huán)內(nèi)部還是外部)

    
    
    1.  
      //內(nèi)部
    2.  
      for (int i = 0; i < 10; i++)
    3.  
      {
    4.  
       string s = ss[i];
    5.  
       ...
    6.  
      }
    7.  
       
    8.  
       
    9.  
      //外部
    10.  
      string s;
    11.  
      for (int i = 0; i < 10; i++)
    12.  
      {
    13.  
       s = ss[i];
    14.  
       ...
    15.  
      }
     

    如果定義在內(nèi)部,每次循環(huán)都要重新定義string變量s,意味著每次循環(huán)都要調(diào)用構(gòu)造和析構(gòu)函數(shù);而定義在外部每次循環(huán)只需要調(diào)用復(fù)制構(gòu)造函數(shù)。一般建議將大的對象定義到外部,提高運行效率,把小的對象定義在里面,提高程序可讀性。

     

    基本運算和函數(shù)

    1.在乘以2(或2的整數(shù)次冪)或除以2(或2的整數(shù)次冪)的時候盡量用位運算來替代。

    2.盡量減少使用除法運算(可以適當(dāng)轉(zhuǎn)換為乘法,如條件判斷時將if (a == b / c)替換為if (a * c == b)。除法運算需要更多的移位和轉(zhuǎn)換操作,往往需要的時間是相應(yīng)乘法的兩倍)

    3.多使用+=、-=、*=、/=等復(fù)合運算符,以加一為例,效率由高到低是(i++ 、 i += 1 、 i = i + 1)

    4.多掌握一些小巧的庫函數(shù),例如:swap, max, min, sort, qsort, ati, stoi...它們用起來方便,效率更是比一般人寫的代碼高。

     

    inline、const、&修飾符

    inline讓函數(shù)內(nèi)聯(lián),建議編譯器將函數(shù)體代碼“復(fù)制粘貼”到函數(shù)調(diào)用處,在函數(shù)體短小,函數(shù)調(diào)用又比較頻繁的時候能有效避免因函數(shù)調(diào)用帶來的內(nèi)存開銷(因為每一次調(diào)用函數(shù)系統(tǒng)都會生成許多額外的變量)。

    const不僅僅可以保證其修飾的變量不被修改,提高程序的穩(wěn)定性,同時也讓編譯器更好地為我們優(yōu)化代碼。舉個例子:我們?nèi)绻胏onst修飾某一個常量,那么程序中所有用到該常量的地方都會用其值來代替,這樣就避免了讀取其地址而浪費時間。

    &修飾返回值類型和參數(shù)類型表示采取引用的方式傳遞,避免了對象賦值構(gòu)造所需的時間和內(nèi)存。

     

    緩存(cache)和寄存器(register)

    除了CPU,就是寄存器和緩存的訪問速度高了,一般不建議我們自己定義寄存器變量和控制數(shù)據(jù)緩存,編譯器會自動幫我們把經(jīng)常用到的一些數(shù)據(jù)放到緩存和寄存器中。但是,了解一些編譯器控制數(shù)據(jù)的依據(jù)對編程也有極大幫助。一般來說,放到寄存器/緩存的數(shù)據(jù)優(yōu)先級為:用register修飾的變量,循環(huán)控制變量,auto局部變量,靜態(tài)變量,用戶自己分配的內(nèi)存數(shù)據(jù)。

     

    迭代器(iterator)

    1.訪問容器中元素的時候盡量使用迭代器而不是下標(biāo)或者指針。在剛從C語言轉(zhuǎn)到C++的那段時間,我非常不適應(yīng)迭代器的用法,總覺得下標(biāo)訪問多好,與for循環(huán)搭配在一起簡直是無敵的存在。后來我才慢慢發(fā)掘出迭代器的眾多優(yōu)勢。首先,迭代器訪問元素類似與指針,相對于下標(biāo)訪問不用根據(jù)下標(biāo)值計算地址,這在循環(huán)中能夠節(jié)省不少時間。其次,迭代器作為指針一種延拓,能更好的代表并操作其所指的對象,而在下標(biāo)訪問中我們往往用一個int值pos來表示pos下標(biāo)下的元素,沒有面向?qū)ο缶幊痰闹庇^。再次,迭代器為我們訪問各種容器(數(shù)組,vector,list,map,queue,deque,set …)中的元素提供了統(tǒng)一的方法,其作用類似于“語法糖”,讓編程更加簡單、方便。

    2.另外在使用迭代器的自增和自減運算符需要注意,iterator++,和++iterator的效率有天壤之別。兩種自增方式的運算符重載如下:

    
    
    1.  
      iterator & operator++()
    2.  
      {  // 前增
    3.  
       ++*this;
    4.  
       return (*this);
    5.  
      }
    6.  
       
    7.  
      iterator operator++(int)
    8.  
      {  // 后增
    9.  
       iterator temp = *this;
    10.  
       ++*this;
    11.  
       return (temp);
    12.  
      }
     

     

    • 后增(iterator++)相對于前增(++iterator)創(chuàng)建了一個臨時迭代器temp,并將其返回,而前增直接返回原來迭代器的引用。在for循環(huán)中的頻繁自增操作中,創(chuàng)建臨時迭代器temp,以及返回temp時調(diào)用的復(fù)制構(gòu)造函數(shù)所需的時間不容忽視。

     

    vector容器

    vector容器毫無疑問是C++STL使用為頻繁的容器了,當(dāng)然這個強大容器的使用也包含了很多的小技巧。

    1.在適當(dāng)時候使用emplace和emplace_back函數(shù)來替代insert和push_back函數(shù)。它們之間的區(qū)別很明顯,insert和push_back函數(shù)參數(shù)是vector容器里面的模板對象,而帶emplace的函數(shù)參數(shù)是模板對象的構(gòu)造函數(shù)的參數(shù),這意味著后者將模板對象插入到vector容器的過程中不用先生成好對象,而是可以直接利用參數(shù)構(gòu)造。當(dāng)然如果模板對象已經(jīng)是生成好的,那就沒有必要用emplace函數(shù)了。在很多循環(huán)遞歸迭代中,往往需要反復(fù)向vector容器中添加對象,這時候額外構(gòu)造一個對象所需要的時間和空間就不容忽視了,因此這是一個vector進(jìn)階用法的好trick。

    2.vector容器的底層實現(xiàn)是數(shù)組,并且在當(dāng)元素大于大容量的時候會重新生成一個更大的數(shù)組,將原來數(shù)組中的對象復(fù)制構(gòu)造到新數(shù)組中。由于要重新分配大量內(nèi)存以及反復(fù)調(diào)用復(fù)制構(gòu)造函數(shù),這對時間和空間的開銷是巨大的。為了減少內(nèi)存的重新分配,我們可以適當(dāng)?shù)墓烙嬑覀冃枰4娴脑財?shù)量,并在vector初始化的時候指定其capacity。這種方法很直接但也有其缺點,就是我們往往很難在開始的時候就估計準(zhǔn)確我們要保存的元素數(shù)量(如果能,我們就直接用數(shù)組得了)。一個很好的解決辦法是:將vector中保存的元素改為指針,指針指向我們真正想要保存的對象。由于指針相對于其所指向的對象來說占用內(nèi)存很小,而且在復(fù)制的時候不用調(diào)用復(fù)制構(gòu)造函數(shù),因此以上提到的一些缺點都能很好的克服。事實上,對于能夠熟練控制內(nèi)存分配的老碼農(nóng)來說,這種vector + 指針的方式是十分完美的。

     

    if條件判斷

    在進(jìn)入討論之前,我們先思考下面這個例子:

    一個班的數(shù)學(xué)成績?nèi)缦拢?4、76、78、94、97、68、77、65、54、89…,總共有50個數(shù)據(jù)。要求用程序?qū)⒎謹(jǐn)?shù)為優(yōu)秀(>=80)、良好(>=70)、及格(>=60)、不及格(>=0)四個分?jǐn)?shù)段。

    
    
    1.  
      for 所有學(xué)生分?jǐn)?shù)
    2.  
       if 分?jǐn)?shù) < 60
    3.  
         歸為不及格段
    4.  
       else if 分?jǐn)?shù) < 70
    5.  
         歸為及格段
    6.  
       else if 分?jǐn)?shù) < 80
    7.  
         歸為良好段
    8.  
       else 
    9.  
         歸為優(yōu)秀段
     

    這個偽代碼邏輯沒有問題,但是就這個數(shù)據(jù)來看這段代碼運行效率糟透了。由于這個班的數(shù)學(xué)成績絕大多數(shù)是良好和優(yōu)秀,而這個程序需要三次if判斷才能將分?jǐn)?shù)歸為良好,三次if判斷加上一個else才能將分?jǐn)?shù)歸為優(yōu)秀,所以絕大多數(shù)前兩個if判斷是不必要的。我們將if判斷語句的順序變換下:

    
    
    1.  
      for 所有學(xué)生分?jǐn)?shù)
    2.  
       if 分?jǐn)?shù) >= 80
    3.  
         歸為優(yōu)秀段
    4.  
       else if 分?jǐn)?shù) >= 70
    5.  
         歸為良好段
    6.  
       else if 分?jǐn)?shù) >= 60
    7.  
         歸為及格段
    8.  
       else 
    9.  
         歸為不及格段
     

    在這個偽代碼中絕大多數(shù)分?jǐn)?shù)都在前兩個if語句中完成了分段。兩者的時間效率相差巨大,實際運行也發(fā)現(xiàn),前者是后者運行時間的兩倍多。

     

    switch分支判斷

    switch語句的底層實現(xiàn)主要有三種方式:轉(zhuǎn)換為if else 語句,跳轉(zhuǎn)表,樹形結(jié)構(gòu)。當(dāng)分支比較小時,編譯器傾向于轉(zhuǎn)換為if else語句,當(dāng)分支比較多,分支范圍很廣時,用樹形結(jié)構(gòu),當(dāng)分支數(shù)量不算多,分支范圍緊湊時,用跳轉(zhuǎn)表。跳轉(zhuǎn)表的底層實現(xiàn)是數(shù)組映射,對條件轉(zhuǎn)換的效率為O(1),相比于另外兩種方式優(yōu)勢明顯,因此我們應(yīng)該盡量控制分支的數(shù)量,以及讓各個分支的int型數(shù)據(jù)緊湊。

    希望大家能夠掌握編程技巧,在編程的道理路上越走越遠(yuǎn)!

    分享到:

    相關(guān)閱讀:

    近期文章

    搶試聽名額

    名額僅剩66名

    教育改變生活

    WE CHANGE LIVES

    主站蜘蛛池模板: 一本大道无香蕉综合在线| 天天综合天天综合色在线| 狠狠色丁香九九婷婷综合五月| 精品国产第一国产综合精品| 综合五月激情二区视频| 色偷偷亚洲第一综合| 国产综合无码一区二区三区| 亚洲AV综合色区无码二区偷拍| 色综合91久久精品中文字幕| 久久婷婷五月综合色丁香| 亚洲伊人成无码综合网 | 色婷婷综合久久久中文字幕| 狠狠色丁香久久婷婷综合_中| 国产成人亚洲综合| 亚洲av永久中文无码精品综合| 久久综合伊人77777麻豆| 久久综合偷偷噜噜噜色| 久久精品国产9久久综合| 亚洲伊人久久成综合人影院| 国产色丁香久久综合| 精品亚洲综合在线第一区| 亚洲综合色在线观看亚洲| 狠狠色丁香婷婷久久综合蜜芽| 亚洲综合久久久久久中文字幕| 综合在线视频精品专区| 亚洲国产婷婷综合在线精品| 热の无码热の有码热の综合| 亚洲狠狠婷婷综合久久蜜芽| 五月婷婷综合免费| 伊人色综合视频一区二区三区| 国产综合免费精品久久久| 青青热久久久久综合精品| 久久综合五月丁香久久激情| 亚洲狠狠婷婷综合久久久久| 国产亚洲综合色就色| 久久精品国产亚洲综合色| 一本一道久久精品综合| 色综合天天综合狠狠| 色婷婷久久综合中文久久蜜桃| 国产精彩对白综合视频| 天堂无码久久综合东京热|