C++學(xué)習(xí)(計蒜客)

學(xué)習(xí)C++

1. 斐波納切數(shù)列

斐波那契數(shù)列是一種非常有意思的數(shù)列,由 00 和 11 開始,之后的斐波那契系數(shù)就由之前的兩數(shù)相加。用數(shù)學(xué)公式定義斐波那契數(shù)列則可以看成如下形式:
?Fn表示斐波那契數(shù)列的第n項,你能知道斐波那契數(shù)列中的任何一項嗎?

#include <iostream>
using namespace std;
int Fibonacci(int pos);
int main(){
    int pos;
    cin >> pos;
    int value;
    value = Fibonacci(pos);
    cout << value << endl;
    return 0;
}
int Fibonacci(int pos){
    if (pos == 0){
        return 0;
    }else if (pos == 1){
        return 1;
    }
    else{
        return Fibonacci(pos - 1) + Fibonacci(pos - 2);
    }
}```

###2. 矩陣翻轉(zhuǎn)
曉萌最近在做一個翻轉(zhuǎn)圖片的應(yīng)用,你可能也知道,圖片其實(shí)是由一個個的點(diǎn)組成的。于是,曉萌想先做一個可以翻轉(zhuǎn)矩陣的程序,來解決他問題的核心部分。
輸入第一行包括由空格分開的整數(shù)M、N、T(0 < M < 200,0 < N < 200,T=0或1),其中M和N分別表示待處理矩陣的行數(shù)與列數(shù),T為0時表示左右翻轉(zhuǎn),為1時表示上下翻轉(zhuǎn)。
之后的M行,每行包括由空格分隔的N個整數(shù),依次為輸入矩陣的每一行的數(shù)據(jù)。
輸出包括M行N列,每個數(shù)字之間用一個空格分隔,每一行行末均有一個空格,表示的是按照要求翻轉(zhuǎn)后的矩陣。
 

include <iostream>

using namespace std;
int main(){
int row,col,lrud;
cin >> row >> col >> lrud;
int arr[row][col];
//i不能到5
for (int i=0; i<row; i++){
for(int j=0; j<col; j++){
cin >> arr[i][j];
}
}
//左右翻轉(zhuǎn)
if (lrud == 0){
for (int i1=0; i1<row; i1++){
for (int j1=col-1; j1>=0; j1--){
cout << arr[i1][j1] << " ";
}
cout << endl;
}
}else if(lrud == 1){ //上下翻轉(zhuǎn)
for (int i1=row-1; i1>=0; i1--){
for (int j1=0; j1<col; j1++){
cout << arr[i1][j1] << " ";
}
cout << endl;
}
}
}

###3. 位操作

include<iostream>

using namespace std;
int main(){
int a;
cin>>a;
//hex指輸出16進(jìn)制數(shù),oct是八進(jìn)制數(shù),dec是十進(jìn)制,bin二進(jìn)制
cout << hex << a << " " << ~a << endl;
return 0;
}```

4. cstdio庫

#include <cstdio>引入C風(fēng)格的輸入和輸出,scanf和printf比cout和cin要高效。

5. 指針

一個指針是一個地址,是一個常量,而一個指針變量卻可以被賦予不同的指針值,是變量。定義指針的目的是通過指針去訪問內(nèi)存單元。
指針變量的賦值只能被賦予地址數(shù)據(jù),錯誤賦值將無法通過編譯或者在運(yùn)行中出錯。變量的地址是系統(tǒng)分配,使用&進(jìn)行取地址,*是指針運(yùn)算符,間接訪問運(yùn)算符,通過指針變量存儲的地址來訪問變量。

#include<iostream>
using namespace std;
int main(){
    int a = 0, b = 0, *p, *p1, *p2;
    cin >> a >> b;
    p1 = &a;
    p2 = &b;
    if (a<b){
        p = p1;
        p1 = p2;
        p2 = p;
    }
    cout << "a=" << a << ",b=" << b << endl;
    cout << "max=" << *p1 << ",min=" << *p2 << endl;
    return 0;
}```
函數(shù)的形式參數(shù)是一個指針類型的變量,*表示指針變量的類型聲明,square函數(shù)中的指針指向了主函數(shù)中的變量,square函數(shù)中的指針值的運(yùn)算將改變主函數(shù)中變量num的值。

include<iostream>

using namespace std;
void square(int *n){
*n = *n * *n;
}
int main(){
int num = 2;
cout<<"The original number is "<<num<<endl;
square(&num);
cout<<"The new value of number is "<<num<<endl;
return 0;
}```

