认识栈结构和特性
相比较数组而言,栈是一种受限的线性结构。
栈结构示意图
栈,一种受限的线性结构,后进先出(LIFO)
- 仅允许在一端进行插入和删除运算。这一端叫做栈顶,相对的,把另一端叫做栈底。
- 后进先出表示后进入的元素,第一个弹出栈空间。类似于电梯。
- 向一个栈插入新元素又称为进栈、入栈或压栈。
- 从一个栈删除元素又称作出栈或退栈。
生活中类似于栈的
- 进出电梯
栈结构面试题
/* 面试题目:
有六个元素6,5,4,3,2,1 的顺序进栈,问下列哪一个不是合法的出栈序列?( )
A. 5 4 3 6 1 2 B. 4 5 3 2 1 6 C. 3 4 6 5 2 1 D. 2 3 4 1 5 6
答案: C
解析
A答案: 65进栈, 5出栈, 4进栈出栈, 3进栈出栈, 6出栈, 21进栈, 1出栈, 2出栈
B答案: 654进栈,45出栈,3进栈出栈,2进栈出栈,1进栈出栈,6出栈
D答案: 65432进栈,2出栈,3出栈,4出栈,1进栈出栈,5出栈,6出栈
/*
栈结构的实现
实现栈结构有两种比较常见的方式:
- 基于数组实现
- 基于链表实现
我们这里先基于数组实现栈结构,基于链表结构的后面再补充。
创建栈的类
class ArrayStack<T> {
private data: T[] = [];
}
- 创建一个Stack类,可以定义一个泛型类。
- 在构造函数中,定义了一个数组类型的变量,这个变量可以用于保存当前栈对象
- 之后的进栈还是出栈操作,都是从数组中添加和删除元素
- 栈有一些相关的操作方法,通常无论是什么语言,操作都是比较类似的。
栈的操作
栈常见有哪些操作呢?
- push(element): 添加一个新元素到栈顶位置。
- pop(): 移除栈顶元素,同时返回被移除的元素
- peek(): 返回栈顶元素,不对栈做任何修改
- isEmpty(): 如果栈里没有任何元素就返回true,否则返回false
- size(): 返回栈里面元素的个数,和数组的length属性很类似。
现在我们在类中实现这些方法:
class ArrayStack<T> {
private data: T[] = [];
push(element: T){
this.data.push(element);
}
pop(): T | undefined {
return this.data.pop();
}
peek(): T | undefined {
}
isEmpty(): boolean {
return this.data.length === 0;
}
size(): number {
return this.datat.length;
}
}
面试题
一、十进制转二进制
现实生活中,我们主要使用十进制。但在计算科学中,二进制非常重要,因为计算机里所有的内容都是用二进制数字表示的(0和1)。没有十进制和二进制相互转化的能力,与计算机交流就很困难。
要把十进制转化成二进制,我们可以将该十进制数除以2(二进制是满二进一)并对商取整,直到结果是0为止。举个例子,把十进制的数10转化为二进制的数,大致过程是如下这样的。
代码如下:
function decimalToBinary(num: number): string {
// 先创建一个栈
const stack = new ArrayStack<number>();
while (num > 0) {
// 循环体
const remainder = num % 2;
stack.push(remainder);
num = Math.floor(num / 2);
}
// 依次出栈
let binary = "";
while (!stack.isEmpty()) {
binary += stack.pop();
}
return binary;
}
有效的括号
给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须一正确的顺序闭合。
- 每个右括号都有一个对应的相同类型的左括号。
function isValid(s: string): boolean {
// 1. 创建一个栈
const stack = new ArrayStack<string>();
// 循环整个字符串
for (let i = 0; i < s.length; i++) {
const element: string = s[i];
switch (element) {
case "(":
stack.push(")");
break;
case "{":
stack.push("}");
break;
case "[":
stack.push("]");
break;
default:
if(element !== stack.pop()){
return false;
}
break;
}
}
// 最后栈不能为空
return stack.isEmpty();
}