栈的最鲜明的特征就是
先进后出
判断一个按从小到大输入栈的序列是否为栈的输出
规则为,在数 n 的后面(n > 2), 后1 ,2,3 ,n-1的排列得是降序
数的排列得是降序
例如进栈的顺序是1234
那么 4 2 3 1
是不可能的 因为 在 4 的后面 1,2,3 这三个数只能 排成 3 2 1
还如 3 1 2 4 ,也是不对的 ,在3 的后面 1 2 得按降序的来 按 2 1的 顺序来
如 3 2 1 4,3 2 4 1,3 4 2 1 就是可以的
这是 栈的基本性质和输出规则
接着来分析,对所有情况的输出
按照 升序的方式输入以 1 2 3 为例
((输入序列),(栈中序列),(出栈序列))
1入栈 ((2,3),(1),())
这时面临 两种情况
①1出栈 ((2,3),(),(1))
②2入栈((3),(1,2),())
这时在①上只有入栈的一种情况
而在②上是有两种情况的
一是 3 入栈
一是 2 出栈
用图来演示全过程
(有点丑)
下面是算法得出的结果
就像这样 穷举法
这是一种比较直接的比较笨重的求法
还知道一种更笨重的方法,就是输出n 个数的所有排列
然后根据栈的输出规则 来删除不合法的情况
算法思维来自
python的函数重载(一)----参数个数
给定入栈顺序…
还有一种算法是
回溯法
比较难
贴一个python算法
#coding=gbk
def stackallput(q,s,qs):# q 为输入队列储存输入序列 S是栈 qs是输出队列用来储存栈的输出
#用穷举法递归出所有可能输出情况
if(qs.lenth() == lens): #当输出队列满 说明一种情况产生完毕 输出
for i in range(lens):
print(qs.out(),end = ' ')
print()
if q.lenth() == 0:#判断输入队列是否为空 为空 进行出栈
if s.lenth() != 0:
qs.insert(s.pop())
stackallput(q,s,qs)#1
else: #输入队列非空
if s.lenth() == 0: #判断栈是否为空 为空入栈
s.push(q.out())
stackallput(q,s,qs)#2
else: #非空
qe = q.copy()
se = s.copy()
qse = qs.copy()
se.push(qe.out()) #情况一 入栈操作
stackallput(qe,se,qse)#3
qs.insert(s.pop()) #情况二 出栈操作
stackallput(q,s,qs)#4
class Stack:#列表 模拟栈
def __init__(self): #初始化栈 列表
self.lens = []
def pop(self): #以列表 模拟出栈
return self.lens.pop()
def push(self,value): #模拟入栈
self.lens.append(value)
def lenth(self):#测量 栈长 作用 判断栈是否为空
return len(self.lens)
def copy(self): #复制 栈 作用 用复制的栈代替原栈,保留原栈的储存数据
s = Stack()
s.lens = self.lens[:]
return s
class Queue:#列表 模拟队列
def __init__(self,lens = 0):#初始化 两种构造情况 一是长度参数 另一个是不带长度参数
self.lens = [None]*lens
for i in range(lens): #按序 创建队列储存数据
self.lens[i] = i+1
def out(self):#模拟出队
return self.lens.pop(0)
def lenth(self):#测 队列的长度 作用判断 队列是否为空 队列是否为满
return len(self.lens)
def insert(self,value):# 模拟入队
self.lens.append(value)
def copy(self):#复制队列 使用复制队列参与递归 保留原队列数据
q = Queue(self.lenth())
q.lens = self.lens[:]
return q
lens = int(input("输入一个栈的长度:"))
q1 = Queue(lens)#输入队列
s1 = Stack()#栈
qs = Queue()#输出队列
stackallput(q1,s1,qs) #穷举递归求栈的所有输出