数组
数组是一个变量,由数据类型相同的一组元素组成
数组的结构和基本要素:
标识符(唯一的名称): 数组的名称,用于区分不同数组
数组元素:向数组中存放的数据
元素下标(从零开始):对数组元素的编号(每个元素都可以通过下标来访问)
元素类型:数组元素的数据类型
数组的长度固定不变,避免数组越界,并且C与C++ 数组越界编译器一般不会报错
一维数组
datatype arrayName[size]
例
int num[2];
初始化
在C99的编译器里C++ 中可以使数组的长度为变量 但推荐用动态数组vector
可以理解成数组长度可以用变量定义,但是初始化的时候是不能变量.因为程序的初始化是在执行之前,所以在程序执行之前不能给一个变量给数组初始化.除了const int等等.
int echo[6] = {1,2,3,4,5,6};
//元素个数与声明的一致
int goal[2] = {0,2,3,4;}
//后面的元素未初始化,默认值为0
int days[] = {1,2};
//元素的个数初始化为2
int air[] = {};
//错误,未知个数初始化错误.
在C++11后初始化可以省略 = 号 //int days[] {1,5};
大括号可以为空,表示元素置零. //int days[365] = {};
const int N = 100;
int num[N];
num[0] = 6666;
int N = 100;
int num[N];
num[0] = 6666;
利用sizeof()探究未赋值的数值;
int num[5];
cout << "数组的长度为"<< sizeof(num)/sizeof(int) <<endl;
因为初始化后的num里默认是5个0,sizeof(num)得到的是5个int的长度,所以再除以一个int长度的值就为5
查找数组中数字的时候,养成良好习惯.将存储下标的变量设置为不可能的值,像-1或者INT_MIN
int search_index = -1;
for (i = 0; i < 7; i++)
{
if (total[i] == j)
{
search_index = i;
cout << "你寻找的数字在数组的第" << i + 1 << "号" << endl;
}
}
if (search_index == -1)
{
cout << "数组中没有你想要的数字喔" << endl;
}
数组的大小一旦确定了就不能再更改了
为了实现静态数组的动态化我们可以
double num[999]; //先预留足够大的空间
int num_count = 0; //当前元素的个数
num[num_count++] = 1;
num[num_count++] = 3;
num[num_count++] = 1;
num[num_count++] = 4;
数组排序
冒泡排序
按从小到大从上到下排列
1.最下面的数从下面往上冒泡,假如下面的数比上面小就往上走.往上走就会有调换的次数.第一轮的时候5个数字我们就需要比较4次.
2.第二轮的时候同理冒泡,但是这第二个数是不需要和第一个数对比的,因为在第一次循环的时候已经比较过了,所以比较的次数要比第二轮的少一次.也就是只需要比较3次.
3.然后利用嵌套循环进行冒泡排序的控制.外层控制5个数字里4个数字要去冒泡,也就是数字冒泡的轮数.而内层控制每个数字冒泡要比较多少次,因为每轮结束后下一轮比较的次数要少1.
int num[5];
int i,j,temp;
for (i = 0; i < 5; i++)
{
cin >> num[i];
}
cout << "排序前的数组顺序为:";
for (i = 0; i < 5; i++)
{
cout << num[i] << "\t";
}
for (i = 0; i < 4; i++)
{
for (j = 0; j < 4 - i; j++)
{
if (num[j] < num[j + 1])
{
temp = num[j];
num[j] = num[j + 1];
num[j + 1] = temp;
}
}
}
cout << "排序后的数组顺序为:";
for (i = 0; i < 5; i++)
{
cout << num[i] << "\t";
}
选择排序
用temp临时数进行打擂台,从第一个数赋值开始,和后面每个数进行比较,如果temp里的数比当前面对的数小,就进行一次调回,在最后的时候进行数组内调换数字(当前的num[i]和极值,)极值值就排到边边.
跟冒泡排序的区别在于内层循环的j与i的关系为 j = i + 1, 与当前num[i]的下一位数比较
int num[5];
int i, j, temp;
int min_index = 0;
for (i = 0; i < 5; i++)
{
cin >> num[i];
}
cout << "排序前的数组顺序为:";
for (i = 0; i < 5; i++)
{
cout << num[i] << "\t";
}
cout << "\n此数组中的个数为:" << sizeof(num) / sizeof(int) << endl;
for (i = 0; i < sizeof(num) / sizeof(int) - 1; i++)
{
temp = num[i];
min_index = i; //超几把重要,不仅最小的数字要重置,最小数的小标也要重置,假如没有没有进入j循环的比较环节,min_index讲沿用上一次循环的下标.
for (j = i + 1; j < sizeof(num) / sizeof(int) ; j++)
{
if ( num[j] < temp )
{
temp = num[j];
min_index = j;
}
}
if (min_index > i)
{
num[min_index] = num[i];
num[i] = temp;
}
}
cout << "排序后的数组顺序为:";
for (i = 0; i < 5; i++)
{
cout << num[i] << "\t";
}
元素的插入和删除
删除的话要设置好下标为-1 和上面的排序一样 假如查找不到要删除的数字就不更改下标,然后通过检测下标是否为-1来判读是否有要删除的数字.
1.找一个数字比目标数字大的,放在它的旁边.(需要注意数据有可能有重复性, 例如查找从大到小排序的数组,找比2大并且将2放在其后面时,我们可能会放到第一个3的后面,那我们就可以换个查找方式,找到比2小的数,放在它的前面.)
2.从最后一个元素开始向右挪动
3.将挪出来的空位插入目标数字
4.数组的长度增加一个数据. // num_count++;
double num[999]; //先预留足够大的空间
int num_count = 0; //当前元素的个数
num[num_count++] = 1;
num[num_count++] = 3;
num[num_count++] = 1;
num[num_count++] = 4;
double temp;
int max_index = 0;
double del_num;
int del_index = -1;
for (int i = 0; i < num_count; i++) //输出
{
cout << num[i] << "\t";
}
cout << endl;
for (int i = 0;i < num_count - 1; i++) //排序
{
temp = num[i];
max_index = i;
for (int j = num_count; j > i; j--)
{
if (temp < num[j])
{
temp = num[j];
max_index = j;
}
}
num[max_index] = num[i];
num[i] = temp;
}
for (int i = 0; i < num_count; i++) //输出
{
cout << num[i] << "\t";
}
int insert_index = num_count; //输入数字的下标.使数组里数字个数 + 1,且把下标定在最后一个.
double insert_power;
cout << "\n请输入数字" << endl;
cin >> insert_power;
num[insert_index] = insert_power;
for (int i = 0; i < num_count; i++) //把输入的数字放在最后,然后从头到尾查找一次
{
if ( num[i] < insert_power ) //当找到一个数比我输入的数小时就执行
{
for (int j = num_count; j >= i + 1; j--) //从倒数第二个开始把数字向左挪
{
num[j] = num[j - 1];
}
num[i] = insert_power; //令空出来的那个位置等于输入的数字
insert_index = i; //更新下标
break;
}
}
num_count++; //记得增加数组中个数
for (int i = 0; i < num_count; i++) //输出
{
cout << num[i] << "\t";
}
cout << endl;
cout << "请输入你想删除的数字" << endl;
cin >> del_num;
for (int i = 0; i < num_count - 1; i++)
{
if (num[i] == del_num)
{
del_num = i; //记录所做的下标
for (int j = i; j < num_count - 1; j++)
{
num[j] = num[j + 1];
}
del_index = i;
num_count--;
}
}
if (del_index == -1)
{
cout << "没有找到你输入的数字喔~~" << endl;
}
else
{
for (int i = 0; i < num_count; i++) //输出
{
cout << num[i] << "\t";
}
cout << endl;
}
二维数组
datatype arrayName[size1][size2]
例
int num[2][3];
double index[1][2];
string stu_names[] = { "张三","李四","王五" };
string subject[] = { "C++","CAD","工程力学" };
const int ROW = 3;
const int COL = 3;
double scores[ROW][COL];
for (int i = 0; i < ROW; i++) //外层循环控制学生
{
for (int j = 0; j < COL; j++) //内层循环控制课程
{
cout << stu_names[i] << "的" << subject[j] << "成绩为" << endl;
cin >> scores[i][j];
}
}
for (int i = 0; i < COL; i++)
{
cout << "\t" << subject[i];
}
cout << endl;
for (int i = 0; i < ROW; i++)
{
cout << stu_names[i];
for (int j = 0; j < COL; j++)
{
cout << "\t" << scores[i][j];
}
cout << endl;
}
从而达到输出成一个表格状的结构
假如在此处无法用cout cin string类型的数据或者数组,可以看我的另一篇文章
数组的替代品vector(向量)
vector是容器,是一个模板类,是相当于一个快速的动态分配内存的数组.
①其为动态数组,可以在运行阶段设置长度
②具有数组的快速索引方式
③可以插入和删除元素
之所以说是代替,是因为在C++里不论是一维还是多维都可以用vector来代替数组
并且推荐在C++里使用快捷方便的容器vector
关于vector是否可以完全替代数组可以参考下面链接里大佬的回答
关于vector是否可以完全替代数组.
使用前要添加头文件< vector >
定义和初始化
vector<int> vec1; //只能存放int类型的数据
vector<int> vec2(3); //给他3个数据类型的存放空间
vector<int> vec3(4,0); //给4个int类型 全部赋为0;
其常用操作有
claer() | 移除容器里的全部数据 |
---|---|
empty() | 判断容器是否为空 |
size() | 返回容器中元素的个数 |
[index]、at(index) | 返回索引为index的元素 |
erase(position) | 删除position位置处的数据(只能用于迭代器) |
erase([begin,end]) | 删除[begin,end]区间的数据 |
front() | 返回第一个元素 |
insert(position,element) | 在position出插入元素element |
pop_back() | 删除最后一个元素 |
push_back(element) | 在容器末尾插入一个元素 |
resize(num) | 重新设置容器大小 |
begin()、end() | 返回容器首、尾元素的迭代器 |
在使用算法时我们还需要额外引入头文件
< algorithm >
迭代器
迭代器其实是一种指针。
那it的自加自减就是地址的自加自减.
由此我们可以知道在内存分配时,分配的是相邻的地址,并且按照下标顺序进行地址顺序分配
我们这里演示自带的算法排序和输出
vector<double> vec_double = { 3.0, 1.0, 4.0, 2.0, 5.0 };
vec_double.push_back(0.0);
for (unsigned int i = 0; i < vec_double.size(); i++)
{
cout << vec_double[i] << "\t";
}
cout << endl;
vector<double>::iterator it; //启用同一数据类型double的迭代器
sort(vec_double.begin(), vec_double.end()); //进行正序排列
for (it = vec_double.begin(); it != vec_double.end(); ++it)
//此处为vector式输出,it为前置自加
{
cout << *it << "\t";
}
cout << endl;
reverse(vec_double.begin(), vec_double.end()); //进行逆序排序
for (it = vec_double.begin(); it != vec_double.end(); ++it)
{
cout << *it << "\t";
}
cout << endl;
小知识
vector其实也有默认分配的内存.当我们一直往里面push_back时,最终会超出它的默认分配内存.此时它会运行一下几个操作
①创造一个新的更大内存的vector1
②把vector里的数据分配到vector1
③删除vector
总结
①数组是在内存里分配一块连续的存储结构供我们使用(但是里面的元素要是同一个数据类型)
②数组需要先初始化,才能够使用(初始化就是分出一定量的内存空间,我们可以用变量控制数组的size,但是我们不能用变量初始化数组)
③数组的元素我们使用下标来访问(要自己声明一个index)
④不论是一维数组还是二维数组,都可以使用循环来动态初始化.例如下式
for(int i = 0; i < 5; i ++)
{
for(int j = 0; j < 4; j++)
{
cin >> num[i][j];
}
}
⑤vector(容器)在安全性和功能性上都比数组要强,但是在编译时会比数组满,是典型的功能复杂强大带来的弊端.
在CSDN学习的时光,是博客和在看的你支持了我~