1. 程式人生 > >函式部分課程筆記與學習心得

函式部分課程筆記與學習心得



                 函式章節課程筆記

 

  1. 基礎知識

    1. 函式的定義

資料型別 函式名(形勢引數表)

{   

函式體

}

資料型別是函式的返回值型別,若資料型別為void,是無返回值型別;

形參必須要有有型別說明,形參可以是變數名,陣列名或指標名,它的作用是實現主調函式與被調函式之間的關係;

函式不允許有巢狀定義

,但是允許巢狀使用.

    1. 函式的宣告

      型別說明符 被調函式名(含型別說明的引數表);

      如果是在所有函式定義之前聲明瞭函式原形,那麼該函式原形只在本程式檔案中任何的地方都有效,也就是說在本程式檔案中任何地方都可以依照該原形呼叫相應的函式.如果是在某個主調函式內部聲明瞭被呼叫函式的原形,那麼該原形就只能在這個函式內部有效.

    2. 函式的傳值呼叫

      1. 傳值呼叫

        這種呼叫方式是將實參的資料值傳遞給形參,即將實參值拷貝一個副本存放在被呼叫函式的棧區中。在被呼叫函式中,形參值可以改變,但是影響主調函式的實參值。引數傳遞的方向只是從實參到形參,簡稱單向值傳遞。

        例如以下程式碼:

        #include<iostream>

        using namespace std;

        Void swap(int a,int b)

        { int  tmp=a;

        a=b;

        b=tmp;}

        int main()

        {int c=1,d=2;

        swap(c,d);

        cout<<c<<’ ‘<<d<<endl;

        return 0;

        }                  //程式輸出為:1 2

        在此例中,雖然

        swap函式中交換了a,b兩數的值,但是在main函式中卻沒有交換因為swap函式只是交換c,d兩變數的副本值,實參值並沒有改變,並沒有達到交換的目的。

      2.  地址傳遞

        如果在函式定義時將形參說明成指標,呼叫函式時就需要指定地址形式的實參。這時的引數傳遞方式就是按地址傳遞方式。

        按地址傳遞與按指值傳遞的不同在於:形參指標和實參指標指向同一個地址。因此,被呼叫函式中對形參指標所指向的地址中內容的任何改變都會影響到實參。

        #include<iostream>

        using namespace std;

        void swap(int*,int*);

        int main()

        { int a=3,b=4;

        cout<<”a=”<<a<<”,b=”<<b<<endl;

        system(“pause”);

        return 0;

        }

        void swap(int *x,int *y)

        {int t=*x;

        *x=*y;

        *y=t;

        }

      3.  引用傳遞

         如果以引用為引數,則既可以使得對形參的任何操作都能改變相應的資料,又使得函式呼叫顯得方便,自然。引用傳遞方式是在函式定義時在形參前面加上引用運算子”&”

        #include<iostream>

        using namespace std;

        void swap(int &,int &);

        int main()

        {int a=3,b=4;

        cout<<”a=”<<a<<”,b=”<<endl;

        swap(a,b);

        cout<<”a=”<<a<<”,b=”<<b<<endl;

        system(“pause”);

        return 0;

        }

        Void swap(int &x,int &y)

        {int t=x;

        x=y;

        y=t;

        }

    3. 遞迴演算法

      1.  概念

         當函式的定義中,其內部操作又直接間接的出現對自身的呼叫,則稱這樣的程式巢狀定義為遞迴定義。

        函式直接呼叫其自身,稱為直接遞迴;函式間接呼叫其自身,稱為間接遞迴。

      2.    簡單的說,遞迴演算法的本質就是自己呼叫自己,用呼叫自己的方法去處理問題,可使解決問題變得簡潔明瞭。

        在遞迴程式的遞迴過程中,一般具有如下模式:

        將呼叫程式的返回地址,相應的呼叫前的變數都儲存在系統棧隊中。

        執行被呼叫的函式.

        若滿足退出遞迴的條件,則退出遞迴,並從棧頂上彈回返回地址,取回儲存起來的變數值,繼續沿著返回地址,向下執行程式;

        否則繼續遞迴呼叫,只是遞迴呼叫的引數發生變化:增加一個量或減少一個量,重複執行直到遞迴呼叫結束。

      3.  能夠用遞迴演算法解決的問題,一般滿足如下要求:

        需要求解的問題可以化為子問題求解,其子問題的求解方法與原問題相同之時規模上的增加或減少;

        遞迴呼叫的次數是有限的,必須有遞迴結束的條件(稱為遞迴邊界)

2.經典例題

1函式的簡單題

以驗證哥德巴赫猜想為例

驗證歌德巴赫猜想,即:任意一個大於2的偶數均可表示成兩個素數之和。

輸入

輸入只有一個正整數x(x是偶數,x <= 2000 x > 2)

輸出

