数据结构与算法----栈和队列(Stack & Queue)(三)

简介: 数据结构与算法----栈和队列(Stack & Queue)

队列


队列是一种运算受限的线性表,元素的添加操作在表的一端进行,而另一端的删除在另一端进行,允许插入的一端称为队尾,允许删除的一端称为队头。


假设队列 q = [x1,x2,x3,,,,,xn] x1是队头,x2是队尾,队列中的数据的入队序列是x1,x2,x3,,,xn,队列也只能按这个顺序进行出队,队列的特点是先进入队列的先出来,后进队的必须等前面的数据出队完成以后才可以出队,所以队列也成为先进先出表(First in First out)


84b385e584a447edb91104a048d67b8c.png

队列的操作


队列由由多种实现方式,这里就选三个比较有代表性的实现方式讲解’基础队列,循环队列链队列,代码放在后面,在讲解的途中就在分别展示了


说明:循环队列也是用数组来实现的,只不过通过,一些算法实现了数组空间的复用,而且不用频繁的移动数组中的元素。


初始化队列


22da93f192624398b21f91a5c26e1735.png


入队


e4cd8d39755c443f965f7faa13e5b7d8.png


出队


原队列


ae761914d70e403f81cf5dcfd971db49.png



出队


顺序队列:就是将第一个元素返回出去,其余的元素向前移动一单位

循环队列:就是将队头的指针向后移动一个单位,里面的元素变为无效数据,等待覆盖

链队列:就是链表的删除,将头部指针front,指向队头的的指针移动到,指向队头后一个元素


a11cc399eaf1437eba0f29f864258233.png


遍历队列


顺序队列:将数组中的中的数据从开头一直遍历到最后

循环队列:创建一个临时的指针tmp该指针的位置和front指针一样,根据这个临时指针tmp的移动一次访问元素,直至临时指针和rear指针指向同一个位置的时候停止。

链队列:从头部直接遍历,循环调用next方法,直至到next==null的时候停止遍历


清空队列


清空队列就是将队列中的所有元素清空,让队列回归最初的状态


顺序队列:清空列表中的元素,并将rear指针回归到最初的位置

循环队列:清空列表中的元素,并将指针回归到最初的位置

链队列:将头部指针指向为null


队列的存储结构


顺序存储


基础队列的队头始终在数组的头部,每删除一个元素,整个队列就会向前移动一个单位,保证队列头始终在数组的第一个元素。这样我门就可以发现每执行删除操作(出队),队列就要移动一次,这样会造成系统的额外开销。


class BaseQueue:
    def __init__(self):
        self.data = []
        self.front = 0
        self.rear = 0  # 记录队尾
        self.maxlength = 10  # 设置队列的最大长度
    def enqueue(self, arg):
        """入队"""
        if self.rear >= self.maxlength:
            print("队列已满")
            return
        self.rear += 1
        self.data.append(arg)
    def dequeue(self):
        """出队"""
        if self.rear == 0:
            print("队列已空")
            return
        self.rear -= 1
        return self.data.pop(0)
    def gethead(self):
        """获取队头"""
        if self.rear == 0:
            print("队列已空")
            return
        return self.data[0]
    def size(self):
        """返回队列的长度"""
        return self.rear
    def isEmpty(self):
        """判断队列是否为空"""
        return self.rear == 0
    def next(self):
        """遍历并输出"""
        p = self.rear
        for i in range(0, p):
            print(self.data[i])
    def clear(self):
        """清空队列"""
        self.data.clear()
        self.rear = 0


循环队列


循环队列,本质上还是使用数组进行实现,只是在逻辑上将首部、尾部连接起来,形成一个环状的循环队列,循环队列存储的元素个数比数组的长度少一,用来区分队满还是对待队空。


class LoopQueue:
    def __init__(self):
        self.maxsize = 10
        self.data = [0 for i in range(self.maxsize)]
        self.front = 0
        self.rear = 0
    def enqueue(self, arg):
        """入队"""
        if (self.rear + 1) % self.maxsize == self.front:
            print("队列已满,无法入队")
            return
        self.data[self.rear] = arg
        self.rear = (self.rear + 1) % self.maxsize
    def dequeue(self):
        """出队"""
        if self.isEmpty():
            print("队列已空,无法读取元素")
            return
        tmp = self.data[self.front]
        self.front = self.front + 1 % self.maxsize
        return tmp
    def gethead(self):
        """获取队头"""
        if self.isEmpty():
            print("队列已空,无法读取元素")
            return
        tmp = self.data[self.front]
        return tmp
    def size(self):
        """返回队列的长度"""
        if self.front <= self.rear:
            return self.rear - self.front
        else:
            return self.maxsize - (self.front - self.rear)
    def isEmpty(self):
        """判断队列是否为空"""
        return self.front == self.rear
    def next(self):
        """遍历并输出"""
        tmp = self.front
        while tmp < self.rear:
            print(self.data[tmp])
            tmp += 1
    def clear(self):
        """清空队列"""
        self.front = 0
        self.rear = 0


