学习笔记①
阶段一:基础算法和数据结构
一.数据结构
- 数组、链表、栈、队列的基本操作
栈
-
栈(Stack)是一种线性存储结构,它具有如下特点:
(1)栈中的数据元素遵守“先进后出"(First In Last Out)的原则,简称FILO结构。(后进先出的叫法,也是可以的)
(2)限定只能在栈顶进行插入和删除操作。
-
栈的相关概念:
(1)栈顶与栈底:允许元素插入与删除的一端称为栈顶,另一端称为栈底。
(2)压栈:栈的插入操作,叫做进栈,也称压栈、入栈。
(3)弹栈:栈的删除操作,也叫做出栈。
-
栈的常用操作为:
(1)弹栈,通常命名为pop
(2)压栈,通常命名为push
(3)求栈的大小
(4)判断栈是否为空
(5)获取栈顶元素的值
-
栈的常见分类:
(1)基于数组的栈——以数组为底层数据结构时,通常以数组头为栈底,数组头到数组尾为栈顶的生长方向
(2)基于单链表的栈——以链表为底层的数据结构时,以链表头为栈顶,便于节点的插入与删除,压栈产生的新节点将一直出现在链表的头部
队列
- 队列(Queue)与栈一样,是一种线性存储结构,它具有如下特点:
(1)队列中的数据元素遵循“先进先出”(First In First Out)的原则,简称FIFO结构;
(2)在队尾添加元素,在队头删除元素。
- 队列的相关概念:
(1)队头与队尾: 允许元素插入的一端称为队尾,允许元素删除的一端称为队头;
(2)入队:队列的插入操作;
(3)出队:队列的删除操作。
- 队列的操作:
(1)入队: 通常命名为push()
(2)出队: 通常命名为pop()
(3)求队列中元素个数
(4)判断队列是否为空
(5)获取队首元素
- 队列的分类:
(1)基于数组的循环队列(循环队列)
(2)基于链表的队列(链队列)
//定义栈如下:
stack<int> s;
//定义队列如下:
queue<int> q;
//栈提供了如下的操作:
s.empty() //如果栈为空返回true,否则返回false
s.size() //返回栈中元素的个数
s.pop() //删除栈顶元素但不返回其值
s.top() //返回栈顶的元素,但不删除该元素
s.push() //在栈顶压入新元素
//队列提供了下面的操作:
q.empty() //如果队列为空返回true,否则返回false
q.size() //返回队列中元素的个数
q.pop() //删除队列首元素但不返回其值
q.front() //返回队首元素的值,但不删除该元素
q.push() //在队尾压入新元素
q.back() //返回队列尾元素的值,但不删除该元素
数组
- 初始化
int a[10];
memset(a,0,sizeof(a)); //初始化为0
memset(a,-1,sizeof(a));//初始化为-1
memset(a,0x3f,sizeof(a));//初始化为无穷大
char b[10];
memset(b,1,sizeof(b));//初始化为1(可以是任何值)
- 返回数组大小
int a[]={1,2,3,4};
int num=sizeof(a)/sizeof(a[0]);
动态数组vector
-
初始化
vector<int> v; vector<int> v(5);//初始大小为5 vector<int> v(10,1);//初始大小为10且值都为1
-
增加函数
\(\operatorname{push\_back()}\) 在数组的末尾添加一个数据
for(int i=1;i<=10;i++) v.push_back(i);//将1-10依次加入数组
\(\operatorname{insert()}\) 插入
v.insert(v.begin(),8);//在数组首位插入新元素 v.insert(v.begin()+2,8)//在第二个元素前插入新元素 v.insert(v.end(),3,1);//在最后一个元素后添加3个1 v.insert(v.end(),v2.begin(),v2.end());//在数组末尾添加v2中的数据
-
删除函数
\(\operatorname{pop\_back()}\) 删除队尾元素
v.pop_back();
\(\operatorname{erase()}\) 删除任意位元素
v.erase(v.begin()+3);//删除第3位元素 v.erase(v.begin()+2,v.begin()+4);//删除v里面[2,3)的元素(第2个元素)
\(\operatorname{clear()}\) 清空当前数组
只能清除数据,不能释放内存。
v.clear();
v.swap(vector<int>())//释放内存空间
-
遍历函数
\(\operatorname{at()}\) 得到编号位置的数据
v.at(3);//第三位的数值
\(\operatorname{front()}\) 引用数组头元素(begin、end返回值是指针)
int f=v.front();
\(\operatorname{back()}\) 引用数组末尾元素
int b=v.back();
\(\operatorname{begin()}\) 返回第一个元素的指针
\(\operatorname{end()}\) 返回最后一个元素的指针
vector<int>::iterator iter; iter = v.begin()+4; cout << *iter << endl;
//使用begin()实现遍历 for(vector<int>::iterator iter=v.begin();iter!=v.end();++iter) { cout<<" "<<*iter; }
-
判断函数
\(\operatorname{empty()}\) 判断数组是否为空
cout << " v.empty(): " << v.empty() << endl;
输出值为0/1
-
大小函数
\(\operatorname{size()}\) 当前数组使用数据的大小
int size = v.size();
\(\operatorname{capasity()}\) vector实际能容纳的大小
int cap = v.capacity();
\(\operatorname{max\_size()}\) vector最大可允许使用的元素数量值
int max = v.max_size();
-
其他函数
\(\operatorname{swap()}\) 交换
vector<int> v(4,10); v.swap(vector<int> ()); vector<int>().swap(v);
\(\operatorname{assign}\) 使用括号内的值设置当前vector
vector<int> v; vetor<int> first(4,10); v.assign(7,3); //分配七个3 v.assign(first.begin(),first.end());
\(\operatorname{resize()}\) 调整数组大小
v.resize(10);//将v中现有元素调为10个,多删少补,其值随机 v.resize(10,2)//将v中现有元素调为10个,多删少补,其值为2
-
误区
for(int i=1;i<=10;i++) v[i]=i;
这种做法是错误的。下标只能用于获取已经存在的元素,而当 \(a_i\) 还为空时不能操作。
参考链接:
数据结构图文解析之:数组、单链表、双链表介绍及C++模板实现
[C++ vector的用法(整理](C++ vector的用法(整理)-CSDN博客)