【8】数据结构的栈与队列练习篇章

目录标题

线性表的两种存储结构各有哪些优缺点?

  • 顺序存储结构(数组):

    • 优点:
      • 存储空间利用率高。
      • 可以通过索引快速访问任意位置的元素。
      • 插入和删除操作(在非尾部)可能需要移动大量元素。
    • 缺点:
      • 需要预先分配固定大小的存储空间。
      • 插入和删除操作可能效率较低,尤其是当元素不在数组尾部时。
  • 链式存储结构(链表):

    • 优点:
      • 动态分配存储空间,可以根据需要增加或减少。
      • 插入和删除操作相对简单,只需修改指针。
    • 缺点:
      • 每个节点需要额外的存储空间来存放指针。
      • 访问元素需要从头节点开始遍历,不能直接访问。

使用栈结构实现括号匹配问题

  • 核心思路:
    • 主要通过不断将左括号入栈,若匹配,则,对应左括号出栈,若不匹配,则失败,最终栈空表示,全部匹配成功。
    • 每个右圆括号与最近遇到的尚未匹配的左圆括号匹配;
    • 每个右方括号与最近遇到的尚未匹配的左方括号匹配;
    • 每个右花括号与最近遇到的尚未匹配的左花括号匹配;
  • 示意图
  • 代码实现
python 复制代码
class Node:
    """
    定义链栈结点类型
    """
    def __init__(self, data):
        # 结点的数据域
        self.data = data
        # 结点的指针域
        self.next = None
class LinkedStack:
    """
    链栈的定义
    """
    def __init__(self):
        """
        初始化
        """
        # 栈的头结点指针
        self.top = Node(None)

    def isEmpty(self):
        """
        判断为空
        :return: true or false
        """
        return self.top.next is None

    def push(self, data):
        """
        入栈
        :param data: 入栈元素
        :return:
        """
        newNode = Node(data)
        # 新结点的next指向栈顶指针
        newNode.next = self.top.next
        # 将栈顶指针指向新结点
        self.top.next = newNode

    def pop(self):
        """
        出栈
        :return: 出栈元素值
        """
        if self.isEmpty():
            raise IndexError('栈为空')
        # 存储栈顶元素
        node = self.top.next
        # 指向栈顶的下一个元素
        self.top.next = self.top.next.next
        # 返回栈顶元素
        return node

    def peak(self):
        """
        获取栈顶
        :return: 返回栈顶元素
        """
        if self.isEmpty():
            raise IndexError('栈为空')
        else:
            return self.top.next.data

    # 括号匹配问题
    def match(self, char1, char2):
        """
        判断是否匹配
        :param char1: 需要匹配第一个字符
        :param char2: 需要匹配第二个字符
        :return:
        """
        if char1 == '(' and char2 == ')':
            return True
        elif char1 == '[' and char2 == ']':
            return True
        elif char1 == '{' and char2 == '}':
            return True
        else:
            return False

    def brackedMatch(self, str):
        """
        括号匹配
        :param str: 表达式
        :return:
            括号匹配成功,返回true
            括号匹配失败,返回false
        """
        stack = LinkedStack()
        arr = list(str)
        for i in range(len(arr)):
            # 如果字符为'('、'['、'{',将其入栈
            if arr[i] == '(' or arr[i] == '[' or arr[i] == '{':
                stack.push(arr[i])
            elif arr[i] == ')' or arr[i] == ']' or arr[i] == '}':
                # 判断是否空栈
                if stack.isEmpty():
                    print(f'右括号{arr[i]}多余')
                    return False
                else:
                    char = stack.peak()
                    if stack.match(char, arr[i]):
                        stack.pop()
                    else:
                        print(f'对应的左括号{char}与右括号{arr[i]}不匹配')
                        return False
        if stack.isEmpty():
            print('当前字符串的括号匹配')
            return True
        else:
            print(f'左括号{stack.peak().data}多余')
            return False
  
 if __name__ == '__main__':

    # print('PyCharm')
    # 13.括号匹配问题
    linkedStack = LinkedStack()
    expStr = '({[((1)+2)+(3+4)]+(5+(6))})'
    linkedStack.brackedMatch(expStr)

使用队列实现杨辉三角

  • 核心思想

    • 将每一行的数据元素入队,
    • 下一行从第二个元素开始,由上一行的出队元素和队首两个元素相加而得;
    • 循环往复,获得杨辉三角
  • 杨辉三角特点

    • 每一行的第一个数字与最后一个数字均为1;
    • 其他位置上的数字是上一行中与之相邻的两个数字之和。
  • 示意图

  • 代码实现

