数组
数组是可以在内存中连续存储多个元素的结构,数组是一个类型例如 int [], double [] ,数组中所有元素必须属于相同的数据类型。在内存中的存放方式为:
变量:内存中的一块空间
数组:内存中的一串连续的空间
数组必须先声明,再使用,数组的长度固定不变,避免数组越界。必须在定义数组的时候明确数组的长度。
定义数组
dataType arrayName[size];
dataType arrayName[] = {elements, ...}
dataType arrayName[]{elements, ...}
定义数组有以下几个注意点:
- size 可以只可以是常量(
const int N,或者数字)。 - = 号可以省略,例如
int days[]{1, 15}; - 大括号内可为空,这样所有元素置零,例如
float m[100]{}; - 但是大括号内和 size 不能同时为空,必须要有一个标示数组大小的声明。
数组的初始化
int nums[5];
这种声明数组中的内容是没有被初始化的,打印的话会显示数组分配的内存地址之前存储的内容。
int nums[5]{};
int nums[5] = {1, 2}
int nums[5] = {0}
这几种声明则会将数组中的内容全部初始化为0。
#include <iostream>
using namespace std;
int main() {
int nums_uninit[5];
int nums_init1[5]{};
int nums_init2[5]{1, 2};
cout << "未初始化\t已初始化\t已初始化" << endl;
for (int i = 0; i < 5; i++) {
cout << nums_uninit[i] << "\t\t"
<< nums_init1[i] << "\t\t"
<< nums_init2[i] << endl;
}
return 0;
}
未初始化 已初始化1 已初始化2
8 0 1
0 0 2
0 0 0
0 0 0
4200112 0 0
从上面代码可以清晰看到,初始化过的数组和未初始化过的数组的区别。
为什么未初始化的数组会出现这种数字呢?下面是我在网上搜到的详细解释:
数组的一些常用算法
动态的获取一个数组的大小:
sizeof(arrayName) / sizeof(dataType) ;
上面这种方法只对于基础类型的数组有效。
另外一种获取方法:
sizeof(nums[0]);
这种方法不建议对未初始化的数组使用,因为数组位初始化,数据是随机的。采用上文说过的 int nums[5]{}; 的声明的话就可以使用,因为数组已经被初始化为0了。
以及字符串类型不能有上面这两种方法来获取,因为字符串的大小不是固定的,不能保证每个字符串的大小一致。
冒泡排序
算法步骤:
- 从第一个元素开始,比较和下一个元素的大小,若大于下一个元素则交换位置。
- 重复步骤 1 直到与最后一个元素比较完成。
- 这样就讲数组中最大的元素移动到了最后一个位置,标记为排序完成。
- 对剩余未排序完成的元素重复步骤 1 - 3 ,直至所有元素排序完成。
// 冒泡排序(升序)
int temp;
for (int i = 0; i < nums_len - 1; i++) { // 步骤 4
// j++ 为步骤 2 ,j < nums_len -i - 1 为步骤 3
for (int j = 0; j < nums_len - i - 1; j++) {
if (nums[j] > nums[j+1]) { // 步骤 1
temp = nums[j];
nums[j] = nums[j+1];
nums[j+1] = temp;
}
}
}
选择排序
算法步骤:
- 设定第一个未排序元素为最大值。
- 将最大值与剩下所有元素比较,找出未排序元素中的最大值。
- 若最大值不为第一个未排序元素,则与其交换位置。并标记第一个元素为排序完成。
- 重复步骤 1 - 3 直至所有元素排序完成。
// 选择排序(降序)
int temp;
for (int i = 0; i < nums_len - 1; i++) { //步骤 4
int max = nums[i]; // 步骤 1
int max_i = i;
for (int j = i + 1; j < nums_len; j++) { //步骤 2
if (max < nums[j]) {
max = nums[j];
max_i = j;
}
}
if (max_i != i) { // 步骤 3
temp = nums[i];
nums[i] = nums[max_i];
nums[max_i] = temp;
}
}
查找元素
// 查找输入数字在数组中的下表,没找到则返回-1
int target_index = -1;
int target;
cout << "请输入你要查找的数:";
cin >> target;
for (int i = 0; i < nums_len; i++) {
if (nums[i] == target) {
target_index = i;
cout << "数字 " << target << " 在数组中的下标为:" << target_index
<< endl; break;
}
}
if (target_index == -1)
cout << "抱歉数字 " << target << " 没有在数组中找到。" << endl;
向量 vector
向量容器 vector 是一个快速的动态分配内层的数组。
有点像是C++中数组的升级版本,和python中的 list 类很相似。
动态数组,可以在运行阶段设置长度,有数组的快速索引方式,可以插入和删除元素。
定义和初始化
vector 的使用一定要导入 vector 头文件。它的定义和初始化有许多方法:
#include <vector>
vector<double> vec1; //声明一个int型向量vec1
vector<string> vec2(5); //声明一个初始大小为5的string型向量vec2
vector<int> vec3(20, 998); //声明一个初始大小为20的int型向量vec3,并且所有初始值为998
vector<int> vec4(vec3); //声明一个int型向量vec4,并用vec3初始化
vector<int> vec5(vec3.begin(), vec3.begin()+2); //声明一个int型变量vec5,并用vec3
vector<int> vec6 {1, 2}; //声明一个int型变量vec6,并初始化为{1, 2}
//使用数组进行初始化
int nums[] {1, 2, 3};
vector<int> vec7(arr, arr+2); //声明一个int型向量vec7,使用数组arr的0-2(3个元素)进行初始化
vector<int> vec8(&arr[1], &arr[2]); //声明一个int型向量vec8,使用数组arr的1-2(两个元素)进行初始化
常用操作
| 方法名 | 用处 |
|---|---|
| clear() | 移除容器中的所有数据 |
| empty() | 判断容器是否为空 |
| size() | 返回容器中元素的个数 |
| [index]、at(index) | 返回索引为index的元素 |
| erase(pos) | 删除pos位置处的数据 |
| erase(beg, end) | 删除[beg, end]区间的数据 |
| front() | 返回第一个元素 |
| insert(pos, elem) | 在pos位置处插入一个元素 |
| pop_back() | 删除最后一个元素 |
| push_back(elem) | 在容器末尾插入一个元素 |
| resize(num) | 重新设置容器大小 |
| begin()、end() | 返回容器首位元素的迭代器 |
vector 扩容的基本步骤
- 创造一个新的连续内存空间
- 将原来内存空间中的数据拷贝到新的内存空间中
- 销毁原来内存空间中的数据
这里推荐 vector 里面存放指针,不要存放一些复杂类型的数据,因为其实它的效率没有普通数组高。