序列
序列
概述
在前面的章节中,我们学习到了数组(C++与Java
中)。如果我们需要记录 个数,我们并不需要定义
个变量,而是只需要定义一个长度为
的数组。
为什么我们需要序列?
假设我们现在定义了一个长度为
的数组
arr
,并在这个数组中放入了这
个数。根据在数组一章的知识,我们可以这样写:
代码实现
#include <bits/stdc++.h>
using namespace std;
int arr[100];
int main() {
for (int i = 0; i < 100; i++) { // 注意!长度为 100 的数组的合法索引范围应为 0 ~ 99
arr[i] = i + 1;
// 将 arr[i] 赋值为 i + 1
}
for (int i = 0; i < 100; i++) {
cout << arr[i] << " ";
}
return 0;
}
public class Main {
public static void main(String[] args) {
int[] arr = new int[100]; // 创建长度为 100 的数组
// 填充数组,arr[i] 为 i + 1
for (int i = 0; i < 100; i++) {
arr[i] = i + 1;
}
// 输出数组的元素
for (int i = 0; i < 100; i++) {
System.out.print(arr[i] + " ");
}
}
}
但是! 如果我们现在想再多记录一个数呢?由于数组的长度在声明的时候就需要给定,我们无法改变数组的长度。所以,我们需要序列以解决这个问题。
序列的基本操作
序列有以下的常用操作:
- 将元素加入序列末尾:将一个元素加入到序列的末尾。例如将
加入到
的末尾,序列变为
。
- 弹出末尾的元素:删除末尾的元素。例如弹出
的末尾,序列变为
。
- 查询序列的长度:查询当前序列中元素的个数。例如
的长度为
。
- 清空序列:将序列中所有元素删除,也就是让序列变成空序列。
C++
在 C++ 中,序列通常是通过标准库中的 vector
类来表示的,vector
是一种动态数组,它可以存储任意类型的数据,并且会自动扩展或收缩以适应数据的变化。
#include <bits/stdc++.h>
using namespace std;
int main() {
vector<int> vec1; // 声明了一个用于存放 int 类型数据的序列
vector<char> vec2; // 声明了一个用于存放 char 类型数据的序列
vector<vector<int>> vec3; // 声明了一个用于存放 vector<int> 类型数据的序列
return 0;
}
在这里,我们可以把 vector<int>
看成一种数据类型(就和 int
,char
,long long
一样)。其中,我们一般用 vector<T>
表示序列,而 T
可以被替换成任意数据类型(int
,char
,自定义的结构体,或者是 vector<T>
)。
注意:
vector
是类型安全的容器,声明时需要指定元素类型。例如:vector<int>
只允许存储int
类型的元素,vector<char>
只允许存储char
类型的元素。- 需要注意的是,
vector
是基于动态数组实现的,它会自动扩展或收缩,所以不需要显式指定大小。
需要注意的是,上述代码声明的序列长度为 ,也就是说,你需要通过
push_back
操作来放入元素,而不能直接使用例如 vec1[3] = 0
的方法来给序列赋值。你可以尝试以下代码:
#include <bits/stdc++.h>
using namespace std;
int main() {
vector<int> vec1; // 声明了一个用于存放 int 类型数据的序列
cout << vec1[3] << '\n'; // 尝试访问索引为 3 的元素
return 0;
}
这是一个未定义行为。根据上文,我们只声明了一个空的序列。也就是说,这个序列的长度为 。访问其中第
个元素是未定义行为(和数组越界的逻辑一致)。
所以,我们需要学习怎么声明一个长度不为 的序列。(当然,由于序列的长度是可变的,所以我们预先声明一定长度的序列实际上可以被更改长度)。语法如下:
vector<int> vec1(5); // 声明一个长度为 5 的 vector,初始值为 0,即初始元素为 {0, 0, 0, 0, 0}
vector<int> vec2(5, 123); // 声明一个长度为 5 的 vector,初始值为 123,即初始元素为 {123, 123, 123, 123, 123}
vector<int> vec3 = {1, 2, 3, 4}; // 声明一个 vector,其中初始元素为 {1, 2, 3, 4}
在 C++ 中,序列最常用的操作可以通过以下代码实现:
添加元素(末尾) | 序列变量名.push_back(需要添加的元素) | vec.push_back(3) |
|
删除元素(末尾) | 序列变量名.pop_back() | vec.pop_back() |
|
访问元素 | 序列变量名[索引] | vec[0] |
|
修改元素 | 序列变量名[索引] = 新值 | vec[0] = 5 |
|
获取序列长度 | 序列变量名.size() | vec.size() |
|
判断序列是否为空 | 序列变量名.empty() | vec.empty() |
|
清空序列 | 序列变量名.clear() | vec.clear() |
Java
在 Java 中,序列通常通过 ArrayList
类来表示,它是一个动态数组,可以自动扩展或收缩以适应数据的变化。
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>(); // 声明一个长度为 5 的 ArrayList,初始值为 0,即初始元素为 {0, 0, 0, 0, 0}
ArrayList<Integer> list = new ArrayList<>(Collections.nCopies(5, 123)); // 声明一个长度为 5 的 ArrayList,初始值为 123,即初始元素为 {123, 123, 123, 123, 123}
List<Integer> list = Arrays.asList(1, 2, 3, 4); // 声明一个 ArrayList,其中初始元素为 {1, 2, 3, 4}
}
}
在 Java
中,序列最常用的操作可以通过以下代码实现:
添加元素(末尾) | 序列变量名.add(需要添加的元素) |
list.add(3) |
|
删除元素(末尾) | 序列变量名.remove(序列变量名.size() - 1) |
list.remove(list.size() - 1) |
|
访问元素 | 序列变量名.get(索引) |
list.get(0) |
|
修改元素 | 序列变量名.set(索引, 新值) |
list.set(0, 5) |
|
获取序列长度 | 序列变量名.size() |
list.size() |
|
判断序列是否为空 | 序列变量名.isEmpty() |
list.isEmpty() |
|
清空序列 | 序列变量名.clear() |
list.clear() |
Python
在 Python
中,序列通常使用 list
来表示,它是一个灵活的容器,可以存储不同类型的数据。
my_list = [] # 声明一个空的列表
my_list = [123] * 5 # 声明一个长度为 5 的列表,初始化为 123,即初始元素为 {123, 123, 123, 123, 123}
my_list = [1, 2, 3, 4] # 声明一个列表,其中初始元素为 {1, 2, 3, 4}
在 Python
中,序列最常用的操作可以通过以下代码实现:
添加元素(末尾) | 序列变量名.append(需要添加的元素) |
my_list.append(3) |
|
删除元素(末尾) | 序列变量名.pop() |
my_list.pop() |
|
访问元素 | 序列变量名[索引] |
my_list[0] |
|
修改元素 | 序列变量名[索引] = 新值 |
my_list[0] = 5 |
|
获取序列长度 | len(序列变量名) |
len(my_list) |
|
判断序列是否为空 | len(序列变量名) == 0 |
len(my_list) == 0 |
|
清空序列 | 序列变量名.clear() |
my_list.clear() |
序列的遍历
序列的遍历与数组的遍历相似,也是按照顺序访问序列中的所有元素。
vector<int> vec = {1, 2, 3, 4};
for (int i = 0; i < vec.size(); i++) {
cout << vec[i] << " "; // 输出每个元素
}
for (int value : vec) {
cout << value << " "; // 输出每个元素
}
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
for (int i = 0; i < list.size(); i++) {
System.out.print(list.get(i) + " "); // 输出每个元素
}
for (int value : list) {
System.out.print(value + " "); // 输出每个元素
}
my_list = [1, 2, 3, 4]
for i in range(len(my_list)):
print(my_list[i], end=" ") # 输出每个元素
for value in my_list:
print(value, end=" ") # 输出每个元素
序列的排序
对于一个序列(以 为例),升序排序指按照元素的大小从小到大排序,结果为
;降序排序指按照元素的大小从大到小排序,结果为
。
/*
升序排序:sort(vec.begin(), vec.end())
降序排序:sort(vec.begin(), vec.end(), greater<int>())
*/
#include <bits/stdc++.h>
using namespace std;
int main() {
vector<int> v = {1, 1, 4, 5, 1, 4};
// 使用自定义比较函数进行排序
sort(v.begin(), v.end());
// 输出排序结果
for (int i = 0; i < v.size(); i++) {
cout << v[i] << " ";
}
return 0;
}
/*
升序排序:Collections.sort(list)
降序排序:Collections.sort(list, Collections.reverseOrder())
下文为自定义排序方法
*/
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
class Point {
int x, y;
// 构造函数
Point(int x, int y) {
this.x = x;
this.y = y;
}
}
public class Main {
public static void main(String[] args) {
ArrayList<Point> points = new ArrayList<>();
points.add(new Point(1, 3));
points.add(new Point(2, 2));
points.add(new Point(3, 1));
points.add(new Point(4, 4));
// 自定义排序:按照 x * y 降序排序
Collections.sort(points, new Comparator<Point>() {
@Override
public int compare(Point a, Point b) {
return (b.x * b.y) - (a.x * a.y); // 按照 x * y 降序排序
}
});
// 输出排序结果
for (Point p : points) {
System.out.print("(" + p.x + ", " + p.y + ") ");
}
}
}
# 升序排序:sorted(my_list) 或 my_list.sort()
# 降序排序:sorted(my_list, reverse=True) 或 my_list.sort(reverse=True)
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f"({self.x}, {self.y})"
# 创建结构体对象列表
points = [Point(1, 3), Point(2, 2), Point(3, 1), Point(4, 4)]
# 自定义排序:按照 x * y 降序排序
points_sorted = sorted(points, key=lambda p: p.x * p.y, reverse=True)
# 输出排序结果
print(points_sorted)
练习
题目描述
给定一个序列,你需要维护以下操作:
- 操作
:向序列的末尾增加一个数
- 操作
:删掉序列末尾的数(保证此时序列非空)
- 操作
:输出序列中第
个数(起始下标为
)
- 操作
:向序列中的第
个数与第
个数之间插入一个数
(起始下标为
)
- 操作
:将序列升序排序
- 操作
:将序列降序排序
- 操作
:输出序列的长度
- 操作
:输出整个序列
#include <bits/stdc++.h>
using namespace std;
int main() {
vector<int> vec;
int n, i, x, count;
string operation;
cin >> count; // 输入操作的次数
while (count--) {
cin >> operation;
if (operation == "1") {
cin >> x;
vec.push_back(x); // 向序列末尾增加一个数
}
else if (operation == "2") {
vec.pop_back(); // 删掉序列末尾的数
}
else if (operation == "3") {
cin >> i;
cout << vec[i] << endl; // 输出序列中第 i 个数
}
else if (operation == "4") {
cin >> i >> x;
vec.insert(vec.begin() + i, x); // 插入数 x 在第 i 和 i + 1 之间
}
else if (operation == "5") {
sort(vec.begin(), vec.end()); // 升序排序
}
else if (operation == "6") {
sort(vec.begin(), vec.end(), greater<int>()); // 降序排序
}
else if (operation == "7") {
cout << vec.size() << endl; // 输出序列的长度
}
else if (operation == "8") {
for (int v : vec) {
cout << v << " "; // 输出整个序列
}
cout << endl;
}
}
return 0;
}
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
List<Integer> list = new ArrayList<>();
int count = sc.nextInt(); // 输入操作的次数
for (int i = 0; i < count; i++) {
String operation = sc.next();
if (operation.equals("1")) {
int x = sc.nextInt();
list.add(x); // 向序列末尾增加一个数
}
else if (operation.equals("2")) {
list.remove(list.size() - 1); // 删掉序列末尾的数
}
else if (operation.equals("3")) {
int index = sc.nextInt();
System.out.println(list.get(index)); // 输出序列中第 i 个数
}
else if (operation.equals("4")) {
int index = sc.nextInt();
int x = sc.nextInt();
list.add(index, x); // 插入数 x 在第 i 和 i + 1 之间
}
else if (operation.equals("5")) {
Collections.sort(list); // 升序排序
}
else if (operation.equals("6")) {
Collections.sort(list, Collections.reverseOrder()); // 降序排序
}
else if (operation.equals("7")) {
System.out.println(list.size()); // 输出序列的长度
}
else if (operation.equals("8")) {
for (int v : list) {
System.out.print(v + " "); // 输出整个序列
}
System.out.println();
}
}
}
}
# 导入所需模块
from collections import deque
def main():
# 使用 deque 来模拟 Java 中的 List
my_list = []
count = int(input()) # 输入操作的次数
for _ in range(count):
operation = input() # 读取操作类型
if operation == "1":
x = int(input()) # 向序列末尾增加一个数
my_list.append(x)
elif operation == "2":
my_list.pop() # 删掉序列末尾的数
elif operation == "3":
index = int(input()) # 输出序列中第 i 个数
print(my_list[index])
elif operation == "4":
index = int(input()) # 插入数 x 在第 i 和 i + 1 之间
x = int(input())
my_list.insert(index + 1, x)
elif operation == "5":
my_list.sort() # 升序排序
elif operation == "6":
my_list.sort(reverse=True) # 降序排序
elif operation == "7":
print(len(my_list)) # 输出序列的长度
elif operation == "8":
print(*my_list) # 输出整个序列
if __name__ == "__main__":
main()
课后习题
汗牛充栋,学海无涯。<br/> 内含算法知识点讲解,以及牛客题库精选例题。<br/> 学习算法,从牛栋开始。