栈:受限的线性结构
规则:
栈遵循后进先出/先进后出
后进先出 Last in first out FIFO
栈的详解:
1.
2.
3.
4.
5.
6.注意:此时,如果想要将所有元素出栈,必须是元素4先出栈,元素3再出栈,然后再是元素1出栈。
封装栈(es6):
class Stack{
// 封装栈结构
constructor(){
this.item=[]
}
// 1.向栈顶添加元素 数组呃最后添加元素
push(ele){
this.item.push(ele)
}
// 2.移除栈顶元素,返回栈顶元素(数组最后一个元素)
pop(){
let delnode=this.item.pop()
return delnode
}
// 3.返回栈顶元素(数组最后一个元素)
peek(){
let index=this.item.length-1
return this.item[index]
}
// 4.判空 栈为空true 数组的length长度来判断栈是否为空
isEmpty(){
return this.item.length==0
}
// 5.清空栈
clear(){
this.item=[]
}
// 6.栈元素的个数==数组中元素的个数
size(){
return this.item.length
}
}
栈的相关面试题:
1.有六个元素6,5,4,3,2,1的顺序进栈,问以下哪一个不是合法的出栈顺序?(C)
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
2.设栈的输入序列是1234,问以下哪一个不是合法的出栈顺序?(D)
A.1 2 4 3 B.2 1 3 4 C.1 2 3 4 D.4 3 1 2 E.3 2 1 4
3.设栈的输入序列是12345,问以下哪一个不是合法的出栈顺序?(B)
A.2 1 4 3 5 B.5 4 1 3 2 C.2 3 1 4 5 D.1 5 4 3 2
4.设栈的输入序列是12345,问以下哪一个是合法的出栈顺序?(D)
A.5 1 2 3 4 B.4 5 1 3 2 C.4 3 1 2 5 D.3 2 1 5 4
解析第一题的A选项:问题的关键在元素是按顺序进栈,在所有元素进栈的中间过程:栈内的元素是可以出栈的
根据题目作图:
1.A选项:将元素6,元素5压入栈内,再让元素5出栈:
2.A选项:再让元素4入栈,出栈,然后再让元素3入栈,出栈
3.选项A:让元素6出栈,再让元素2、元素1入栈
4.选项A:让元素1、元素2出栈
相关设计代码:
1.设计一个括号是否匹配的方法(栈)
匹配:({[ ]})、{()}
不匹配:({ }]、[( )
<!--1.设计一个括号是否匹配的方法(栈) -->
<script src="Stack.js"></script>
<script>
function pipei(str){
// 如果传入的实参是左括号,就向栈顶添加元素
// 如果传入的实参是右括号,就判断栈内的栈顶元素是否与传入的实参一致
// 如果不一致,就返回false
// 遍历完成,判断栈是否为空
// 空:返回true
// 非空:返回false
var stack=new Stack()
// 将传入的字符串中的元素进行遍历
for(var i=0;i<str.length;i++){
// 如果是下面这些左边的括号,就直接压入栈内
if(str[i]=="("||str[i]=="["||str[i]=="{"){
stack.push(str[i])
}else{
// 如果遍历到的元素不是左边的括号
// 就判断该括号与栈内的栈顶元素对应的右括号是一致的
// 如果是,就移除栈顶元素,并继续执行后面的代码
// 如果不是,证明括号不匹配,就返回false,就不执行后面的代码
switch(str[i]){
case "}":re=stack.pop();
if(re!="{"){
return false
}
break;
case "]":re=stack.pop();
if(re!="["){
return false
}
break;
case ")":re=stack.pop();
if(re!="("){
return false
}
break;
default:
break;
}
}
}
// 当字符串中的所有元素遍历完后
// 判断栈内是否还有元素
// 如果没有,证明所有括号全部匹配成功,返回true
// 如果仍然存在元素,返回false
if(stack.size()==0){
return true
}else{
return false
}
}
console.log( pipei("({})")); //true
console.log( pipei("({(})")); //false
</script>
2.判断当前字符串是不是回文数(栈)
<!-- 2.判断当前字符串是不是回文数(栈) -->
<!-- 回文数:就是12321,正着读和反着是一样的 -->
<script>
function huiwen(str){
// 将传入的字符串中的所有元素压入栈内
// 再将栈内的所有元素移除
// 判断传入的字符串与移除的字符串是否一致
var stack=new Stack()
var str1=""
for(var i=0;i<str.length;i++){
// 将字符串中的所有元素压入栈内
stack.push(str[i])
}
for(var i=0;i<str.length;i++){
// 将栈内所有元素移除
// 并将移除的元素连接成字符串str1
str1+=stack.pop()
}
console.log(str1)
// 判断str与str1是否一致
// 一致,返回true
// 不一致,返回false
if(str1==str){
return true
}else{
return false
}
}
console.log(huiwen("上海自来水来自海上"));
console.log( huiwen("abba"));
</script>
3.进制转换(十进制转任意进制)(栈)
<!--进制转换(十进制转任意进制)(栈) -->
<script>
function jinzhi(ele,scale){
var arr=["A","B","C","D","E","F"]
var stack=new Stack()
while(ele>0){
// 取余
let mn=ele%scale
if(mn>9){
// 当余数大于9,也就意味着,是十进制转换为16进制
// 16进制,超过9以后的数字,将以A-F字母表示
mn=arr[mn-10]
}
// 将除数除以被除数后的值向下取整
ele=Math.floor(ele/scale)
// 将余数压入栈内
stack.push(mn)
}
var str=""
while(!stack.isEmpty()){
// 将栈内的所有元素按顺序移除,连接成字符串
str+=stack.pop()
}
// 返回一个字符串
return str
}
console.log(jinzhi(100,8));
console.log(jinzhi(100,16));
console.log(jinzhi(100,2));
</script>
4.现实生活中栈的一个例子是佩兹糖果盒。想象一下你有要和佩兹糖果盒,里面塞满了红色、黄色和白色的糖果,但是你不喜欢黄色的糖果。使用栈(有可能用到多个栈),写一段程序,在不改变盒内其它糖果叠放顺序的基础上,将黄色糖果移出。
<!-- 佩兹糖果盒 -->
<script>
var sweetBox=new Stack();
sweetBox.push("red")
sweetBox.push("yellow")
sweetBox.push("red")
sweetBox.push("yellow")
sweetBox.push("white")
sweetBox.push("yellow")
sweetBox.push("white")
sweetBox.push("yellow")
sweetBox.push("white")
sweetBox.push("red")
// 创建一个新的栈
var Box=new Stack()
// 判断sweetBox栈内元素的数量
var num=sweetBox.size()
// 遍历sweetBox栈内的所有元素
for(var i=0;i<num;i++){
// console.log(sweetBox.peek())
// 如果sweetBox栈内的栈顶元素为yellow
// 那么将这个栈顶元素移除
if(sweetBox.peek()=="yellow"){
sweetBox.pop()
}else{
// 如果栈顶元素不为yellow
// 那么将这个栈顶元素移除,并压入到Box栈内
Box.push(sweetBox.pop())
}
}
console.log(Box);
// 判断Box栈内元素的数量
var num1=Box.size()
for(var i=0;i<num1;i++){
// 将Box栈内的所有元素移除,并压入sweetBox栈内
sweetBox.push(Box.pop())
}
console.log(sweetBox);
</script>