C++速查笔记

结构体、类、指针、引用

class中默认private, struct中默认是public

堆栈空间

  • 代码是存到内存空间中的,所有的函数调用都是在栈空间中,局部变量都是定义到栈空间中的,静态变量和数组全部定义到堆空间中。
  • 局部变量初始是随机值,全局变量初始全是0;(这是因为开在栈空间里的变量没有赋值,所以是不确定的;开到堆空间里的变量全部默认为0

&*

  • &:引用、取地址符
  • *:指针、解引用符
    某些符号有多重含义;像&*这样的符号;
  • 在声明语句中,&*用于组成符合类型(&引用,*指针)
  • 在表达式中,它们的角色又转变成运算符。(&取地址符,*解引用符)
int i = 42;
int &r = i;// & 紧随类型名出现,因此是声明的一部分,r 是一个引用
cout << r << endl;//42,引用就是一个别名,修改r,i也会随之变化
cout << &r << endl;// 获得r的地址,也就是i的地址

int* p; // * 紧随类型名出现,因此是声明的一部分,p 是一个指针
cout << p << endl;//p的随机地址,因为是局部变量,在栈空间中

p = &i;// & 出现在表达式中,是一个取地址符
cout << p << endl;// 取到i的地址
cout << *p << endl;// 42,通过i的地址得到i的值

*p = i;// * 出现在表达式中,是一个解引用符
cout << p << endl;// i的地址
cout << *p << endl;//解引用: i的值42

int &r2 = *p;// & 是声明的一部分,是一个引用;* 是一个解引用符
cout << r2 << endl;// 42,引用
cout << (r2==r) << (r==i) <<endl;

输出结果为:

42
0x7fffaa03df44
0x7fffaa03e040
0x7fffaa03df44
42
0x7fffaa03df44
42
42
11

指针、数组名

#include<bits/stdc++.h>
using namespace std;

int main()
{
    int a[5] = {1,2,3,4,5};
    cout << a << endl;// 数组名是数组的首地址
    cout << *a << endl;// 1
    for (int i = 0; i < 5; i++)  cout << *(a + i) << ' ';
    cout << endl;
    
    char c = '1';
    cout << (void*) &c << endl;// 地址:0x7fff55b6082b
    for (int i = 0; i < 5; i++)
        cout << (void*)&a[i] << endl;
        /*
        0x7fff5dd31b70
        0x7fff5dd31b74
        0x7fff5dd31b78
        0x7fff5dd31b7c
        0x7fff5dd31b80
        隔了4个字节是因为每个int型变量有4个字节
        如果是char类型的字符数组,则每个地址差1而不是4*/
    return 0;
}

链表

#include<bits/stdc++.h>
using namespace std;
const int N = 1e4;

//定义链表结构体
struct Node
{
    int val;// 链表的值
    Node* next; // 指向链表的下一个节点
    // 构造函数:初始化链表的值,下一个节点指向NULL
    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节点指向q节点
    p->next = q;
    q->next = o;

    // 定义头节点,头节点就是p节点
    Node* head = p;
    
    // 在头节点前面添加节点4
    Node* u = new Node(4);
    u->next = head;// 把新节点插在头节点之前
    head = u;
    
    // 删除节点4
    // head = head->next;
    
    // 删除节点1
    head->next = head->next->next;
    
    // 遍历链表,i是指针,运行条件是 i!=NULL
    for (Node* i = head; i; i = i->next)
        cout << i->val << endl;
    return 0;
}

给定节点指针,删除指定节点

输入:链表 1->4->6->8
删掉节点:第2个节点即6(头节点为第0个节点)

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    void deleteNode(ListNode* node) {
        // 当前node指向6这个节点
        node->val = node->next->val;
        node->next = node->next->next;
    }
};

合并两个递增的链表,合并后仍递增

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* merge(ListNode* l1, ListNode* l2) {

        ListNode* dummy = new ListNode(0);// 记录头节点位置
        ListNode* cur = dummy;
        
        while(l1&&l2)
        {
            if (l1->val < l2->val)// l1的值小
            {
                cur->next = l1;
                l1 = l1->next;
            }
            else// l2的值小
            {
                cur->next = l2;
                l2 = l2->next;
            }
            cur = cur->next;// 向后移动一位
        }
        
        // 如果有一个链表没有遍历完,就加在最后
        if(l1) cur->next = l1; //l1不为NULL
        if(l2) cur->next = l2; //l2不为NULL
        
        return dummy->next;
    }
};

全排列函数

bool next_permutation(iterator start,iterator end):

  • next_permutation()在使用前需要对欲排列数组按升序排序,否则只能找出该序列之后的全排列数
  • next_permutation()求的是当前排列下一个排列,同时并改变当前排列的值
  • 返回值:当当前序列不存在下一个排列时,返回false, 否则返回true
class Solution {
public:
    vector<vector<int>> permutation(vector<int>& nums) {
        
        // next_permutation()在使用前需要对欲排列数组按升序排序,否则只能找出该序列之后的全排列数
        sort(nums.begin(), nums.end());
        
        vector<vector<int>> res;
        
        res.push_back(nums);// 先将排好序的数组放入res中
        
        // bool next_permutation(iterator start,iterator end):
        // 求的是当前排列的下一个排列,同时并改变当前排列的值
        // 返回值:当 当前序列 不存在下一个排列时,返回false, 否则返回true
        while (next_permutation(nums.begin(), nums.end()))
        {
            res.push_back(nums);// 将每次生成的新排列放入 res 中
        }
        return res;
    }
};

c++ string 总结

// str.back():获取string的最后一个字符
// str.pop_back():删除str中最后一个字符
// str.back = '!';修改最后一个字符
// str.front();获取字符串第一个字符
string a="abcd";
1.获取字符串最后一个字符
auto b=a.back(); //结果为 b='d';

2.修改字符串最后一个字符
a.back()='!'; //结果为 a="abc!";

3.获取字符串第一个字符
auto b=a.front(); //结果为 b='a';

4.修改字符串第一个字符
a.front()='!'; //结果为 a="!bcd";

str.erase(0);//删除字符
str.find("ab",index);//返回ab在字符串中第一次出现的位置(从index开始查找)
str.substr(index,length);// 返回从index开始,长为length的子字符串;若没有指定长度,则返回从index开始剩余所有字符串

signed main 和 int main 的区别?

int本来就是signed intint = signed int = signed,就像unsigned = unsigned int
当你不确定过程中会不会爆 int 的时候,可以这么写。
总结:
头文件声明#define int long long,防止爆int

#include<bits/stdc++.h>
#define int long long
using namespace std;
typedef long long ll;
signed main(){
    return 0;
}
#pragma Gcc optimize(3,"inline","Ofast");
#include<bits/stdc++.h>
using namespace std;
#define int long long
typedef long long ll;
 
signed main(){
    double d;cin>>d;
    printf("%.1f",d/59535);
}

printf保留小数

printf("%6.2f".floatNum)# 保留两位小数

说明:%6.2f 表明待打印的数(floatNum)至少占6个字符宽度(包括两位小数和一个小数点),且小数点后面有2位小数,小数点占一位,所以整数部分至少占3位。

注意:这里的6是待打印的数至少占据的字符宽度,包括两位小数(如果小数不够两位用0补位,例如100.1打印出来为100.10)和一个小数点,所以整数部分至少占3个字符宽度。
原文链接

posted @ 2021-12-19 13:22  zzflybird  阅读(109)  评论(0)    收藏  举报