zl程序教程

您现在的位置是:首页 >  后端

当前栏目

10min快速回顾C++语法(七)类、结构体、指针链表专题

C++链表 快速 结构 语法 指针 回顾 专题
2023-06-13 09:11:06 时间

C++的语法基础(七)

⭐写在前面的话:本系列文章旨在短时间内回顾C/C++语法中的重点与易错点,巩固算法竞赛与写题过程中常用的语法知识,精准地解决学过但有遗忘的情况,为算法刷题打下坚实的基础。

10.1类与结构体

10.1.1 类的定义

  • 注意类的‘ } ’后面一定要加分号。
class Person
{
    private:
        int age, height;
        double money;
        string books[100];

    public:
        string name;
    
        void say()
        {
            cout << "I'm " << name << endl;
        }
    
        int get_age()
        {
            return age;
        }
    
        void add_money(double x)
        {
            money += x;
        }

};

类中的变量和函数被统一称为类的成员变量。

private后面的内容是私有成员变量,在类的外部不能访问;public后面的内容是公有成员变量,在类的外部可以访问。

可以定义多个private在不同的位置

10.1.2 类的使用

#include <iostream>

using namespace std;

const int N = 1000010;

class Person
{
    private:
        int age, height;
        double money;
        string books[100];

    public:
        string name;
    
        void say()
        {
            cout << "I'm " << name << endl;
        }
    
        int set_age(int a)
        {
            age = a;
        }
    
        int get_age()
        {
            return age;
        }
    
        void add_money(double x)
        {
            money += x;
        }

} person_a, person_b, persons[100];

int main()
{
    Person c;

    c.name = "timerring";      // 正确!访问公有变量
    c.age = 18;          // 错误!访问私有变量
    c.set_age(18);       // 正确!set_age()是共有成员变量
    c.add_money(100);
    
    c.say();
    cout << c.get_age() << endl;
    
    return 0;

}

结构体和类的作用是一样的。不同点在于类默认是private,结构体默认是public。

struct Person
{
    private:
        int age, height;
        double money;
        string books[100];

    public:
        string name;
    
        void say()
        {
            cout << "I'm " << name << endl;
        }
    
        int set_age(int a)
        {
            age = a;
        }
    
        int get_age()
        {
            return age;
        }
    
        void add_money(double x)
        {
            money += x;
        }

} person_a, person_b, persons[100];

10.1.3 结构体的构造函数

#include <iostream>

using namespace std;

struct Person 
{
    int age ,height;
    double money;
    
    Person() {}//第一种构造函数
    Person( int _age , int _height , double _money)
    {//第二种构造函数
        age = _age;
        height = _height;
        money = _money;
    }
    
    Person( int _age , int _height , double _money):age(_age),height(_height),money(_money){ }
    //第三种方式,这里可以完成快速赋值。
    
};

int main()
{
    Person p;//会调用第一种构造函数,如果没有定义第一种构造函数,则会报错
    Person p2( 18 , 180 , 618.1);//会调用第二种构造函数
    return 0;
}

10.2 指针和引用

指针指向存放变量的值的地址,因此我们可以通过指针来修改变量的值。

#include <iostream>

using namespace std;

int main()
{
    int a = 10;
    int *p = &a;//定义指针并赋值 
    int** q = &p;//可以定义指针的指针

    *p += 5;
    cout << a << endl;
    
    return 0;

}

数组名是一种特殊的指针。指针可以做运算:

#include <iostream>

using namespace std;

int main()
{
    int a[5] = {1, 2, 3, 4, 5};

    for (int i = 0; i < 5; i ++ )
        cout << *(a + i) << endl;
    
    return 0;

}

引用和指针类似,相当于给变量起了个别名。

#include <iostream>

using namespace std;

int main()
{
    int a = 10;
    int &p = a;//引用、别名

    p += 5;
    cout << a << endl;
    
    return 0;

}
  • 栈区间是从小到大分配
  • 堆区间是从大到小分配

10.3 链表

#include <iostream>

using namespace std;

struct Node
{
    int val;
    Node* next;//定义一个指针Node,此处不能定义一个变量Node next ,这样会报错
} *head;

int main()
{
    for (int i = 1; i <= 5; i ++ )
    {
        Node* p = new Node();
        p->val = i;
        p->next = head;
        head = p;
    }

    for (Node* p = head; p; p = p->next)
        cout << p->val << ' ';
    cout << endl;
    
    return 0;

}

10.3.1 链表详解

#include <isotream>
using namespace std;

struct Node
{
    int val ;
    Node* next;
    
    Node(int _val): val(_val),next(NULL){}//定义构造函数
};

int main()
{
    /*
    Node node = Node(1);//值为1,指向空的节点 返回是这个变量的值
    Node* p = &node;//然后把它放在指针中
    */
    
    //与上面等价,c++可以生成一个结构体,把结构体指针放在p中
    Node* p = new Node(1);
    		//返回是这个变量的地址,可以理解为动态开辟了一段空间,这段空间的地址给p
    
    p -> next = p;//让指针指向自己。
    			  //这里解释一下->,由于p是一个地址,因此p如果调用成员的next方法,必须通过->调用
   /* 
    Node a = Node(1);
    a.next ,a.val;//而对于a是一个变量,只需要采用.的方式调用即可
    */
    
    auto q = new Node(2);//也可以用auto自动判断
    p -> next = q;
}

这样的数据结构就叫做链表。通常会把链表的第一个节点的地址放在head(头节点)中。

10.3.2 遍历链表

#include <isotream>
using namespace std;

struct Node
{
    int val ;
    Node* next;
    
    Node(int _val): val(_val),next(NULL){}//定义构造函数
};

int main()
{
	Node* p = new Node(1);
    Node* q = new Node(2);
    Node* o = new Node(3);
    
    p -> next = q;
    q -> next = o;
    
    Node* head = p;//定义head指针等于p
    
    for(Node* i = head ; i ; i = i -> next)
        cout << i ->val <<endl;
    return 0;
}

10.3.3 链表的添加

由于遍历节点是从前往后的,因此后面的节点地址不知道。因此通常会在最前面添加新节点。

Node* u = new Node(4);
u -> next = p;
head = u;

10.3.4 链表的删除

链表的删除是指在遍历中跳过这个节点或者在遍历时遍历不到这个点。

head -> next = head -> next -> next;