zoukankan      html  css  js  c++  java
  • 数据结构和算法-列表

    队列和栈相反

    • 队列: 先进先出(FIFO)
    • 栈: 后进先出(LIFO)

    类型

    • 循环队列
      • Disruptor高性能队列
    • 并发队列(线程安全)
    • 阻塞队列

    顺序队列

    使用python的list结构来模拟, 在右端插入的话时间复杂度是O(n), 在左端弹出的话是O(1)

    方式一: 每次出队操作都要移动数组

    # coding:utf-8
    
    """
    使用列表模拟单端队列
    
    左出右进
    """
    
    
    class Queue(object):
        """
        使用列表模拟实现单端队列
        """
    
        def __init__(self):
            self.items = []
    
        def isEmpty(self):
            return self.items == []
    
        def size(self):
            return len(self.items)
    
        def enqueue(self, item):
            self.items.append(item)
    
        def dequeue(self):
            """
            每次出队所有元素都会向前移动
            :return:
            """
            if self.isEmpty():
                raise Exception("empty queue")
            res = self.items.pop(0)
            return res
    
    

    方式二

    定义两个指针head和tail, 每次出队时不用再移动所有元素, 只有当入队时如果tail指针在最尾部, 检测数组是否还有空间

    • 如果还有空间, 移动所有元素后再添加
    • 如果没有空间, 返回错误
    # coding:utf-8
    
    
    class Queue(object):
        """
        队列
    
        使用固定数组的形式, 优点是出队操作不用再每次都移动数组
    
        只有当入队操作的时候, 如果数组内还有空余位置, 但是tail已经在最尾部了, 此时需要进行数据搬移
    
        """
    
        def __init__(self, length):
            self.items = [0 for _ in range(length)]
            self.head = 0
            self.tail = 0
            self.length = length
    
        def size(self):
            return self.tail - self.head
    
        def enqueue(self, item):
            if self.tail >= self.length:
                if self.head == 0:
                    raise Exception("Full")
                # 进行数据搬移
                for i in range(self.head, self.tail):
                    self.items[i - self.head] = self.items[i]
                # 移动完毕后重新更新head和tail
                self.tail = self.tail - self.head
                self.head = 0
    
            self.items[self.tail] = item
            self.tail += 1
    
        def dequeue(self):
            if self.head >= self.tail:
                raise Exception("Empty")
            data = self.items[self.head]
            self.head += 1
            return data
    
    
    if __name__ == "__main__":
        q = Queue(10)
        for i in range(10):
            q.enqueue(i)
    
        print(q.dequeue())
        print(q.dequeue())
    
        q.enqueue(11)
        q.enqueue(12)
    
        res = []
        while True:
            try:
                res.append(q.dequeue())
            except Exception as e:
                print(e)
                break
        print(res)
    
    
    """
    0
    1
    Empty
    [2, 3, 4, 5, 6, 7, 8, 9, 11, 12]
    """
    

    链式队列

    # coding:utf-8
    
    """
    基于链表实现的复杂度
    """
    
    
    class Node(object):
        def __init__(self, data, next_=None):
            self.data = data
            self.next_ = next_
    
    
    class Queue(object):
        def __init__(self):
            self.head = None
            self.tail = None
            self.length = 0
    
        def size(self):
            return self.length
    
        def enqueue(self, item):
            if self.head == None:
                self.head = Node(item)
                self.tail = self.head
            else:
                self.tail.next_ = Node(item)
                self.tail = self.tail.next_
            self.length += 1
    
        def dequeue(self):
            if self.head == None:
                raise Exception("Empty")
            data = self.head.data
            self.head = self.head.next_
            self.length -= 1
            return data
    
    
    if __name__ == "__main__":
        q = Queue()
        for i in range(10):
            q.enqueue(i)
    
        res = []
        while True:
            try:
                res.append(q.dequeue())
            except Exception as e:
                print(e)
                break
        print(res)
    

    循环队列

    模拟队列是一个环, 同样需要定义head和tail指针, 该类型队列可以避免移动元素的操作,
    如判断循环队列是否已满的条件是(tail + 1) % n = head

    # coding:utf-8
    
    """
    循环队列
    """
    
    
    class QueueLoop(object):
        def __init__(self, length):
            self.items = [0 for _ in range(length)]
            self.head = 0
            self.tail = 0
            self.length = length + 1    # 循环队列会多用一位, 因为当tail指向最后一个空位置时认为已经满了
    
        def enqueue(self, item):
            if self.is_full():
                raise Exception("Full")
            self.items[self.tail] = item
            self.tail += 1
    
        def dequeue(self):
            if self.is_empty():
                raise Exception("Empty")
            data = self.items[self.head]
            self.head = self.head + 1
            return data
    
        def is_empty(self):
            if self.head == self.tail:
                return True
            else:
                return False
    
        def is_full(self):
            """
            当tail指向head的前一位的时候认为队列已满
            :return: 
            """
            if (self.tail + 1) % self.length == self.head:
                return True
            else:
                return False
    
    
    
    if __name__ == "__main__":
        q = QueueLoop(10)
    
        for i in range(10):
            q.enqueue(i)
    
        res = []
        while True:
            try:
                res.append(q.dequeue())
            except Exception as e:
                print(e)
                break
        print(res)
    
    
    """
    Empty
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    
    """
        
    """
    Empty
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    
    """
    

    资料

    • <<大话数据结构>>-程杰
    • 数据结构和算法之美-王争
  • 相关阅读:
    火狐优化及遇到的问题
    拷贝工程,名字不改变问题
    Ajax基础实例
    Java中检测字符串的编码格式
    innerHTML和outerHTML有什么区别
    启动Tomcat出现“Bad version number in .class file (unable to load class XXX)”解决
    MyEclipse8.6安装SVN 教程 与遇到的问题
    彻底卸载JDK的-并只依赖配置环境安装JDK(不依赖注册表)-解决Error opening registry key'softwareJavasoftJava Runti问题
    数据库下的分页代码
    WSGI
  • 原文地址:https://www.cnblogs.com/zlone/p/10989120.html
Copyright © 2011-2022 走看看