輸出這個數的所有分解形式,形式為:
x = y + z
其中x為待驗證的數,yz滿足y + z = x,而且 y<= zyz均是素數。
如果存在多組分解形式,則按照y的升序輸出所有的分解,每行一個分解表示式。

Codeing

#include <iostream>

#include <cmath>

using namespace std;

int main()

{void godbaha(int);

 int n;

 

 cin>>n;

 godbaha(n);

 return 0;

}

void godbaha(int n)

{int prime(int);

 int a,b;

 for(a=3;a<=n/2;a=a+2)

   {if(prime(a))

      {b=n-a;

       if(prime(b))

    cout<<n<<" "<<"="<<""<<a<<" "<<"+"<<" "<<b<<endl;}

    }

}

 

int prime(int m)

{int i,k=sqrt(m);

 for(i=2;i<=k;i++)

 if(m%i==0) break;

 if (i>k) return1;

 else     return 0;

}

這道題定義了兩個函式,一個是哥德巴赫猜想的輸出形式,其次就是 素數的判斷方法。

求兩個正整數的最大公約數

輸入

兩個正整數

輸出

最大公約數

Codeing

#include<iostream>

using namespace std;

int gcd(int,int);

int main()

{ int a,b;

         cin>>a>>b;

         cout<<gcd(a,b)<<endl;

         return 0;

         }

int gcd(int x,int y)

{   int g;

         if(y==0) g=x;

         else g=gcd(y,x%y);

         return g;

         }

這道題用到了遞迴的簡單演算法,在函式中呼叫了自身

這種求最大公約數的演算法就叫做 輾轉相除法

m%n的餘數

如果餘數不為0,則讓m=n,n=餘數,重複上一步,

如果餘數為0,則終止呼叫子程式

此時輸出n的值;

③求兩個正整數的最小公倍數

描述

輸入兩個正整數,求最小公倍數

輸入

兩個正整數

輸出

最小公倍數

Codeing

#include<iostream>

using namespace std;

int gad(int,int);

int main()

{ int a,b;

         cin>>a>>b;

         cout<<(a*b)/gad(a,b)<<endl;

         return 0;

         }

int gad(int x,int y)

 { int g;

          if(y==0) g=x;

          else g=gad(y,x%y);

         

          return g;

      }

最小公倍數=兩個數的乘積/最大公約數

2)遞迴演算法的題目

描述

給出一個正整數a,要求分解成若干個正整數的乘積,即a = a1 * a2 * a3 * ... * an,並且1 < a1<= a2 <= a3 <= ... <= an,問這樣的分解的種數有多少。注意到a= a也是一種分解。

輸入

1行是測試資料的組數n,後面跟著n行輸入。每組測試資料佔1行,包括一個正整數a (1 < a < 32768)

輸出

n行,每行輸出對應一個輸入。輸出應是一個正整數,指明滿足要求的分解的種數

樣例輸入

2

2

20

樣例輸出

1

4

Codeing

#include<iostream>
using namespace std;
 
int find(int a,int b)
{
        int sum=0;
        if(a==1) return 1;
for(int i=b;i<=a;i++)
if(a%i==0)
{sum+=find(a/i,i);}
return sum;
 
}
int main()
{int n,a,i;
cin>>n;
for(i=1;i<=n;++i)
{cin>>a;
cout<<find(a,2)<<endl;}
return 0;
}

這道題運用了遞迴演算法,把可能的方式一一枚舉出來即可

②八皇后的問題

描述

在國際象棋棋盤上放置八個皇后,要求每兩個皇后之間不能直接吃掉對方。

輸入

無輸入。

輸出

按給定順序和格式輸出所有八皇后問題的解(見Sample Output)。

樣例輸入

樣例輸出

No. 1

1 0 0 0 0 0 0 0

0 0 0 0 0 0 1 0

0 0 0 0 1 0 0 0

0 0 0 0 0 0 0 1

0 1 0 0 0 0 0 0

0 0 0 1 0 0 0 0

0 0 0 0 0 1 0 0

0 0 1 0 0 0 0 0

No. 2

1 0 0 0 0 0 0 0

0 0 0 0 0 0 1 0

0 0 0 1 0 0 0 0

0 0 0 0 0 1 0 0

0 0 0 0 0 0 0 1

0 1 0 0 0 0 0 0

0 0 0 0 1 0 0 0

0 0 1 0 0 0 0 0

……

Codeing

#include<bits/stdc++.h>

using namespace std;

int b[101]={0},c[101]={0},d[101]={0};

int a[101];

int sum=0;

int print();

int search(int i);

int main()

{search(1);//從第一個皇后開始

return 0;}

int search(int i)