6. 引用

引用就是某一變量的一個別名,對引用的操作與對變量直接操作完全一樣,定義引用的表示方法與定義指針類似,只是用&代替了*,例如int a,&ra=a,ra是目標(biāo)引用名,ra=1;等價于a=1,并且&只是在聲明的時候起標(biāo)識作用,不同于取地址。
聲明一個引用,不是新定義了一個變量,它本身不是一種數(shù)據(jù)類型。
不能建立引用的數(shù)組,無法建立一個由引用組成的集合,但是可以建立數(shù)組的引用。
下面是引用做函數(shù)參數(shù)的例子,同樣和指針一樣可以修改main中的變量值。

#include<iostream>
using namespace std;
void square(int &n){
    n = n * n;
}
int main(){
    int num = 2;
    cout<<"The original number is "<<num<<endl;
    square(num);
    cout<<"The new value of number is "<<num<<endl;
    return 0;
}```
###7. 內(nèi)存分區(qū)
計算機(jī)中的內(nèi)存在用于編程的時候,被人為的進(jìn)行了分區(qū),分為棧區(qū)stack,堆區(qū)heap,全局區(qū)(靜態(tài)區(qū)Static),文字常量區(qū),程序代碼區(qū)。
函數(shù)的參數(shù)值,局部變量值都被存在了棧區(qū),這部分的內(nèi)存是系統(tǒng)幫助來進(jìn)行管理的。
堆區(qū)的內(nèi)存,是由程序員來進(jìn)行分配和釋放的,使用堆內(nèi)存的原因是棧上內(nèi)存較少,不夠用,系統(tǒng)管理內(nèi)存的方式比較死板,不方便用。堆上的內(nèi)存,程序員手動分配后,如果不釋放就有可能出現(xiàn)內(nèi)存泄漏。
全局變量和靜態(tài)變量的存儲是在一塊的,初始化的全局變量和靜態(tài)變量在一塊區(qū)域,為初始化的全局變量和未初始化的靜態(tài)變量在相鄰的另一塊區(qū)域。程序結(jié)束后由系統(tǒng)釋放。
文字常量區(qū)用于儲存常量字符串的,程序結(jié)束后由系統(tǒng)釋放。
程序代碼區(qū)用于存放函數(shù)體的二進(jìn)制代碼。
`int *arr = new int[n];` new用于申請堆上空間的運(yùn)算符,申請空間的最開始位置首地址,用前面聲明的指針進(jìn)行指向,從而可以像用數(shù)組一樣用指針名使用這塊空間。

include<iostream>

using namespace std;
int main(){
int i,n;
cin>>n;
int *arr= new int[n];

//以下代碼對一個數(shù)組第一位進(jìn)行了賦值
arr[0]=1;

//以下代碼對一個長度為n的數(shù)組第二位開始依次做計算,并輸出最后一個值結(jié)果
for(i=1;i<n;i++){
    arr[i]=arr[i-1]+i;
}
cout<<arr[n-1];
//請在下一行釋放內(nèi)存空間
delete []arr;
    arr = NULL;
return 0;

}```
new來動態(tài)申請分配堆內(nèi)存
申請單個對象

int *p;
p = new int;
//或者申請的堆內(nèi)存中直接包含值
int *p;
p = new int(100);```
動態(tài)申請數(shù)組

int *p;
p = new int[n];```
圓括號是用來賦初值的,方括號是用來說明申請堆空間大小的。
內(nèi)存釋放
delete加指針名的形式進(jìn)行釋放,如果指針指向的空間是數(shù)組,那么需要在delete后加上[]進(jìn)行標(biāo)識。然后將arr指針數(shù)組指向NULL,使之成為空指針。

8. 鏈表

#include <iostream>
using namespace std;

struct List
{
    int num;
    List *next;
};

List *head;

