Perl 数组操作:push() 与 pop()
Perl 中的数组是动态的、有序的元素集合。push() 和 pop() 是两个最常用的数组操作函数,分别用于在数组末尾添加和移除元素。它们的行为类似于栈(stack)结构中的“入栈”和“出栈”,使用起来非常直观。
push():向数组末尾添加元素
push() 函数的作用是把一个或多个元素追加到数组的末尾。
调用语法:
push(@array, $element);
# 或一次添加多个
push(@array, $elem1, $elem2, $elem3);
执行效果:
- 原数组长度增加。
- 新元素按顺序排在最后。
- 函数返回操作后数组的总长度(但通常我们不关心这个返回值)。
操作步骤
- 准备一个数组变量,例如
@fruits = ("apple", "banana");。 - 调用
push(),把新元素传入:push(@fruits, "cherry"); - 此时
@fruits的内容变为("apple", "banana", "cherry")。
你也可以一次添加多个元素:
push(@fruits, "date", "elderberry");
执行后,数组变成 ("apple", "banana", "cherry", "date", "elderberry")。
注意:
push()的第一个参数必须是数组变量(以@开头),不能是数组引用或列表字面量。
pop():从数组末尾移除元素
pop() 函数的作用是从数组末尾取出并移除最后一个元素。
调用语法:
$last_element = pop(@array);
```
**执行效果**:
- 数组长度减 1。
- 被移除的元素作为函数的返回值。
- 如果数组为空,`pop()` 返回 `undef`(Perl 中的“未定义”值)。
### 操作步骤
1. **确保数组非空**(可选,但避免逻辑错误)。
2. **调用 `pop()`** 并接收返回值:
```perl
my $removed = pop(@fruits);
- `$removed` 现在保存了被移除的元素,而 `@fruits` 少了一个末尾项。
例如,若 `@fruits = ("apple", "banana", "cherry")`,执行:
```perl
my $fruit = pop(@fruits);
之后:
- `$fruit` 的值是 `"cherry"`, - `@fruits` 变为 `("apple", "banana")`。 如果连续调用 `pop()`: ```perl pop(@fruits); # 移除 "banana" pop(@fruits); # 移除 "apple" ``` 此时 `@fruits` 为空数组 `()`。 --- ## 组合使用:模拟栈操作 `push()` 和 `pop()` 天然支持“后进先出”(LIFO)的栈行为。你可以用它们轻松实现撤销操作、表达式求值、深度优先搜索等算法。 ### 示例:简易撤销历史 ```perl my @history = (); my $current = "start";
执行操作并记录历史
$current = "step1"; push(@history, $current);
$current = "step2"; push(@history, $current);
撤销:回到上一步
$current = pop(@history); # $current = "step1"
每次“执行”就 `push()`,每次“撤销”就 `pop()`,逻辑清晰且高效。
---
## 常见误区与注意事项
| 问题 | 正确做法 | 错误示例 |
| :--- | :---: | :--- |
| 对标量使用 `push` | 必须作用于数组变量 | `push($scalar, "x")` ❌ |
| 忘记接收 `pop()` 返回值 | 若需要被移除的值,应赋值给变量 | `pop(@arr);`(丢弃结果,有时合理,但需明确意图) |
| 在空数组上调用 `pop()` | 合法,但返回 `undef` | 需用 `defined()` 判断是否真有值 |
例如,安全地处理空数组:
```perl
if (@stack) {
my $top = pop(@stack);
# 处理 $top
}
```
或者:
```perl
my $item = pop(@stack);
if (defined $item) {
# 使用 $item
}
性能说明
push() 和 pop() 的时间复杂度都是 O(1) —— 无论数组多大,操作速度几乎不变。这是因为 Perl 内部为数组预留了额外空间,并维护了起始和结束指针,无需移动已有元素。
相比之下,对数组开头操作(如 shift() / unshift())可能涉及内存移动,效率较低。因此,优先使用 push() / pop() 而非 unshift() / shift(),除非逻辑上必须从头部操作。
实战练习:括号匹配检查
利用 push() 和 pop() 可快速验证括号是否配对:
sub is_balanced {
my ($str) = @_;
my @stack = ();
for my $char (split //, $str) {
if ($char eq '(') {
**push**(@stack, $char);
} elsif ($char eq ')') {
return 0 unless @stack; # 多余右括号
**pop**(@stack); # 匹配成功,弹出左括号
}
}
return @stack == 0; # 栈空则匹配
}
# 测试
print is_balanced("((()))") ? "OK" : "NO"; # OK
print is_balanced("(()") ? "OK" : "NO"; # NO
此代码逐字符扫描字符串,遇到左括号就 push(),遇到右括号就 pop()。若中途栈空却要 pop(),说明右括号多余;若结束时栈非空,说明左括号多余。
my @list = (1, 2, 3);
push(@list, 4); # @list = (1,2,3,4)
my $last = pop(@list); # $last = 4, @list = (1,2,3)
暂无评论,快来抢沙发吧!