{

for(int j=1;j<=8;j++)//每個皇后都有八個位置可以擺放

{if((b[j]==0)&&(c[i+j]==0)&&(d[i-j+7]==0))//尋找方皇后的位置,d陣列的下標不能為負,可以通過+7來比較

 

{a[i]=j;//擺放皇后,表示的是第i行第j列放了皇后

b[j]=1;//下面的bool型別表示的是宣佈佔領

c[i+j]=1;

d[i-j+7]=1;

if(i==8)

{sum++;

print();

}

else search(i+1);//繼續遞迴之下一個

b[j]=0;//回溯一步

c[i+j]=0;

d[i-j+7]=0;

}

}

}

int print()

{cout<<"No. "<<sum<<endl;

for(int j=1;j<=8;++j)

{for(int i=1;i<=8;++i)

if(j==a[i]) cout<<1<<" ";

else cout<<0<<" ";

cout<<endl;

}

}

這道題運用到了回溯的方法

可以從矩陣的特點上找到規律

如果在同一行則行號相同,同一列則列號相同

,在/對角線上,則行列之和相同,在\對角線上,則行列之差的絕對值相同;

3.學習心得

對於函式部分 我覺得首先是一個在除錯程式時,方便的方法,

對於程式的執行時間,佔用記憶體並無幫助,還有傳值呼叫不能返回兩個值,可以用傳引用和傳地址的方式來實現

然後,是遞迴演算法的那一部分,我覺得遞迴演算法最重要的一個部分是找到遞迴表示式,也就是找到問題與問題之間的聯絡,還有就是找到遞迴邊界,比如算一個數的階乘,可以轉化為 1=10=1

  1. int Factorial(int n)  

  2. {  

  3.     if(n==1)  

  4.         return 1;  

  5.     return n*Factorial(n-1);  

  6. }  

    這樣 可以看到 遞迴的問題邊界是n==1,遞迴表示式是n*factorial(n-1)

    遞迴演算法中還有就是 搜尋與回溯,比如八皇后的問題,在考慮這個問題的時候,要想到 八個皇后只能獨佔一列一行兩個方向的對角線,那麼我們可以這樣考慮 要將所在的位置用bool型別的陣列定義佔領,還要繼續向下一步搜尋,最後回溯一步,就完成。

    再比如著名的斐波那契數列

    題目大體意思是 後一項數的大小等於前兩項的數之和

    1 1 2 3 5 8 13……

    那麼這個程式可以這樣來寫

1.  int

相關推薦

函式部分課程筆記學習心得

                  函式章節課程筆記   基礎知識 函式的定

Stanford機器學習課程筆記3-學習理論部分

簡單補充點SVM吧關於SVM的筆記部落格內沒有整理,主要是因為另外,關於LibSVM的理論,除了Andrew Ng給的Handout外,推薦的就是林智仁兩份資料:好了,SVM不多說了,本文主要是要說一些偏機器學習中實踐的東西(雖然標題是學習理論,但其實是機器學習實踐更恰當些)

馬哥學習----李洋個人筆記----ansible學習心得

server books 出錯 pts images 此外 .com handlers play 自動運維化工具 ansible LINUX發展趨勢:越來越強大的工具,通過子命令來實現,而不是通過選項。 ANSIBLE擁有上千個模塊(子命令),ANSIBLE適用於200臺機

馬哥學習----李洋個人筆記----DNS學習心得

完整 client dom 回復 can 保存 lib 外網 更新 DNS服務 DNS:Domain Name Service 是應用層協議 基於C/S(客戶端/服務端來實現),共有2個端口分別是 53/udp以及 53/tcp BIND:Bekerley Internat

CS229機器學習課程筆記---監督學習之線性模型