void Insert(List *&head)
{
    //在下面編寫插入代碼
    List *node = NULL;
    node = new List;
    cin >> node->num;
    node -> next = NULL;
    List *q, *p;
    //如果插入的值本身小于head的值,插入到最前面
    if(node->num <= head->num){
        node->next = head;
        head = node; 
        return ;
    }
    p = head; //記錄head指針
    q = head->next; //記錄指向head后面的
    while(q!=NULL){
        if(node->num > q->num){
            //大于的話,判斷下一個
            p = q;
            q = q->next;
        }else{
            break;
        }
    }
    p->next = node;
    node->next = q;
}
void deleteNode(List *&head)
{
    //在下面編寫刪除代碼
    int num;
    cin >> num;
    List *p = NULL, *q = NULL;
    p = head;
    if(p->num == num){
        head = p->next;
        delete p;
        return;
    }
    //如果刪除的節(jié)點(diǎn)不是頭節(jié)點(diǎn)
    q = p->next;
    while(q != NULL){
        if(q->num == num){
            p->next = q->next;
            delete q;
            return;
        }
        if(q->num > num){
            return;
        }
        p = q;
        q = q->next;
    }
    return ;
}
List *Create()
{
    List *p = NULL;
    List *q = NULL;
    head = NULL;
    for ( int i = 0; i < 3; i++ ) {
        p = new List;
        p->num = i * 2;
        if ( head == NULL ) {
            head = p;
        }
        else {
            q->next = p;
        }
        q = p;
    }

    if ( head != NULL ) {
        q->next = NULL;
    }

    return head;
}

void displayList(List *head)
{
    while ( head != NULL ) {
        cout << head->num;
        head = head->next;
        if ( head != NULL ) {
            cout << "->";
        }
    }
    cout << endl;
}

int main() {
    Create();
    Insert(head);
    displayList(head);
    return 0;
}```
###9. 單鏈表部分逆置
給定一個固定的單鏈表,輸入兩個數(shù)begin和end。將下標(biāo)為begin到end之間的內(nèi)容逆置。

給定的單鏈表為:0->2->4->6->8->10->12->14->16->18

測試數(shù)據(jù)確保begin和end不會超出單鏈表的長度范圍,并且end>=begin

include <iostream>

using namespace std;

struct List
{
int num;
List *next;
};

List *head;

void reverse(int begin, int end, List *&head)
{
//在這個函數(shù)中編寫你的代碼
if(end <= begin || begin < 0 || end > 9){
return;
}
if(begin == 0){
List *p = head;
List *qian = p;
List *kai = p;
List *hou = NULL;
p = p->next;
for(int i=1;i<=end;i++){
hou = p;
p = p->next;
//開始轉(zhuǎn)換
hou->next = qian;
qian = hou;
if(i == end){
kai->next = p;
head = hou;
}
}
}else{
//記錄begin前面的指針,begin的指針,end處的,end后面的
//算法思想就是將鏈表指針逆過來
List *p = head;
//q 開始的前一個節(jié)點(diǎn)指針
List *q = NULL;
//qian 是兩個節(jié)點(diǎn)進(jìn)行逆序時第一個節(jié)點(diǎn)指針
//kai 是開始位置節(jié)點(diǎn)指針
//hou是逆序時候第二個節(jié)點(diǎn)指針
List *qian=NULL, *hou=NULL, *kai=NULL;
for(int i=0;i<=end;i++){
if(i == begin - 1){
q = p;
qian = p;
p = p -> next;
}else if (i >= begin){
if (i == begin){
kai = p;
}
hou = p;
p = p->next;
//這里進(jìn)行兩個節(jié)點(diǎn)之間的逆序
hou -> next = qian;
qian = hou;
if(i == end){
if(q == NULL){
head = hou;
}else{
//這里處理結(jié)束時候與鏈表其它位置交接的地方
q->next = hou;
kai->next = p;
}
}
}else{
p = p->next;
}
}
}
}

List *Create()
{
List *p = NULL;
List *q = NULL;
head = NULL;
for ( int i = 0; i < 10; i++ ) {
p = new List;
p->num = i * 2;
if ( head == NULL ) {
head = p;
}
else {
q->next = p;
}
q = p;
}

if ( head != NULL ) {
    q->next = NULL;
}

return head;

}

void displayList(List *head)
{
while ( head != NULL ) {
cout << head->num;
head = head->next;
if ( head != NULL ) {
cout << "->";
}
}
cout << endl;
}

int main() {
Create();
int begin, end;
cin >> begin >> end;
reverse(begin, end, head);
displayList(head);
return 0;
}```

10. 單鏈表是否有環(huán)?

如果單鏈表里有重復(fù)的節(jié)點(diǎn),則說明單鏈表中存在環(huán)
有一個鏈表,我們需要判斷鏈表中是否存在環(huán)。有環(huán)則輸出true,否則輸出false。

