记录一下自己刷题过程中学习到的其它基础知识。菜鸟一只,如有错误请多指教~
题目:反转链表
struct ListNode {
int val;
strucr ListNode * next;
ListNode(int x): val(x), next(NULL) {}
};
class solution {
public:
ListNode* ReverseList(ListNode* pHead){
if(!pHead) return nullptr;
ListNode* reverse = nullptr;
ListNode* cur = pHead;
Listnode* nex = nullptr;
while(cur){
nex = cur-> next;
cur->next = reverse;
reverse = cur;
cur = nex;
}
return reverse;
}
}
结构体的构造函数
结构体的构造函数可以不经定义就直接初始化结构体变量。结构体的构造函数与结构体同名。
struct ListNode {
int val;
struct ListNode* next;
//默认构造函数,注意函数后没有分号
ListNode(){}
//自定义构造函数
ListNode(int x): val(x), next(NULL) {}
} node[2]
结构体的构造函数分为两种:
- 无参构造函数,也称为自定义构造函数。
- 有参构造函数,也成为默认构造函数。
二者的区别是,默认构造函数需要对结构体中的所有变量一起初始化,而自定义构造函数允许只对结构体中的某一些或某个变量单独初始化。为了方便,这两个构造函数通常会一起使用。
void main(){
node[0] = {3, NULL}; \\两个变量都要初始化
node[1] = {4}; \\仅初始化了val
}
vector:
vector是容器,可以理解成高级版的数组。比数组的优点在于,vector可以动态增加减少数据。vector可以存放各种类型的对象,但一个vector中的所有对象类型必须一致。
vector和数组的异同
数据结构 | vector | 数组 |
相同 | 同一容器中所有数据的类型必须一致 | |
连续存储,可以用下标对数据进行随机读写 | ||
都可以用迭代器进行操作(在c++中每个容器都配有各自的迭代器) | ||
不同 | 长度不固定,可以随时增加减少。因此需要考虑迭代的是否有效问题 | 长度固定,定义好就不可以更改。因此不需要考虑迭代的是否有效问题 |
可以直接将一个vector赋值给另一个vector | 不可以直接用其它数组赋值,仅能通过循环逐个元素初始化为另一个数组对应的值 | |
除了下标访问,还可以使用front() back() at()进行访问,有效避免越界问题 | 仅能下标访问,容易出现越界 | |
提供了两个容器对象的内容交换,即swap() | 只能通过遍历的方式逐个交换元素 | |
声明周期完成后,会自动地释放其所占用的内存 | 用new[ ]/malloc申请的空间,必须用对应的delete[ ]/free来释放空间 | |
可以使用size()和Empty()获得vector大小和判断是都为空 | 只能通过sizeof()/strlen()以及遍历计数来获取大小和是否为空 |
本部分参考链接: 【C++】array和vector,数组三者区别和联系, Vector与数组的区别.
C++中的NULL和nullptr
c++中为避免野指针,在定义指针时也要初始化,有些尚未使用的指针就被初始化为空指针。常用的有null和nullptr。
int *p = NULL; // int *p = 0
int *a = nullptr;
char *c = nullptr;
double *d = nullptr;
NULL在c++中是宏定义,值就是常整数0,而不是(void*)0,不支持隐式转换。而使用nullptr时,nullptr 可以被隐式转换成任意的指针类型。也就是说,不同类型的指针变量都可以使用 nullptr 来初始化,编译器分别将 nullptr 隐式转换成对应的指针类型。