数据结构和算法-列表

队列和栈相反

  • 队列: 先进先出(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

方式二

每次出队时不用再移动所有元素, 只有当入队时如果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)

循环队列

该类型队列可以避免移动元素的操作

上图中队列大小是8. 判断队列满的条件是(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]

"""

资料

  • <>-程杰
  • 数据结构和算法之美-王争

原文地址:https://www.cnblogs.com/zlone/p/10989120.html

时间: 2024-07-31 19:37:16

数据结构和算法-列表的相关文章

javascript数据结构与算法---列表

前言:在日常生活中,人们经常要使用列表,比如我们有时候要去购物时,为了购物时东西要买全,我们可以在去之前,列下要买的东西,这就要用的列表了,或者我们小时候上学那段时间,每次考完试后,学校都会列出这次考试成绩前十名的同学的排名及成绩单,等等这些都是列表的列子.我们计算机内也在使用列表,那么列表适合使用在什么地方呢?不适合使用在什么地方呢? 适合使用在:当列表的元素不是很多的情况下,可以使用列表,因为对列表中的元素查找或者排序时,效率还算非常高,反之:如果列表元素非常多的情况下,就不适合使用列表了.

数据结构和算法篇——散列表

之前讲过博主在某网买了一个数据结构与算法的课程.本篇散列表是其中的三节.散列表应该是 Java 程序员常用并且最先碰到的一个数据结构了吧?Java 的 HashMap 就是对散列表的实现.可以说散列表算是一个比较基础.比较好理解(抛开需要缜密设计的哈希函数不说).比较好用(查询时间复杂度O(1))的一种数据结构.本篇在此分享这三节的总结笔记. 1)散列表开篇介绍:https://www.cnblogs.com/christmad/p/11519055.html 2)如何打造一个工业级的散列表:h

数据结构与算法(刺猬书)读书笔记----目录

最近在抓底层的语言基础,以前对数据结构和算法并没有太大感觉,但越往深处学就越觉得这些基础真的是要牢牢掌握住.一个简简单单的数组,深究起来都有很多学问.所以打算写个一系列的读书笔记,好好梳理一下这一块的基础知识.这本书是<数据结构预算法JavaScript描述>,是基于JavaScript的.里面大致介绍了数组.列表.栈.队列.链表.散列.集合及各种常见基础算法.作为基础读物算是很全面的.这系列读书笔记也将会跟着书里的顺序一章章的进行梳理.整个过程计划耗时2-3个月,每周更新一到两张,更新的笔记

数据结构与算法系列研究四——数组和广义表

稀疏矩阵的十字链表实现和转置 一.数组和广义表的定义 数组的定义1:一个 N 维数组是受 N 组线性关系约束的线性表.           二维数组的逻辑结构可形式地描述为:           2_ARRAY(D,R)              其中 D={aij} | i=0,1,...,b1-1; j=0,1,...,b2-1;aij∈D0}              R={Row,Col}              Row={<aij,ai,j+1>|0<=i<=b1-1;

我的软考之路(七)——数据结构与算法(5)之查找

上篇博文我重点介绍了八大内部排序,这篇博文(数据结构与算法的最后一课)重点介绍查找,我们依旧沿用上篇博文的风格,先简单介绍,再以例子重点讲解. 下面我们开始今天的旅行,首先祝你旅行愉快,呵呵. 静态查找 若查找目的是为了查询某个特定的数据是否在表中或检索某个特定数据的各种属性,则此类查找表为静态查找表. 1.顺序查找 基本原理:从表一端开始逐个和关键字进行比较,若找到一个记录和给定值相等,则查找成功,反之失败.再简单点就是,一个一个的比大小,看看是否相等. 例子: 顺序查找更适合于顺序存储结构和

《数据结构与算法-Javascript描述》

今年的上半年,项目原因大部分时间在写js,这期间把easyui,echarts,bootstrap都用了点皮毛,写的多了,自然也多了些感觉,不过仅局限于运用层面,于是决定再系统的看些javascript方面的书,强化运用能力,便有了这本~来自于国内知名公司前端工程师翻译自国外的书,见名知意用Javascript角度来讲数据结构和算法,一方面可以把javascript的基础知识加强,一方面加深数据结构以及算法的理解和应用. 全书篇幅不长,第一章简明扼要对javascript做了简单的介绍,基本语法

javascript数据结构与算法---队列

队列是一种列表,不同的是队列只能在队尾插入元素,在队首删除元素.队列用于存储按顺序排列的数据,先进先出,这点和栈不一样(后入先出).在栈中,最后入栈的元素反而被优先处理.我们现在可以把队列想象对我们去餐馆吃饭的情景,很多人排队吃饭,排在最前面的人先打饭.新来的人只能在后面排队.直到轮到他们为止. 一:对队列的操作 队列有2种主要的操作,向队尾中插入新元素enqueue()方法和删除队列中的队首的元素的dequeue()方法,另外我们还有一个读取队头的元素,这个方法我们可以叫front()方法.该

数据结构与算法5: 递归(Recursion)

数据结构与算法5: 递归(Recursion) 写在前面 <软件随想录:程序员部落酋长Joel谈软件>一书中<学校只教java的危险性>一章提到,大学计算机系专业课有两个传统的知识点,但许多人从来都没搞懂过,那就是指针和递归.我也很遗憾没能早点熟练掌握这两个知识点.本节一些关键知识点和部分例子,都整理自教材或者网络,参考资料列在末尾.如果错误请纠正我. 思考列表: 1)什么程序具有递归解决的潜质? 2)递归还是非递归算法,怎么选择? 3)递归程序构造的一般模式 1.递归定义 首要引

Pascal数据结构与算法

第一章 数据结构与算法的引入 1.1 数据结构的基本概念 一. 学习数据结构的意义 程序设计 = 数据结构 + 算法 目前,80%的待处理的数据具有“算法简单”(四则运算.检索.排序等),“对象复杂”(数据类型不同.数据量大.需要保存)等特点,故合理组织数据.选择较好的数据结构可为高效算法(时间少.占用空间小)提供理想的对象. 二.基本术语 1.数据(data): 是对客观事物的符号的表示,是所有能输入到计算机中并被计算机程序处理的符号的总称.(P1表1-1中,学号.姓名.性别.民族等列为字符型