輸入有多行,每行為由空格分隔的兩個整數(shù)m和n,m是當(dāng)前結(jié)點(diǎn)的數(shù)據(jù),n代表當(dāng)前結(jié)點(diǎn)的指針域指向第n個結(jié)點(diǎn)。

n存在四種情形:
①為-1,代表該結(jié)點(diǎn)的指針域指向NULL,輸入結(jié)束;
②指向該結(jié)點(diǎn)之前的結(jié)點(diǎn),如第3個結(jié)點(diǎn)的指針域指向n = 2的結(jié)點(diǎn);
③指向自己,如第3個結(jié)點(diǎn)的指針域指向n = 3的結(jié)點(diǎn);
④指向其直接后繼結(jié)點(diǎn),如第3個結(jié)點(diǎn)的指針域指向n = 4的結(jié)點(diǎn),不能指向n = 5的結(jié)點(diǎn)。

當(dāng)輸入為:
1 2
2 3
3 -1
時,代表:第1個結(jié)點(diǎn)的數(shù)據(jù)為1,指向第2個結(jié)點(diǎn);第2個結(jié)點(diǎn)的數(shù)據(jù)為2,指向第3個結(jié)點(diǎn);第3個結(jié)點(diǎn)的數(shù)據(jù)為3,指向NULL,輸入結(jié)束。
下面是代碼實(shí)現(xiàn)一個初步的算法,基本思想還是建立鏈表后,進(jìn)行遍歷,遍歷過的節(jié)點(diǎn)置flag為1,如果以后遍歷到flag==1的節(jié)點(diǎn),那么就說明有環(huán)。

#include <iostream>
#include <vector>
using namespace std;

struct List{
    int num;
    int flag;
    List *next;
};

//建立頭指針
List *head = NULL;

int main(){
    //建立輸入動態(tài)數(shù)組
    vector<int> data;
    vector<int> pos;
    vector<List *> point;
    int m, n;
    while(cin >> m >> n){
        data.push_back(m);
        pos.push_back(n);
    }
    for(int i=0;i<pos.size();i++){
        List *node = NULL;
        node = new List;
        node->num = data[i];
        node->flag = 0;
        point.push_back(node);
    }
    head = point[0];
    //建立鏈表
    for(int j=0;j<pos.size();j++){
        if(pos[j] != -1){
            point[j]->next = point[pos[j]-1];
        }else{
            point[j]->next = NULL;
        }
    }
    //遍歷鏈表
    int loop = 0;
    List *p;
    head->flag = 1;
    cout << head->num << "->";
    p = head->next;
    while(p){
      if(p->flag != 1){
        cout << p->num << "->";
        p->flag = 1;
      }else{
        loop = 1;
        break;
      }
      p = p->next;
    }
    cout << endl;
    if(loop == 1){
      cout << "true" << endl;
    }else{
      cout << "false" << endl;
    }
}```
###11. 面向?qū)ο驩bject Oriented Programming
首先是抽象特性,封裝,繼承,多態(tài)
C++對于類內(nèi)的成員提供了三種訪問權(quán)限,public,protected,private表示公有,保護(hù)和私有。
  - public
表示其后定義的成員對程序所有部分可見,包括數(shù)據(jù)成員,成員函數(shù)以及類型。作為公有成員存在的大多是一些特定方式讀取,修改數(shù)據(jù)成員的成員函數(shù),類的接口。
  - private
修飾成員時表示該成員僅在該類內(nèi)可見,類外無法對這個成員進(jìn)行訪問。包括大部分變量,一些不需要類的使用者關(guān)注的用于具體運(yùn)算過程的函數(shù)。
  - protected
繼承派生

  通過對成員訪問的控制,信息被封存在了一個可控的地方,可以設(shè)定一些安全的途徑,獲得和修改一些信息,這就是面向?qū)ο蟮囊粋€特性,封裝

include<iostream>

using namespace std;
class Student{
private:
int id;
int age;
public:
int getID(){return id;}
int getAge(){return age;}
//先進(jìn)行聲明,函數(shù)比較復(fù)雜,定義在類的外面
void setID(int newID);
void setAge(int newAge);
};
void Student::setID(int newID){
id = newID;
}
void Student::setAge(int newAge){
age = newAge<100?newAge:99;
}
int main(){
Student tom;
tom.setID(1);
tom.setAge(16);
cout<<tom.getID()<<" "<<tom.getAge();
return 0;
}```

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容