監督學習 首先,我們考慮以下資料集,基於此資料集預測房價。 可以畫出如下散點圖: 定義符號 m — 訓練集樣本總數 x — 輸入變數/輸入特徵 (例,living area) y — 輸出/目標變數(例,price) { (x(i),y(i)) ;i =

深入學習RBAC系列模型——RBAC0模型的開發學習心得

RBAC0模型簡介:   RBAC0是RBAC系列模型中的基礎模型,隨後的RBAC系列模型都將按照RBAC0基礎模型進行改進,所以學習RBAC模型就必須要牢牢掌握RBAC0模型的思想以及使用方法。 R

臺大林軒田機器學習課程筆記----機器學習初探及PLA演算法

機器學習初探 1、什麼是機器學習 學習指的是一個人在觀察事物的過程中所提煉出的技能,相比於學習,機器學習指的就是讓計算機在一堆資料中通過觀察獲得某些經驗(即數學模型),從而提升某些方面(例如推薦系統的精度)的效能(可測量的)。 2、機器學習使用的條件 需要有規則可以學習 有事先準

C++學習筆記學習心得

本篇部落格是本人根據百度加上自己的修改得到的,可以算轉載。Split函式是C++沒有的,需要自己搞,網上給出的程式碼說要用strtok,但是vs2017不支援strtok,只支援strtok_s......所以這就很難受了,網上也有strtok_s的使用方法,這裡我給出我整理

卷積神經網絡學習筆記心得(4)池化

設計者 位置 浪費 需要 三種 限制 右移 理論 alt 圖片經過卷積、激活後的結果一般帶有大量原圖信息。 上圖中卷積核提取的是豎直方向上的連續像素,但是,被增強的像素只占了結果的1/3,對於多層網絡,其余重要性較低的信息也被傳入了下一層網絡,造成了不必要的浪費,因此需要

斯坦福CS229機器學習課程筆記一:線性迴歸梯度下降演算法

機器學習三要素 機器學習的三要素為:模型、策略、演算法。 模型:就是所要學習的條件概率分佈或決策函式。線性迴歸模型 策略:按照什麼樣的準則學習或選擇最優的模型。最小化均方誤差,即所謂的 least-squares(在spss裡線性迴歸對應的模組就叫OLS即Ordinary Least Squares):

神經網路深度學習課程筆記(第三、四周)

接著學習吳恩達老師第三、四周的課程。(圖片均來自吳恩達老師課件)   第三週 1. 普通的淺層網路                        

神經網路深度學習課程筆記(第一、二週)

   之前結束了吳恩達老師的機器學習的15節課,雖然看得很艱辛,但是也算是對於機器學習的理論有了一個入門,很多的東西需要不斷的思考以及總結。現在開始深度學習的學習,仍然做課程筆記,記錄自己的一些收穫以及思考。   第一週 1. ReLU (Rectified

Go語言學習筆記-函式部分(三)

函式部分 函式基本組成:關鍵字func、函式名、引數列表、返回值、函式體、返回語句 例子: func Add(int a, int b) (return int, err error){ ....函式體... } 如果相鄰引數型別相同,可以簡寫,eg: a,b int //a、b引數型別相同 函式

資料結構演算法之美 課程筆記一 如何抓住重點,系統高效地學習資料結構演算法?

什麼是資料結構?什麼是演算法? 從廣義上講,資料結構就是指一組資料的儲存結構。演算法就是操作資料的一種方法。 從狹義上講,是指某些著名的資料結構和演算法,比如佇列、棧、堆、二分查詢、動態規劃等。 那資料結構和演算法有什麼關係呢? 資料結構和演算法是相輔相成的。資料結構是為演算法服務的

虛擬函式多型課程筆記

虛擬函式與多型 一、基礎知識 1.多型性是指一個名字,多種語義;或介面相同,多種實現。 過載函式是多型性的一種簡單形式。 虛擬函式允許函式呼叫與函式體的聯絡在執行時才進行,稱為動態聯編,switch語句是一個動態聯編的例子。程式編譯階段不能預知switch表示式的值,一直要等到程式執行時,對

吳恩達《神經網路深度學習課程筆記歸納(二)-- 神經網路基礎之邏輯迴歸

上節課我們主要對深度學習(Deep Learning)的概念做了簡要的概述。我們先從房價預測的例子出發,建立了標準的神經網路(Neural Network)模型結構。然後從監督式學習入手,介紹了Standard NN,CNN和RNN三種不同的神經網路模型。接著介紹了兩種不

吳恩達《神經網路深度學習課程筆記歸納(三)-- 神經網路基礎之Python向量化

上節課我們主要介紹了邏輯迴歸,以輸出概率的形式來處理二分類問題。我們介紹了邏輯迴歸的Cost function表示式,並使用梯度下降演算法來計算最小化Cost function時對應的引數w和b。通過計算圖的方式來講述了神經網路的正向傳播和反向傳播兩個過程。本節課我們將來

機器學習筆記之五——目標函式、經驗風險結構風險、正則項

一、常見的目標函式(loss/cost function)   二、經驗風險與結構風險    經驗風險 L(f) 就是以上損失函式,描述的是模型與訓練資料的契合程度。   結構風險Ω(f)對應於過擬合問題,用正則項解決過擬合是結構風險的課

Stanford機器學習課程筆記4-Kmeans高斯混合模型

這一部分屬於無監督學習的內容,無監督學習內容主要包括:Kmeans聚類演算法、高斯混合模型及EM演算法、Factor Analysis、PCA、ICA等。本文是Kmeans聚類演算法、高斯混合模型的筆記,EM演算法是適用於存在latent/hidden變數的通用演算法,高斯混

Coursera吳恩達《神經網路深度學習課程筆記(2)-- 神經網路基礎之邏輯迴歸

上節課我們主要對深度學習(Deep Learning)的概念做了簡要的概述。我們先從房價預測的例子出發,建立了標準的神經網路(Neural Network)模型結構。然後從監督式學習入手,介紹了Standard NN,CNN和RNN三種不同的神經網路模型。接