Python__数据结构与算法——表、栈、队列

目录

一、表

二、栈(后进先出)

三、队列(先进先出)


数据结构使用来描述一种或多种数据元素之间的特定关系,算法是程序设计中对数据操作的描述,数据结构和算法组成了程序。对于简单的任务,只要使用编程语言提供的基本数据类型就足够了;而对于较复杂的任务,就需要使用基本的数据类型来构造出更加复杂的数据结构。

表、堆栈和队列都是基本的线性数据结构。由于 Python 具有良好的数据结构,因此其列表可以当做表来使用,而且列表的某些特性与链表相似,因此,在 Python 中,表的实现非常简单。对于栈和队列,则可以自己编写脚本来构建。

一、表

表是最基本的数据结构,在 Python 中可以使用列表来创建表。而在 C 语言中,一般使用数组来创建表。使用数组所创建的表,在对表中元素进行插入和删除操作时开销较大。当插入一个元素时,要先将该元素后的所有元素,从最后一个元素开始,依次向后移动一个位置。完成元素移动后,再将元素插入到数组中。同样,要删除表中的元素时,首先删除元素,然后将位于该元素之后的元素从前向后,依次向前移动一个位置。

如果一个表中含有的元素较多,而要进行插入或删除的位置又比较靠近表的前端,则移动表中元素的操作将耗费大量的时间。为了减少插入或删除元素的线性开销,于是就出现了使用链表代替表。在 C 语言中,链表中不仅保存了数据,还保存了指向下一个元素的指针,如图 1 所示。当进行插入操作时,要先将位于插入元素前的元素的指针赋值给插入元素。完成赋值后再将插入元素的地址赋值给位于其前面的元素,如图 2 所示。当删除元素时,只需将要删除元素的指针赋值给其前面的元素即可,如图 3 所示。

使用链表,可以降低插入、删除元素的线性开销。然而,由于链表中不仅存储了数据,而且还保存了指向下一个元素的指针,因此使用链表将占用更大的存储空间。

而在 Python 中,列表本身就提供了插入和删除操作。因此,在 Python 中,列表也可以充当链表使用,而不用自己另外编写脚本来构建。

还有一种链表,称之为双向链表,如图 4 所示。双向链表中不仅保存了指向下一元素地址的指针,而且还保存了指向上一个元素地址的指针。相对于单向链表,双向链表需要占用更多的存储空间,但使用双向链表可以完成正序和倒序扫描链表。

二、栈(后进先出)

桟可以看做在同一位置上进行插入和删除的表,这个位置一般称为栈顶。栈的基本操作是进栈和出栈,栈可以看做一个容器,如图 5 所示,先入栈的数据保存在容器底部,后入栈的数据保存在容器顶部。出栈的时候,后入栈的数据先出,而先入栈的数据后出,因此栈有一个特性叫做后进先出(LIFO)。

在 Python 中,仍然可以使用列表来存储堆栈数据。通过创建一个堆栈类,实现对堆栈进行操作的方法。例如,进栈 PUSH 方法、出栈 POP 方法,编写检查栈是否为满栈,或者是否为空栈的方法,等等。

下面所示的 pystack.py 在 Python 中创建了一个简单的堆栈结构。

# -*- coding:UTF-8 -*-
# file: pystack.py


class PyStack:  # 堆栈类
    def __init__(self, size=20):
        self.stack = []  # 堆栈列表
        self.size = size  # 堆栈大小
        self.top = -1  # 堆顶位置

    def setSize(self, size):  # 设置堆栈大小
        self.size = size

    def push(self, element):  # 元素进栈
        if self.isFull():
            raise StackException('PyStackOverflow')  # 如果栈满则引发异常
        else:
            self.stack.append(element)
            self.top = self.top + 1

    def pop(self):  # 元素出栈
        if self.isEmpty():
            raise StackException('PyStackUnderflow')  # 如果栈为空则引发异常
        else:
            element = self.stack[-1]
            self.top = self.top - 1
            del self.stack[-1]
            return element

    def Top(self):  # 后面需要引用
        return self.top  # 获取栈顶位置

    def empty(self):  # 清空栈
        self.stack = []
        self.top = -1

    def isEmpty(self):  # 是否为空栈
        if self.top == -1:
            return True
        else:
            return False

    def isFull(self):  # 是否为满栈
        if self.top == self.size - 1:
            return True
        else:
            return False


class StackException(Exception):  # 自定义异常类
    def __init__(self, data):
        self.data = data

    def __str__(self):
        return self.data


if __name__ == '__main__':
    stack = PyStack()  # 创建栈
    for i in range(10):
        stack.push(i)  # 元素进栈
    print(stack.Top())  # 输出栈顶位置
    for i in range(10):
        print(stack.pop())  # 元素出栈
    stack.empty()  # 清空栈
    for i in range(21):
        stack.push(i)  # 此处将引发异常

运行 pystack.py 脚本后,输出内容如下(异常的位置不固定)。

三、队列(先进先出)

队列和栈的结构类似,如图 6 所示,不同的是,队列的出队操作是在队首元素进行的删除操作。因此对于队列而言,先入队的元素将先出队。因此队列的特性可以称之为先进先出(FIFO)。

和堆栈类似,在 Python 中同样可以使用列表来构建一个队列,并完成对队列的操作。下面所示的 pyqueue.py 脚本构建了一个简单的队列。

# -*- coding:UTF-8 -*-
# file: pyqueue.py


class PyQueue:  # 创建队列
    def __init__(self, size = 20):
        self.queue = []  # 队列
        self.size = size  # 队列大小
        self.end = -1  # 队尾

    def setSize(self, size):  # 设置队列大小
        self.size = size

    def In(self, element):  # 入队
        if self.end < self.size - 1:
            self.queue.append(element)
            self.end = self.end + 1
        else:
            raise QueueException('PyQueueFull')  # 如果队列满则引发异常

    def Out(self):  # 出队
        if self.end != -1:
            element = self.queue[0]
            self.queue = self.queue[1:]
            self.end = self.end - 1
            return element
        else:
            raise QueueException('PyQueueEmpty')  # 如果队列为空则引发异常

    def End(self):  # 输出队尾
        return self.end

    def empty(self):  # 清除队列
        self.queue = []
        self.end = -1


class QueueException(Exception):  # 自定义异常类
    def __init__(self, data):
        self.data = data

    def __str__(self):
        return self.data


if __name__ == '__main__':
    queue = PyQueue()
    for i in range(10):
        queue.In(i)  # 元素入队
    print(queue.End())
    for i in range(10):
        print(queue.Out())  # 元素出队
    for i in range(20):
        queue.In(i)  # 元素入队
    queue.empty()  # 清空队列
    for i in range(20):
        print(queue.Out())  # 此处将引发异常

运行 pyqueue.py 脚本后,输出内容如下(异常的位置不固定)。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值