在这一节中,我会记录学习二种特殊形式的线性表,其中一种只能在一端进行操作,也就是只能在队尾进行插入删除操作的栈,还有一种是在一段进行插入(队伍尾巴)在另一端进行删除操作(队伍的前头)的队列。二者均是线性表。
栈
栈是只能在表尾进行插入删除操作,并且表尾被称为了栈顶,另一端被称为了栈底,不含任何元素的栈被称为空栈,栈的结构属于后进先出(LIFO)结构,所以被称为了后进先出表。
栈的结构是一个线性表,只不过是一个特殊的线性表,只是限制了插入删除的位置,即栈底是固定的,栈顶是变化的。
1,栈的顺序存储结构(顺序栈)
顺序存储结构中,一般以数组来作为存储的容器,bottom一般为数组的下标0那个位置,top为-1时表明空栈,top=0时表示有一个元素,top应小于stacksize的大小。
栈的顺序存储结构与一般的线性表的顺序存储没有很大的区别,有的区别在于操作只能在数组的尾端进行操作,也就是只能在栈顶进行操作,需要维持一个记录栈顶位置的变量。因为栈操作只涉及到的是栈顶元素的操作,所以,在插入删除操作时不涉及到大量元素的搬移的工作,时间复杂度为O(1)。
栈中可以通过共享空间来达到最大限度的利用事先开辟好的存储空间的目的。什么是共享空间?就是在一个空间比较大的数组中维护二个栈的操作,一个栈的栈底在数组下标为0的地方,一个栈的栈底在数组下标为n-1的地方,二者的栈顶元素来朝着中间方向来进行延伸。使用的前提在于,二者的数据类型是相同的,否则会使得问题变得复杂。
2,栈的链式存储结构(链栈)
栈的链式存储结构中头指针的存在,而栈顶变量也是必不可少的,可以使二者合二为一,并且栈顶在头部了,单链表中的头结点也就失去了意义,不需要头结点。
栈的链式存储结构中的进栈,出栈操作需要分配内存以及删除内存的操作,并且对于栈顶的指针进行操作即可。
栈的应用
1,递归程序,主要考虑的结束条件,不能无穷无尽的运行到底。
兔子的繁殖问题,主要是应用的斐波那契数列。利用递归以及迭代可以实现斐波那契数列。
对于迭代而言,主要利用的循环的结构,而对于递归则利用的是选择结构。
对于递归的操作,由栈的结构来实现。
2,四则运算表达式求值
四则运算利用栈的结构来实现,称为逆波兰表示,也可以称为后缀表达式,在后缀表达式中,遇到数字即压入栈,遇到字符则出栈,出栈一般由二维操作符,但如果栈已空,说明为一维操作符,这样就可以解决四则运算的苦恼。
我们一般的表示是中缀表达式,需要把中缀表达式转换为后缀表达式,具体转换的步骤如下:
从人的思维角度来说,比较容易可以实现这个步骤,先把数字写好,然后如果有先运算的,就在后面加个字符。
从规则的角度来说,对于数字则输出,对于符号则判断与栈顶元素的优先级判断是否出栈,一直到所有的表达式写完。以9+(3-1)*3+10/2为例。
1,初始化一个空栈。
2,对于字符串从左到右来进行处理,然后数字9则输出,对于+符号入栈,对于(则入栈,对于数字3则输出,对于符号-入栈,对于数字1输出,对于)符号需要将(之前的出栈,包括(符号,对于入栈,的优先级高于后面的数字3的+符号,所以输出数字3之后则+不能入栈,将*出栈,,+的优先级与栈顶的+优先级相同,所以+不入栈,输出+符号,输出数字10,然后对于/的优先级高于+则入栈,输出数字2,因为没有符号,则所有的符号均出栈。
顺序栈的实现代码(python)
# -*- coding: utf-8 -*-
class Stack_sq():
def __init__(self):
self._list = []
self._top = -1
def is_empty(self):
if self._top == -1:
print "the stack is empty"
else:
print "the stack has data"
def insert_one(self, data):
self._list.append(data)
self._top += 1
def delete_one(self):
if self._top <= -1:
print "can not delete data"
self._list.pop()
self._top -= 1
def read_stack(self):
for i in self._list:
print i,
print "is all data"
stack = Stack_sq()
stack.is_empty()
stack.insert_one(1)
stack.insert_one(2)
stack.insert_one(3)
stack.read_stack()
stack.delete_one()
stack.read_stack()
利用顺序栈来实现中缀表达式转后缀表达式,实现四则运算
# -*- coding: utf-8 -*-
class Stack_sq():
def __init__(self):
self._list = []
self._top = -1
def is_empty(self):
if self._top == -1:
return 1
else:
return 0
def get_length(self):
length = self._top + 1
return length
def insert_one(self, data):
self._list.append(data)
self._top += 1
def delete_one(self):
if self._top <= -1:
print "can not delete data"
self._list.pop()
self._top -= 1
def read_stack(self):
for i in self._list:
print i,
print "is all data"
def last_data(self):
return self._list[self._top]
def symbol2rank(str1):
dict1 = {'+': 6, '-': 5, '*': 4, '/': 3, '(': 2, ')': 1}
return dict1[str1]
def rank2symbol(str2):
dict2 = {'6': '+', '5': '-', '4': '*', '3': '/', '2': '(', '1': ')'}
str2 = str(str2)
return dict2[str2]
def operation(s1, s2, s):
if s == '+':
sum = s2 + s1
elif s == '-':
sum = s2 - s1
elif s == '*':
sum = s2 * s1
elif s == '/':
sum = s2 / s1
else:
print "the expression is wrong"
return sum
def middle2behind(string):
string1 = ''
stack = Stack_sq()
for s in string:
if s in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']:
string1 = string1 + s
continue
s = symbol2rank(s)
while True:
if s >= 2:
if stack.is_empty() == 1:
stack.insert_one(s)
break
else:
s_l = stack.last_data()
if s < s_l or s_l == 2:
stack.insert_one(s)
break
elif s - s_l > 1:
string1 = string1 + rank2symbol(s_l)
stack.delete_one()
else:
string1 = string1 + rank2symbol(s)
break
if s == 1:
s_l = stack.last_data()
if s_l == 2:
stack.delete_one()
break
else:
string1 = string1 + rank2symbol(s_l)
stack.delete_one()
if stack.is_empty() == 1:
break
while True:
if stack.is_empty() == 1:
break
s_l = stack.last_data()
string1 = string1 + rank2symbol(s_l)
stack.delete_one()
return string1
def four_operation(string):
stack = Stack_sq()
sum = 0
for s in string:
if s in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']:
stack.insert_one(int(s))
else:
length = stack.get_length()
if length < 2:
print "the expression is wrong!"
return False
s_l = stack.last_data()
stack.delete_one()
s_ll = stack.last_data()
stack.delete_one()
sum = operation(s_l, s_ll, s)
stack.insert_one(sum)
sum_all = stack.last_data()
return sum_all
r = "8+3*5+6*(6+8*3)/2"
r1 = middle2behind(r)
sum = four_operation(r1)
print sum
# 8+3*5+6*(6+8*3)/2的中缀表达式向后缀表达式的转换,并实现四则运算
python来实现链栈,并且实现顺序栈的上述的功能
# -*- coding: utf-8 -*-
class Node():
def __init__(self, data):
self._data = data
self._next = None
class Stack_link():
def __init__(self):
self._head = Node(data=-1)
self._top = self._head
def is_empty(self):
if self._head._data == -1:
return 1
else:
return 0
def insert_one(self, data):
a = Node(data)
p = self._head
while True:
if p == self._top:
p._next = a
self._top = a
self._head._data += 1
break
else:
p = p._next
def delete_one(self):
p = self._head
while True:
if self._head == -1:
print "stack is empty"
break
else:
if p._next == self._top:
p._next = None
self._top = p
self._head._data -= 1
break
else:
p = p._next
def last_data(self):
last_data = self._top._data
return last_data
def get_length(self):
length = self._head._data + 1
return length
def symbol2rank(str1):
dict1 = {'+': 6, '-': 5, '*': 4, '/': 3, '(': 2, ')': 1}
return dict1[str1]
def rank2symbol(str2):
dict2 = {'6': '+', '5': '-', '4': '*', '3': '/', '2': '(', '1': ')'}
str2 = str(str2)
return dict2[str2]
def operation(s1, s2, s):
if s == '+':
sum = s2 + s1
elif s == '-':
sum = s2 - s1
elif s == '*':
sum = s2 * s1
elif s == '/':
sum = s2 / s1
else:
print "the expression is wrong"
return sum
def middle2behind(string):
string1 = ''
# stack = Stack_sq()
stack = Stack_link()
for s in string:
if s in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']:
string1 = string1 + s
continue
s = symbol2rank(s)
while True:
if s >= 2:
if stack.is_empty() == 1:
stack.insert_one(s)
break
else:
s_l = stack.last_data()
if s < s_l or s_l == 2:
stack.insert_one(data=s)
break
elif s - s_l > 1:
string1 = string1 + rank2symbol(s_l)
stack.delete_one()
else:
string1 = string1 + rank2symbol(s)
break
if s == 1:
s_l = stack.last_data()
if s_l == 2:
stack.delete_one()
break
else:
string1 = string1 + rank2symbol(s_l)
stack.delete_one()
if stack.is_empty() == 1:
break
while True:
if stack.is_empty() == 1:
break
s_l = stack.last_data()
string1 = string1 + rank2symbol(s_l)
stack.delete_one()
return string1
def four_operation(string):
stack = Stack_sq()
sum = 0
for s in string:
if s in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']:
stack.insert_one(int(s))
else:
length = stack.get_length()
if length < 2:
print "the expression is wrong!"
return False
s_l = stack.last_data()
stack.delete_one()
s_ll = stack.last_data()
stack.delete_one()
sum = operation(s_l, s_ll, s)
stack.insert_one(sum)
sum_all = stack.last_data()
return sum_all
# 实现四则运算8+3*5+6*(7+8)/2的中缀表达式向后缀表达式的转换
r = "8+3*5+6*(6+8*3)/2"
r1 = middle2behind(r)
sum = four_operation(r1)
print sum
# 测试链栈是否正常工作
# stack = Stack_link()
# stack.insert_one(3)
# stack.insert_one(3)
# stack.insert_one(4)
# a = stack.last_data()
# stack.delete_one()
# print a