链式存储


队列的链存储结构称为链队列,它是限制在表头删除和表尾插入的单链表,由于需要在表尾进行插入操作,所以为操作方便除头指针外有必要再增加一个指向尾节点的指针

这个部分用到的链表的知识比较多,如果有不理解的可以去补补链表的知识


class Node(object):
    """节点类"""
    def __init__(self, data=None):
        self.data = data
        self.next = None
class LinkQueue:
    def __init__(self):
        self.length = 0
        self.front = None  # 头节点
        self.rear = None  # 尾节点
    def enqueue(self, arg):
        """入队"""
        node = Node(data=arg)
        if self.isEmpty():
            self.front = self.rear = node
            self.length += 1
        else:
            self.rear.next = node
            self.rear = node
            self.length += 1
    def dequeue(self):
        """出队"""
        if self.isEmpty():
            print("队列为空")
        else:
            resulst = self.front.data
            self.front = self.front.next
            self.length-=1
            return resulst
    def gethead(self):
        """获取队头"""
        if not self.isEmpty():
            return self.front.data
        else:
            print("队列为空")
    def size(self):
        """返回队列的长度"""
        return self.length
    def isEmpty(self):
        """判断队列是否为空"""
        if self.length == 0:
            return True
        else:
            return False
    def next(self):
        """遍历并输出"""
        tmp = self.front
        while tmp:
            print(tmp.data)
            tmp = tmp.next
    def clear(self):
        """清空队列"""
        self.front = None
        self.rear = None


队列实战题目


这两个题目我们再刚开始讲解的时候已经写过了


78ae94c602c34bc2b7a1b864404304d6.png


总结


栈是限定再表尾进行插入或删除的线性表,又称后进先出的线性表,栈有两种存储表示,顺序栈,链式栈,链的主要操作是进栈和出栈,对于出栈和进栈操作判断栈满还是栈空

队列是一种先进先出的线性表,它只允许在表的一端进行插入,而在另一端进行删除,队列也有两种存储结构,顺序存储,链式存储,队列的主要操作是进队和出队,对于顺序表需要注意队满和队空的情况

栈和队列是在程序设计中被广泛使用的两种数据结构,其具体的应用场景都是与其展示方法和运算规则相互关联的。


相关文章
|
2月前
|
算法 C语言
【数据结构与算法 经典例题】使用栈实现队列(图文详解)
【数据结构与算法 经典例题】使用栈实现队列(图文详解)
|
4天前
|
缓存 算法 Java
刷算法,你应该知道的队列经典应用
文章介绍了队列的基本特性和经典应用,包括如何用队列实现栈、使用优先级队列解决Top K问题,并通过LeetCode题目示例展示了队列在算法实现中的应用。
刷算法,你应该知道的队列经典应用
|
4天前
|
算法
【数据结构与算法】优先级队列
【数据结构与算法】优先级队列
6 0
|
4天前
|
存储 算法
【数据结构与算法】队列(顺序存储)
【数据结构与算法】队列(顺序存储)
5 0
|
2月前
|
算法 C语言
【数据结构与算法 经典例题】使用队列实现栈(图文详解)
【数据结构与算法 经典例题】使用队列实现栈(图文详解)
|
1月前
|
算法
数据结构与算法:栈与队列
数据结构与算法:栈与队列
|
2月前
|
算法 程序员 数据处理
【数据结构与算法】使用单链表实现队列:原理、步骤与应用
【数据结构与算法】使用单链表实现队列:原理、步骤与应用
|
6天前
|
算法 C语言 C++
【practise】栈的压入和弹出序列
【practise】栈的压入和弹出序列
|
4天前
栈的几个经典应用,真的绝了
文章总结了栈的几个经典应用场景,包括使用两个栈来实现队列的功能以及利用栈进行对称匹配,并通过LeetCode上的题目示例展示了栈在实际问题中的应用。
栈的几个经典应用,真的绝了
|
1天前
|
负载均衡 网络协议 安全
DKDP用户态协议栈-kni
DKDP用户态协议栈-kni