python 复制代码
class Node:
    """
    定义链式队列结点
    """
    def __init__(self, data):
        # 数据域
        self.data = data
        # 指针域
        self.next = None

class LinkedQueue:
    """
    链式队列定义
    """
    def __init__(self):
        """
        链式队列初始化
        """
        # 队首结点指向None
        self.front = Node(None)
        # 队尾指针指向队首
        self.rear = self.front

    def isEmpty(self):
        """
        判断是否为空
        :return: true or false
        """
        return self.front == self.rear

    def enter(self, data):
        """
        入队
        :param data: 入队元素值
        """
        # 创建新结点
        newNode = Node(data)
        self.rear.next = newNode
        self.rear = newNode

    def delete(self):
        """
        出队
        :return: 出队值
        """
        # 队列为空
        if self.isEmpty():
            raise IndexError('队列为空')
        else:
            node = self.front.next
            # 队首结点的next指向队首结点的后继结点
            self.front.next = node.next
            # 返回出队结点
            return node

    def peak(self):
        """
        获取队首元素
        :return: 队首元素
        """
        # 队列为空
        if self.isEmpty():
            raise IndexError('队列为空')
        else:
            # 返回队首元素
            return self.front.next.data

    def pascalTriangle(self):
        """
        杨辉三角的应用
        :return:
        """
        # 第1行数字入队
        self.enter(1)
        line = eval(input('请输入行数:'))
        # 产生第n行数字,并入队,同时打印出
        for n in range(2, line + 2):
            # 打印空格
            for i in range(line - n + 1):
                print('', end='')
            # 步骤1:第n行第一个数字入队
            self.enter(1)
            # 步骤2:输出第n-1行数字,同时产生第n行中间的第n-2个数字并将其入队
            for i in range(1, n-1):
                # 步骤2-1:打印第n-1行数字
                temp = self.delete().data
                print(temp, end=" ")
                # 步骤2-2:利用队列中第n-1行数字产生第n行数字
                num = self.peak()
                num = num + temp
                self.enter(num)
            # 步骤3:打印第n-1行的最后一个数字
            num = self.delete().data
            print(num, end=' ')
            # 步骤4:第n行的最后1个数字入队
            self.enter(1)
            print()
 
if __name__ == '__main__':

    print('PyCharm')
    # 14.杨辉三角
    linkedQueue = LinkedQueue()
    linkedQueue.pascalTriangle()

结合栈和队列实现回文判断

  • 核心思想
    • 通过将字符依次插入栈和队列,再依次对栈顶元素和队首元素的字符进行比较,实现回文判断。
  • 代码实现
python 复制代码
if __name__ == '__main__':

    print('PyCharm')
    # 15. 回文
    chars = 'abcdefggfedcba'
    linkedStack = LinkedStack()
    linkedQueue = LinkedQueue()
    is_palindrome = True

    for char in chars:
        linkedStack.push(char)
        linkedQueue.enter(char)

    while linkedStack.isEmpty() is False:
        print('进入循环')
        if linkedStack.pop().data != linkedQueue.delete().data:
            is_palindrome = False
            break

    result = '字符是回文' if is_palindrome else '字符不是回文'
    print(f"字符串 '{chars}'\t{result}")
相关推荐
李慕瑶1 分钟前
Scala语言的移动UI设计
开发语言·后端·golang
梦回阑珊2 分钟前
《QT从基础到进阶·七十四》Qt+C++开发一个python编译器,能够编写,运行python程序改进版
c++·python·qt
ツ箫声断丶何处莫凭栏9024 分钟前
C++中的多态和模板
c语言·开发语言·c++
前端开发张小七5 分钟前
13.Python Socket服务端开发指南
前端·python
前端开发张小七7 分钟前
14.Python Socket客户端开发指南
前端·python
齐尹秦7 分钟前
CSS Id 和 Class 选择器学习笔记
css·笔记·学习
Y1nhl16 分钟前
搜广推校招面经六十六
pytorch·python·深度学习·机器学习·广告算法·推荐算法·搜索算法
kfepiza17 分钟前
`docker run --restart no,always,on-failure,unless-stopped`笔记250406
笔记·docker·容器
审计侠28 分钟前
Go语言-初学者日记(八):构建、部署与 Docker 化
开发语言·后端·golang
kovlistudio29 分钟前
红宝书第二十九讲:详解编辑器和IDE:VS Code与WebStorm
开发语言·前端·javascript·ide·学习·编辑器·webstorm