数据结构和算法(04)---数组,动态内存,vector(c++)

文章目录

  • 目录
    • 数组
      • 1.数组的申明
      • 2.数组的初始化
      • 3.二维数组
      • 4.指向数组的指针
      • 5.传递数组给函数
    • 动态内存
      • 1.new ,delete运算符
      • 2.数组的动态内存分配
    • vector
      • 1.vector基本操作
      • 2.vector使用
      • 3.vector动态二维数组 初始化和赋值

目录

  • 数据结构:
    • 逻辑结构:数组,栈,队列,字符串,树,图
    • 存储结构:顺序存储,链式存储
  • C++常用的数据结构有:string , stack , queue , deque , vector , list , map , iterators.

数组

1.数组的申明

在这里插入图片描述
在这里插入图片描述

#include <iostream>
using namespace std;#include <iomanip>
using std::setw;int main ()
{int n[ 10 ]; // n 是一个包含 10 个整数的数组// 初始化数组元素          for ( int i = 0; i < 10; i++ )n[ i ] = i + 100; // 设置元素 i 为 i + 100cout << "Element" << setw( 13 ) << "Value" << endl;// 输出数组中每个元素的值                     for ( int j = 0; j < 10; j++ )cout << setw( 7 )<< j << setw( 13 ) << n[ j ] << endl;}

运行结果:

Element Value
0 100
1 101
2 102
3 103
4 104
5 105
6 106
7 107
8 108
9 109

2.数组的初始化

(1)Array 直接初始化 char 数组是特殊的,这种初始化要记得字符是以一个 null 结尾的

char a1[] = {'C', '+', '+'};          // 初始化,没有 nullchar a2[] = {'C', '+', '+', '\0'};    // 初始化,明确有 nullchar a3[] = "C++";                    // null 终止符自动添加
const char a4[6] = "runoob";          // 报错,没有 null 的位置

a4 是错误的,虽然 a4 包括 6 个直接字符,但是 array 大小是 7:6个字符 + 一个null。正确的是:

const char a4[7] = "runoob";

(2)Array 是固定大小的,不能额外增加元素.当我们想定义不固定大小的字符时,可以使用 vector(向量) 标准库

#include <iostream>
#include <vector>
using namespace std;int main() {// 创建向量用于存储整型数据vector<int> vec; int i;// 显示 vec 初始大小cout << "vector size = " << vec.size() << endl;// 向向量 vec 追加 5 个整数值for(i = 0; i < 5; i++)vec.push_back(i);// 显示追加后 vec 的大小cout << "extended vector size = " << vec.size() << endl;
}

vec 的大小随着 for 循环的输入而增大。

执行以上代码,输出结果:
vector size = 0
extended vector size = 5

(3)动态数组

动态数组指的是在数组使用的时候才分配存储空间,而不是像静态数组那样一开始就分配好存储空间的。

静态 int array[100];   定义了数组 array,并未对数组进行初始化静态 int array[100] = {12};  定义并初始化了数组 array动态 int* array = new int[100]; delete []array;  分配了长度为 100 的数组 array动态 int* array = new int[100]{12};  delete []array; 为长度为100的数组array初始化前两个元素

3.二维数组

多维数组最简单的形式是二维数组。一个二维数组,在本质上,是一个一维数组的列表。声明一个 x 行 y 列的二维整型数组,形式如下:

type arrayName [ x ][ y ];

其中,type 可以是任意有效的 C++ 数据类型,arrayName 是一个有效的 C++ 标识符。

一个二维数组可以被认为是一个带有 x 行和 y 列的表格。下面是一个二维数组,包含 3 行和 4 列:
在这里插入图片描述
初始化二维数组

int a[3][4] = {  {0, 1, 2, 3} ,   /*  初始化索引号为 0 的行 */{4, 5, 6, 7} ,   /*  初始化索引号为 1 的行 */{8, 9, 10, 11}   /*  初始化索引号为 2 的行 */
};

内部嵌套的括号是可选的

int a[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};

访问二维数组元素

#include <iostream>
using namespace std;int main ()
{// 一个带有 5 行 2 列的数组int a[5][2] = { {0,0}, {1,2}, {2,4}, {3,6},{4,8}};// 输出数组中每个元素的值                      for ( int i = 0; i < 5; i++ ){ for ( int j = 0; j < 2; j++ ){cout << "a[" << i << "][" << j << "]: ";cout << a[i][j]<< endl;}} 
}

a[0][0]: 0
a[0][1]: 0
a[1][0]: 1
a[1][1]: 2
a[2][0]: 2
a[2][1]: 4
a[3][0]: 3
a[3][1]: 6
a[4][0]: 4
a[4][1]: 8

4.指向数组的指针

数组名是一个指向数组中第一个元素的常量指针(无法对数组名重新赋值)。因此,在下面的声明中:

double balance[50];

balance 是一个指向 &balance[0] 的指针,即数组 balance 的第一个元素的地址。因此,下面把 p 赋值为 balance 的第一个元素的地址:

double *p;
double balance[10];p = balance;
  • 使用数组名作为常量指针是合法的,反之亦然。因此,*(balance + 4) 是一种访问 balance[4] 数据的合法方式。
  • 一旦您把第一个元素的地址存储在 p 中,您就可以使用 * p、* (p+1)、* (p+2) 等来访问数组元素
#include <iostream>
using namespace std;int main ()
{// 带有 5 个元素的双精度浮点型数组double balance[5] = {1000.0, 2.0, 3.4, 17.0, 50.0};double *p;p = balance;// 输出数组中每个元素的值cout << "使用指针的数组值 " << endl; for ( int i = 0; i < 5; i++ ){cout << "*(p + " << i << ") : ";cout << *(p + i) << endl;}cout << "使用 balance 作为地址的数组值 " << endl;for ( int i = 0; i < 5; i++ ){cout << "*(balance + " << i << ") : ";cout << *(balance + i) << endl;}return 0;
}

使用指针的数组值
*(p + 0) : 1000
*(p + 1) : 2
*(p + 2) : 3.4
*(p + 3) : 17
*(p + 4) : 50
使用 balance 作为地址的数组值
*(balance + 0) : 1000
*(balance + 1) : 2
*(balance + 2) : 3.4
*(balance + 3) : 17
*(balance + 4) : 50

5.传递数组给函数

  • C++ 不允许向函数传递一个完整的数组作为参数
  • 但是,您可以通过指定不带索引的数组名来传递一个指向数组的指针。

如果您想要在函数中传递一个一维数组作为参数,您必须以下面三种方式来声明函数形式参数,这三种声明方式的结果是一样的,因为每种方式都会告诉编译器将要接收一个整型指针。同样地,您也可以传递一个多维数组作为形式参数

方式1: 形式参数是一个指针

void myFunction(int *param){ }

方式2:形参为一个已经定义了大小的数组

void myFunction(int param[10]){ }

方式3: 形式参数是一个未定义大小的数组

void myFunction(int param[]){ }

实例:把数组作为参数,同时还传递了另一个参数,根据所传的参数,会返回数组中各元素的平均值

#include <iostream>
using namespace std;// 函数声明
double getAverage(int arr[], int size);int main ()
{int balance[5] = {1000, 2, 3, 17, 50};  // 带有 5 个元素的整型数组double avg;avg = getAverage(balance, 5) ;          // 传递一个指向数组的指针作为参数   cout << "平均值是:" << avg << endl;    // 输出返回值
}double getAverage(int arr[], int size)
{int    i, sum = 0;       double avg;          for (i = 0; i < size; ++i)sum += arr[i];avg = double(sum) / size;return avg;
}

平均值是:214.4

动态内存

了解动态内存在 C++ 中是如何工作的是成为一名合格的 C++ 程序员必不可少的。C++ 程序中的内存分为两个部分:

  • 栈:在函数内部声明的所有变量都将占用栈内存。
  • 堆:这是程序中未使用的内存,在程序运行时可用于动态分配内存。

很多时候,您无法提前预知需要多少内存来存储某个定义变量中的特定信息,所需内存的大小需要在运行时才能确定。

  • 在 C++ 中,您可以使用特殊的运算符为给定类型的变量在运行时分配堆内的内存,这会返回所分配的空间地址。这种运算符即 new 运算符。
  • 如果您不需要动态分配内存,可以使用 delete 运算符,删除之前由 new 运算符分配的内存。

1.new ,delete运算符

在这里插入图片描述

#include <iostream>
using namespace std;int main ()
{double* pvalue  = NULL; // 初始化为 null 的指针pvalue  = new double;   // 为变量请求内存*pvalue = 29494.99;     // 在分配的地址存储值cout << "Value of pvalue : " << *pvalue << endl;delete pvalue;         // 释放内存
}

Value of pvalue : 29495

2.数组的动态内存分配

在这里插入图片描述
二维数组

二维数组其实可以看成2个一维的数组,所以初始化也需要分成2步来初始化,先初始化行,然后初始化列。

int **array
// 假定数组第一维长度为 m, 第二维长度为 n// 动态分配空间
array = new int *[m];  //初始化行
//对每行初始化列
for( int i=0; i<m; i++ )
{array[i] = new int [n]  ;
}//释放
for( int i=0; i<m; i++ )
{delete [] arrar[i];
}
delete [] array;

实例

#include <iostream>
using namespace std;int main()
{int **p;   int i,j;   //p[4][8] //开始分配4行8列的二维数据   p = new int *[4];for(i=0;i<4;i++)p[i]=new int [8];for(i=0; i<4; i++){for(j=0; j<8; j++)p[i][j] = j*i;}   //打印数据   for(i=0; i<4; i++){for(j=0; j<8; j++)     {   if(j==0) cout<<endl;   cout<<p[i][j]<<"\t";   }}   //开始释放申请的堆   for(i=0; i<4; i++){delete [] p[i];   }delete [] p;   
}

运行结果:

0 0 0 0 0 0 0 0
0 1 2 3 4 5 6 7
0 2 4 6 8 10 12 14
0 3 6 9 12 15 18 21

vector

1.vector基本操作

在c++中,vector是一个十分有用的容器。

  • 作用:它能够像容器一样存放各种类型的对象,简单地说,vector是一个能够存放任意类型的动态数组,能够增加和压缩数据。
  • vector在C++标准模板库中的部分内容,它是一个多功能的,能够操作多种数据结构和算法的模板类和函数库。
    在这里插入图片描述

实例

#include <iostream>
#include <vector>
using namespace std;int main()
{vector<int> vec;  // 创建一个向量存储 intint i;cout << "vector size = " << vec.size() << endl; // 显示 vec 的原始大小for(i = 0; i < 5; i++)  // 推入 5 个值到向量中vec.push_back(i);cout << "extended vector size = " << vec.size() << endl;  // 显示 vec 扩展后的大小for(i = 0; i < 5; i++)cout << "value of vec [" << i << "] = " << vec[i] << endl; // 访问向量中的 5 个值// 使用迭代器 iterator 访问值vector<int>::iterator  v  = vec.begin();while( v != vec.end()) {cout << "value of v = " << *v << endl;v++;}
}

vector size = 0
extended vector size = 5
value of vec [0] = 0
value of vec [1] = 1
value of vec [2] = 2
value of vec [3] = 3
value of vec [4] = 4
value of v = 0
value of v = 1
value of v = 2
value of v = 3
value of v = 4

2.vector使用

特别注意

  • 1、如果你要表示的向量长度较长(需要为向量内部保存很多数),容易导致内存泄漏,而且效率会很低;
  • 2、Vector作为函数的参数或者返回值时,需要注意它的写法:
    double Distance(vector< int >&a, vector< int >&b) 其中的“&”绝对不能少!!!
  • 3.vector的元素不仅仅可以是int,double,string,还可以是结构体,但是要注意:结构体要定义为全局的,否则会出错。

算法

1.使用reverse将元素翻转,需要头文件#include< algorithm >

reverse(vec.begin(),vec.end());  //将元素翻转,即逆序排列!

在vector中,如果一个函数中需要两个迭代器,一般后一个都不包含

2.使用sort排序:需要头文件#include< algorithm >,

sort(vec.begin(),vec.end());  //默认是按升序排列,即从小到大

可以通过重写排序比较函数按照降序比较,如下:

//定义排序比较函数:
bool Comp(const int &a,const int &b)
{return a>b;
}//调用时
sort(vec.begin(),vec.end(),Comp) //这样就降序排序

3.vector动态二维数组 初始化和赋值

一维数组

#include <iostream> 
#include <vector>     
using namespace std;int main()  
{  vector<int> v={1,2,3};cout<<v[2]<<endl;v.push_back(3);cout<<v[3]<<endl;
}

3
3

二维数组
(1)第1种方法:通过 resize( ) 的形式改变行列数

#include <iostream>
#include <vector>
using namespace std;int main()
{int array_temp[4][4]={1,2,8,9,2,4,9,12,4,7,10,13,6,8,11,15};int i,j;//得到一个 4行4列的数组,通过resize()的形式改变行列数vector<vector<int> > array(4);for(i=0;i<array.size();i++)array[i].resize(4);for(i = 0; i < array.size(); i++){for (j = 0; j < array[0].size();j++)array[i][j] = array_temp[i][j];}cout<<array[2][3]<<endl;
}

(2)第2种方法:通过 push_back( )

#include <iostream>
#include <vector>
using namespace std;int main()
{int array_temp[4][4]={1,2,8,9,2,4,9,12,};int i,j;vector<vector<int> > array;vector<int> a;vector<int> b;for(i=0;i<4;i++)a.push_back(array_temp[0][i]);for(i=0;i<4;i++)b.push_back(array_temp[1][i]);cout<<"a[1]="<<a[1]<<endl;cout<<"b[2]="<<b[2]<<endl;array.push_back(a);array.push_back(b);cout<<array.size()<<endl;cout<<array[0].size()<<endl;cout<<array[1][2]<<endl;}

(3)第3种方法: 使用vector < int* > v1;

#include <iostream> 
#include <vector>     
using namespace std;int main()  
{  int out[3][2] = { 1, 2,   3, 4,  5, 6 };  vector <int*> v1;   //相当于每一行是一个一维的数组,每个元素保存的是该数组的第一个元素地址// vector <vector<int>> v1;  //这样是错误的v1.push_back(out[0]);  //压入第一行元素  v1.push_back(out[1]);  v1.push_back(out[2]);  cout << v1[0][0] << endl; //1  cout << v1[0][1] << endl; //2  cout << v1[1][0] << endl; //3  cout << v1[1][1] << endl; //4  cout << v1[2][0] << endl; //5  cout << v1[2][1] << endl; //6  }  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/445443.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构和算法(05)---链表(c++)

文章目录目录链表的基本概念1.数组和链表链表的使用1.链表的简单使用2.链表的进阶使用3.链表的高阶使用4.链表的其他操作链表容器list1.list介绍2. list使用3. list与vector之间的区别4.list例子代码目录 数据结构&#xff1a; 逻辑结构&#xff1a;数组&#xff0c;栈&#xf…

论文阅读 状态压缩

状态压缩 Abstract 信息学发展势头迅猛&#xff0c;信息学奥赛的题目来源遍及各行各业&#xff0c;经常有一些在实际应用中很有价值的问题被引入信息学并得到有效解决。然而有一些问题却被认为很可能不存在有效的(多项式级的)算法&#xff0c;本文以对几个例题的剖析&#xf…

数据结构和算法(06)---二叉树(c++)

文章目录目录二叉树1.二叉树的基本概念2.二叉树的应用和时间复杂度3.二叉树的插入4.二叉树的查找5. 二叉树的遍历6.二叉树的删除二叉树的基本操作1.二叉树的基础操作2.代码实现创建二叉树和三种遍历二叉树的方法目录 数据结构&#xff1a; 逻辑结构&#xff1a;数组&#xff0c…

如何转载CSDN博客

前言 对于喜欢逛CSDN的人来说&#xff0c;看别人的博客确实能够对自己有不小的提高&#xff0c;有时候看到特别好的博客想转载下载&#xff0c;但是不能一个字一个字的敲了&#xff0c;这时候我们就想快速转载别人的博客&#xff0c;把别人的博客移到自己的空间里面&#xff0c…

CSDN写博客(字体颜色、大小)

markdown里面的标记语言可以使用标签对来实现对文本文字颜色大小信息的控制。下面给出几个实例&#xff1a; 黑体字示例 微软雅黑示例 华文彩云示例 color#00ffff size可以根据实际大小进行设置&#xff0c;一般不超过7。 红色字体CSDN 红色字体CSDN 使用十六进制颜色值 …

bose qc30 安静的城市是什么样子

使用感受 网友1&#xff08;20岁&#xff09;&#xff1a; 当你带着这个耳机听音乐的时候&#xff0c;有一种感觉&#xff0c;感觉这个世界都是你歌曲里的MV&#xff0c;这个枯燥乏味的世界都被赋予了你心中的那份情感&#xff0c;这种感觉&#xff0c;真的很棒 网友2&#…

DeepLearning.ai 提炼笔记(5-1)-- 循环神经网络

参考博客 Class 5: 序列模型Sequence Models Week 1: 循环神经网络RNN (Recurrent) 文章目录Class 5: 序列模型Sequence ModelsWeek 1: 循环神经网络RNN (Recurrent)目录序列模型-循环神经网络1.序列模型的应用2.数学符号3.循环神经网络模型传统标准的神经网络循环神经网络的…

常见人工智能比赛平台总结

目录1.kaggle比赛1.1 kaggle比赛是什么&#xff1f;1.2 为什么举办kaggle比赛&#xff1f;1.3 kaggle比赛形式是什么&#xff1f;1.4 kaggle比赛的奖励制度是什么&#xff1f;2.阿里天池比赛2.1 阿里天池比赛是什么&#xff1f;2.2 为什么举办阿里天池比赛&#xff1f;2.3 阿里…

机器学习模型评分总结(sklearn)

文章目录目录模型评估评价指标1.分类评价指标acc、recall、F1、混淆矩阵、分类综合报告1.准确率方式一&#xff1a;accuracy_score方式二&#xff1a;metrics2.召回率3.F1分数4.混淆矩阵5.分类报告6.kappa scoreROC1.ROC计算2.ROC曲线3.具体实例2.回归评价指标3.聚类评价指标1.…

kaggle (02) - 房价预测案例(进阶版)

房价预测案例&#xff08;进阶版&#xff09; 这是进阶版的notebook。主要是为了比较几种模型框架。所以前面的特征工程部分内容&#xff0c;我也并没有做任何改动&#xff0c;重点都在后面的模型建造section Step 1: 检视源数据集 import numpy as np import pandas as pd读…

《Head First设计模式》第二章笔记 观察者模式

背景 客户有一个WeatherData对象&#xff0c;负责追踪温度、湿度和气压等数据。现在客户给我们提了个需求&#xff0c;让我们利用WeatherData对象取得数据&#xff0c;并更新三个布告板&#xff1a;目前状况、气象统计和天气预报。 WeatherData对象提供了4个接口&#xff1a; …

《Head First设计模式》第三章笔记 装饰者模式

装饰者模式&#xff08;Decorator Pattern) *利用组合&#xff08;composition&#xff09;和委托&#xff08;delegation&#xff09;可以在运行时实现继承行为的效果&#xff0c;动态地给对象加上新的行为。 *利用继承扩展子类的行为&#xff0c;是在编译时静态决定的&#x…

机器学习中如何解决数据不平衡问题?

文章目录目录什么是数据不平衡问题&#xff1f;数据不平衡会造成什么影响&#xff1f;如何处理数据不平衡问题&#xff1f;1、重新采样训练集1.1随机欠抽样1.2.基于聚类的过采样2.使用K-fold交叉验证3.转化为一分类问题4.组合不同的重采样数据集5.用不同比例重新采样6.多模型Ba…

《Head First设计模式》第四章笔记 工厂模式

之前我们一直在使用new操作符&#xff0c;但是实例化这种行为并不应该总是公开的进行&#xff0c;而且初始化经常会造成耦合问题&#xff0c;工厂模式将摆脱这种复杂的依赖&#xff0c;本次内容包括简单工厂&#xff0c;工厂方法和抽象工厂三种情况。 1 2 3 4 5 6 Duck duck&a…

《Head First设计模式》第五章笔记-单件模式

单件模式 定义&#xff1a;确保一个类只有一个实例&#xff0c;并提供全局访问点。 编写格式&#xff1a; 1 2 3 4 5 6 public class MyClass{ private MyClass(){}//构造方法私有化 public static MyClass getInstance(){ //提供全局访问点 return new My…

《Head First设计模式》第六章笔记-命令模式

封装调用-命令模式 命令模式可将“动作的请求者”从“动作的执行者”对象中解耦。 本篇中将不再描述书中所引入的“巴斯特家电自动化公司”的遥控器控制案例&#xff0c;而使用简单易懂的餐厅案例。 在开始之前&#xff0c;让我们通过一个现实中的例子来了解命令模式。 理解…

一文读懂机器学习库graphLab

文章目录目录什么是graphlab为什么使用graphlab?如何安装graphlab?graphlab的简单使用。目录 什么是graphlab GraphLab 是由CMU&#xff08;卡内基梅隆大学&#xff09;的Select 实验室在2010 年提出的一个基于图像处理模型的开源图计算框架&#xff0c;框架使用C语言开发实…

《Head First设计模式》第七章-适配器模式、外观模式

适配器模式 适配器模式是什么&#xff0c;你一定不难理解&#xff0c;因为现实中到处都是。比如说&#xff1a; 如果你需要在欧洲国家使用美国制造的笔记本电脑&#xff0c;你可能需要使用一个交流电的适配器…… 当你不想改变现有的代码&#xff0c;解决接口不适配问题&#…

《Head First设计模式》第八章笔记-模板方法模式

模板方法模式 之前所学习的模式都是围绕着封装进行&#xff0c;如对象创建、方法调用、复杂接口的封装等&#xff0c;这次的模板方法模式将深入封装算法块&#xff0c;好让子类可以在任何时候都将自己挂接进运算里。 模板方法定义&#xff1a;模板方法模式在一个方法中定义一…

机器学习基础-吴恩达-coursera-(第一周学习笔记)----Introduction and Linear Regression

课程网址&#xff1a;https://www.coursera.org/learn/machine-learning Week 1 —— Introduction and Linear Regression 目录 Week 1 Introduction and Linear Regression目录一 介绍1-1 机器学习概念及应用1-2 机器学习分类 二 单变量的线性回归2-1 假设函数hypothesis2…