重学数据结构之栈

一、前言简介

  数据结构课程是一门重要的计算机基础课程,而我本人在上学期间真是没学好这门课, 听课总是听得云里雾里的,写起代码来也不知道如何编写和运用这些数据结构,以致于后来考试也只能是低分飘过,所以现在就需要花时间重新学习一下数据结构了!

  为了能够更好地学习和掌握数据结构,除了学习和理解相应的概念,我还会找几个题目并用所学的数据结构来解决问题,相应的问题和代码也会一并记录在博客中。

二、栈的概念

1.基本概念

  栈(stack)又被称为堆栈,是一种保存数据元素的容器。栈作为一种数据结构,是一种只能在一端进行插入和删除操作的特殊线性表,允许进行插入和删除操作的一端叫做栈顶(top),另一端则叫做栈底(bottom),插入元素一般称为进栈(PUSH),删除元素一般称为出栈(POP)。

  栈按照后进先出的原则(LIFO, Last In First Out)存储数据,后存入的元素会先被取出来使用。存入栈中的元素相互之间并没有任何具体的关系,只有存入的时间先后顺序,而没有元素的前后顺序或者元素的位置等概念。

2.抽象数据类型

  栈的基本操作一个封闭的数据集合,在一个栈里需要实现将元素压入栈中即进栈、从栈中弹出元素即出栈、返回最后一个插入栈中的元素、获取栈中元素的数量等方法,下面就是一个栈的抽象数据类型描述:

ADT Stack:

  Stack(self)  # 创建一个空栈

  empty(self)  # 判断栈是否为空

  push(self, x)  # 将元素压入栈中

  pop(self)  # 从栈中弹出元素

  peek(self)  # 返回最后一个插入的元素

  size(sellf)  # 获取栈中元素的数量

3.用 Python 实现

  在 Python 中没有栈这种数据结构,但我们可以借助 list 来实现,用 list 来存放数据,并实现一个栈所需要的各种方法,具体代码如下:

 1 # 自定义栈
 2 class MyStack:
 3     def __init__(self):
 4         self.data = []
 5 
 6     def push(self, x):
 7         """
 8         将数据压入栈中
 9         :param x: 需要插入的元素
10         :return: 
11         """
12         self.data.append(x)
13 
14     def pop(self):
15         """
16         从栈中弹出元素
17         :return: 弹出的元素
18         """
19         if not self.empty():
20             ret, self.data = self.data[-1], self.data[:-1]
21             return ret
22         return None
23 
24     def empty(self):
25         """
26         判断栈是否为空
27         :return: 栈空--True,非空--False
28         """
29         return len(self.data) == 0
30 
31     def size(self):
32         """
33         获取栈中元素的数量
34         :return: 
35         """
36         return len(self.data)
37 
38     def peek(self):
39         """
40         返回最后一个插入的元素
41         :return: 最后一个插入的元素
42         """
43         if not self.empty():
44             return self.data[-1]
45         return None

三、栈的应用

1.进制转换

1)问题描述

  输入一个任意的十进制正整数,将其转化成相应的二进制、八进制和十六进制的数。

2)解决思路

  这里首先需要介绍一个公式:

N = (N div d) * d + N mod d

  其中 div 表示整除,mod 表示求余。例如当输入的正整数 N 为777,输出的进制是八进制时,计算过程如下:

N      N div 8    N mod 8

777   97       1

97     12       1

12    1     4

1      0     1  

  在进行进制转换的时候,我们就可以将每次求余的结果保存在栈中,最后将栈中的数依次取出,就是转换后的结果了,例如十进制的777转换成八进制就是1411。

3)代码实现

  如何用代码来解决这个问题?一个思路就是将每次求余的结果保存在栈中,而整除的结果则用来进行下一步的计算,直到这个整除的结果为0,表明计算结束,再出栈中依次取出元素,得到的结果就是转换成相应进制后的数。具体代码如下:

 1 def solution(n: int, scale: int):
 2     """
 3     进制转换
 4     :param n: 正整数
 5     :param scale: 进制
 6     :return:
 7     """
 8     stack = MyStack()
 9     # 循环计算
10     while n // scale >= 0 and n > 0:
11         stack.push(n % scale)
12         n = n // scale
13     # 输出
14     while not stack.empty():
15         print(stack.pop(), end="")

2.括号匹配

1)问题描述

  输入一个字符串,里面可能有“()”、“[]”和“{}”三种括号,编写程序检查该字符串中的括号是否成对出现。

2)解决思路

  遍历这个字符串,用栈来存放每次遍历的元素,如果遍历的元素和栈顶的括号是配对的,则进行出栈操作将栈顶元素弹出,反之若不配对,则进行入栈操作将该元素插入到栈中。等遍历结束后,若栈为空,则表明该字符串中的括号都是成对出现的,若栈不为空,则表明有括号不匹配。

3)代码实现

 1 def solution(input_string: str):
 2     """
 3     判断输入的字符中的括号是否成对出现
 4     :param input_string: 输入字符串
 5     :return:
 6     """
 7     def match(c1: str, c2: str):
 8         """
 9         判断两个括号是否匹配
10         :param c1: 
11         :param c2: 
12         :return: 
13         """
14         if c1 == "(" and c2 == ")":
15             return True
16         elif c1 == "[" and c2 == "]":
17             return True
18         elif c1 == "{" and c2 == "}":
19             return True
20         else:
21             return False
22 
23     stack = MyStack()
24     for i in range(len(input_string)):
25         if stack.empty():
26             # 栈空直接入栈
27             stack.push(input_string[i])
28         else:
29             # 栈非空时进行比较
30             if match(stack.peek(), input_string[i]):
31                 stack.pop()
32             else:
33                 stack.push(input_string[i])
34     print("匹配!") if stack.empty() else print("不匹配!")
原文地址:https://www.cnblogs.com/TM0831/p/12831061.html