zoukankan      html  css  js  c++  java
  • 重学数据结构之栈

    一、前言简介

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

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

    二、栈的概念

    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("不匹配!")
  • 相关阅读:
    迭代器和生成器
    案例:复制大文件
    案例:使用seek倒查获取日志文件的最后一行
    Leetcode165. Compare Version Numbers比较版本号
    Leetcode137. Single Number II只出现一次的数字2
    Leetcode129. Sum Root to Leaf Numbers求根到叶子节点数字之和
    Leetcode116. Populating Next Right Pointers in Each Node填充同一层的兄弟节点
    Leetcode114. Flatten Binary Tree to Linked List二叉树展开为链表
    Leetcode113. Path Sum II路径总和2
    C++stl中vector的几种常用构造方法
  • 原文地址:https://www.cnblogs.com/TM0831/p/12831061.html
Copyright © 2011-2022 走看看