用python实现基本数据结构【02/4】

news2024/11/25 7:15:31

*说明

        如果需要用到这些知识却没有掌握,则会让人感到沮丧,也可能导致面试被拒。无论是花几天时间“突击”,还是利用零碎的时间持续学习,在数据结构上下点功夫都是值得的。那么Python 中有哪些数据结构呢?列表、字典、集合,还有……栈?Python 有栈吗?本系列文章将给出详细拼图。

第5章:Searching 和 Sorting

        排序和查找是最基础和频繁的操作,python内置了in操作符和bisect二分操作模块实现查找,内置了sorted方法来实现排序操作。二分和快排也是面试中经常考到的,本章讲的是基本的排序和查找。

def binary_search(sorted_seq, val):
    """ 实现标准库中的bisect.bisect_left """
    low = 0
    high = len(sorted_seq) - 1
    while low <= high:
        mid = (high + low) // 2
        if sorted_seq[mid] == val:
            return mid
        elif val < sorted_seq[mid]:
            high = mid - 1
        else:
            low = mid + 1
    return low

  def bubble_sort(seq):  # O(n^2), n(n-1)/2 = 1/2(n^2 + n)
      n = len(seq)
      for i in range(n-1):
          for j in range(n-1-i):    # 这里之所以 n-1 还需要 减去 i 是因为每一轮冒泡最大的元素都会冒泡到最后,无需再比较
              if seq[j] > seq[j+1]:
                  seq[j], seq[j+1] = seq[j+1], seq[j]


def select_sort(seq):
    """可以看作是冒泡的改进,每次找一个最小的元素交换,每一轮只需要交换一次"""
    n = len(seq)
    for i in range(n-1):
        min_idx = i    # assume the ith element is the smallest
        for j in range(i+1, n):
            if seq[j] < seq[min_idx]:   # find the minist element index
                min_idx = j
        if min_idx != i:    # swap
            seq[i], seq[min_idx] = seq[min_idx], seq[i]


def insertion_sort(seq):
    """ 每次挑选下一个元素插入已经排序的数组中,初始时已排序数组只有一个元素"""
    n = len(seq)
    for i in range(1, n):
        value = seq[i]    # save the value to be positioned
        # find the position where value fits in the ordered part of the list
        pos = i
        while pos > 0 and value < seq[pos-1]:
            # Shift the items to the right during the search
            seq[pos] = seq[pos-1]
            pos -= 1
        seq[pos] = value


def merge_sorted_list(listA, listB):
    """ 归并两个有序数组 """
    new_list = list()
    a = b = 0
    while a < len(listA) and b < len(listB):
        if listA[a] < listB[b]:
            new_list.append(listA[a])
            a += 1
        else:
            new_list.append(listB[b])
            b += 1

    while a < len(listA):
        new_list.append(listA[a])
        a += 1

    while b < len(listB):
        new_list.append(listB[b])
        b += 1

    return new_list

第6章: Linked Structure

        list是最常用的数据结构,但是list在中间增减元素的时候效率会很低,这时候linked list会更适合,缺点就是获取元素的平均时间复杂度变成了O(n)

# 单链表实现
class ListNode:
    def __init__(self, data):
        self.data = data
        self.next = None


def travsersal(head, callback):
    curNode = head
    while curNode is not None:
        callback(curNode.data)
        curNode = curNode.next


def unorderdSearch(head, target):
    curNode = head
    while curNode is not None and curNode.data != target:
        curNode = curNode.next
    return curNode is not None


# Given the head pointer, prepend an item to an unsorted linked list.
def prepend(head, item):
    newNode = ListNode(item)
    newNode.next = head
    head = newNode


# Given the head reference, remove a target from a linked list
def remove(head, target):
    predNode = None
    curNode = head
    while curNode is not None and curNode.data != target:
        # 寻找目标
        predNode = curNode
        curNode = curNode.data
    if curNode is not None:
        if curNode is head:
            head = curNode.next
        else:
            predNode.next = curNode.next

第7章:Stacks

        栈也是计算机里用得比较多的数据结构,栈是一种后进先出的数据结构,可以理解为往一个桶里放盘子,先放进去的会被压在地下,拿盘子的时候,后放的会被先拿出来。

class Stack:
    """ Stack ADT, using a python list
    Stack()
    isEmpty()
    length()
    pop(): assert not empty
    peek(): assert not empty, return top of non-empty stack without removing it
    push(item)
    """
    def __init__(self):
        self._items = list()

    def isEmpty(self):
        return len(self) == 0

    def __len__(self):
        return len(self._items)

    def peek(self):
        assert not self.isEmpty()
        return self._items[-1]

    def pop(self):
        assert not self.isEmpty()
        return self._items.pop()

    def push(self, item):
        self._items.append(item)


class Stack:
    """ Stack ADT, use linked list
    使用list实现很简单,但是如果涉及大量push操作,list的空间不够时复杂度退化到O(n)
    而linked list可以保证最坏情况下仍是O(1)
    """
    def __init__(self):
        self._top = None    # top节点, _StackNode or None
        self._size = 0    # int

    def isEmpty(self):
        return self._top is None

    def __len__(self):
        return self._size

    def peek(self):
        assert not self.isEmpty()
        return self._top.item

    def pop(self):
        assert not self.isEmpty()
        node = self._top
        self.top = self._top.next
        self._size -= 1
        return node.item

    def _push(self, item):
        self._top = _StackNode(item, self._top)
        self._size += 1


class _StackNode:
    def __init__(self, item, link):
        self.item = item
        self.next = link

第8章:Queues

队列也是经常使用的数据结构,比如发送消息等,celery可以使用redis提供的list实现消息队列。 本章我们用list和linked list来实现队列和优先级队列。

class Queue:
    """ Queue ADT, use list。list实现,简单但是push和pop效率最差是O(n)
    Queue()
    isEmpty()
    length()
    enqueue(item)
    dequeue()
    """
    def __init__(self):
        self._qList = list()

    def isEmpty(self):
        return len(self) == 0

    def __len__(self):
        return len(self._qList)

    def enquue(self, item):
        self._qList.append(item)

    def dequeue(self):
        assert not self.isEmpty()
        return self._qList.pop(0)


from array import Array    # Array那一章实现的Array ADT
class Queue:
    """
    circular Array ,通过头尾指针实现。list内置append和pop复杂度会退化,使用
    环数组实现可以使得入队出队操作时间复杂度为O(1),缺点是数组长度需要固定。
    """
    def __init__(self, maxSize):
        self._count = 0
        self._front = 0
        self._back = maxSize - 1
        self._qArray = Array(maxSize)

    def isEmpty(self):
        return self._count == 0

    def isFull(self):
        return self._count == len(self._qArray)

    def __len__(self):
        return len(self._count)

    def enqueue(self, item):
        assert not self.isFull()
        maxSize = len(self._qArray)
        self._back = (self._back + 1) % maxSize     # 移动尾指针
        self._qArray[self._back] = item
        self._count += 1

    def dequeue(self):
        assert not self.isFull()
        item = self._qArray[self._front]
        maxSize = len(self._qArray)
        self._front = (self._front + 1) % maxSize
        self._count -= 1
        return item

class _QueueNode:
    def __init__(self, item):
        self.item = item


class Queue:
    """ Queue ADT, linked list 实现。为了改进环型数组有最大数量的限制,改用
    带有头尾节点的linked list实现。
    """
    def __init__(self):
        self._qhead = None
        self._qtail = None
        self._qsize = 0

    def isEmpty(self):
        return self._qhead is None

    def __len__(self):
        return self._count

    def enqueue(self, item):
        node = _QueueNode(item)    # 创建新的节点并用尾节点指向他
        if self.isEmpty():
            self._qhead = node
        else:
            self._qtail.next = node
        self._qtail = node
        self._qcount += 1

    def dequeue(self):
        assert not self.isEmpty(), 'Can not dequeue from an empty queue'
        node = self._qhead
        if self._qhead is self._qtail:
            self._qtail = None
        self._qhead = self._qhead.next    # 前移头节点
        self._count -= 1
        return node.item


class UnboundedPriorityQueue:
    """ PriorityQueue ADT: 给每个item加上优先级p,高优先级先dequeue
    分为两种:
    - bounded PriorityQueue: 限制优先级在一个区间[0...p)
    - unbounded PriorityQueue: 不限制优先级

    PriorityQueue()
    BPriorityQueue(numLevels): create a bounded PriorityQueue with priority in range
        [0, numLevels-1]
    isEmpty()
    length()
    enqueue(item, priority): 如果是bounded PriorityQueue, priority必须在区间内
    dequeue(): 最高优先级的出队,同优先级的按照FIFO顺序

    - 两种实现方式:
    1.入队的时候都是到队尾,出队操作找到最高优先级的出队,出队操作O(n)
    2.始终维持队列有序,每次入队都找到该插入的位置,出队操作是O(1)
    (注意如果用list实现list.append和pop操作复杂度会因内存分配退化)
    """
    from collections import namedtuple
    _PriorityQEntry = namedtuple('_PriorityQEntry', 'item, priority')

    # 采用方式1,用内置list实现unbounded PriorityQueue
    def __init__(self):
        self._qlist = list()

    def isEmpty(self):
        return len(self) == 0

    def __len__(self):
        return len(self._qlist)

    def enqueue(self, item, priority):
        entry = UnboundedPriorityQueue._PriorityQEntry(item, priority)
        self._qlist.append(entry)

    def deque(self):
        assert not self.isEmpty(), 'can not deque from an empty queue'
        highest = self._qlist[0].priority
        for i in range(len(self)):    # 出队操作O(n),遍历找到最高优先级
            if self._qlist[i].priority < highest:
                highest = self._qlist[i].priority
        entry = self._qlist.pop(highest)
        return entry.item


class BoundedPriorityQueue:
    """ BoundedPriorityQueue ADT,用linked list实现。上一个地方提到了 BoundedPriorityQueue
    但是为什么需要 BoundedPriorityQueue呢? BoundedPriorityQueue 的优先级限制在[0, maxPriority-1]
    对于 UnboundedPriorityQueue,出队操作由于要遍历寻找优先级最高的item,所以平均
    是O(n)的操作,但是对于 BoundedPriorityQueue,用队列数组实现可以达到常量时间,
    用空间换时间。比如要弹出一个元素,直接找到第一个非空队列弹出 元素就可以了。
    (小数字代表高优先级,先出队)

    qlist
    [0] -> ["white"]
    [1]
    [2] -> ["black", "green"]
    [3] -> ["purple", "yellow"]
    """
    # Implementation of the bounded Priority Queue ADT using an array of #
    # queues in which the queues are implemented using a linked list.
    from array import Array    #  第二章定义的ADT

    def __init__(self, numLevels):
        self._qSize = 0
        self._qLevels = Array(numLevels)
        for i in range(numLevels):
            self._qLevels[i] = Queue()    # 上一节讲到用linked list实现的Queue

    def isEmpty(self):
        return len(self) == 0

    def __len__(self):
        return len(self._qSize)

    def enqueue(self, item, priority):
        assert priority >= 0 and priority < len(self._qLevels), 'invalid priority'
        self._qLevel[priority].enquue(item)    # 直接找到 priority 对应的槽入队

    def deque(self):
        assert not self.isEmpty(), 'can not deque from an empty queue'
        i = 0
        p = len(self._qLevels)
        while i < p and not self._qLevels[i].isEmpty():    # 找到第一个非空队列
            i += 1
        return self._qLevels[i].dequeue()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/994783.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

STM32初学-外部RTC时钟芯片DS3231

RTC(Real_Time Clock)即实时时钟&#xff0c;它是电子产品中不可或缺的东西。其最直接的作用就是时钟功能。细心的朋友可以发现&#xff0c;当我们的电脑或者手机没联网时&#xff0c;仍然可以正常显示日期与时钟&#xff0c;这就是RTC的功劳。 RTC的运行无需网络连接&#xff…

python创建exe文件

1、搭建环境 pip install pyinstaller 2、准备测试代码 exe_test.py import timeprint("hello") print("hello") print("hello") print("hello")time.sleep(5) 注&#xff1a;添加sleep以便在执行exe文件的时候能看到结果 3、生…

在Windows操作系统上安装PostgreSQL数据库

在Windows操作系统上安装PostgreSQL数据库 一、在Windows操作系统上安装PostgreSQL数据库 一、在Windows操作系统上安装PostgreSQL数据库 点击 PostgreSQL可跳转至PostGreSQL的官方下载地址。 &#xff08;1&#xff09; &#xff08;2&#xff09;选择安装的目录&#xff…

入门人工智能 —— 使用 Python 进行文件读写,并完成日志记录功能(4)

入门人工智能 —— 使用 Python 进行文件读写&#xff08;4&#xff09; 入门人工智能 —— 使用 Python 进行文件读写打开文件读取文件内容读取整个文件逐行读取文件内容读取所有行并存储为列表 写入文件内容关闭文件 日志记录功能核心代码&#xff1a;完整代码&#xff1a;运…

小工具——筛选图像小工具

最近在公司手动筛图片&#xff0c;需要将某些含有检测目标的图像手动筛选出来用于做新模型的测试。我最开始是两个文件夹&#xff0c;来回复制粘贴&#xff0c;后来感觉这种效率太低了&#xff0c;就随手写了一个图像筛查小工具。代码如下&#xff1a; import sys from PyQt5.…

图论-图的深度优先遍历-Java

回顾力扣144/94//145/102/589/590/429&#xff0c;熟练掌握递归和非递归写法。 图论不强调非递归。 使用邻接表 1个连通分量 Graph.java package Chapt02_DFS; import java.io.File; import java.io.IOException; import java.util.TreeSet; import java.util.Scanner;///…

66.C++多态与虚函数

目录 1.什么是多态 2.多态的分类 3.对象转型 3.1 向上转型&#xff1a; 3.2 向下转型&#xff1a; 4.虚函数 1.什么是多态 生活中的多态&#xff0c;是指的客观的事物在人脑中的主观体现。例如&#xff0c;在路上看到⼀只哈士奇&#xff0c;你可以看做是哈士奇&#xf…

Unity实战(10):如何将某个相机的画面做成贴图(RenderTexture)

目录 前言 一、创建物体、材质与相机 二、将RenderTexture赋给材质 2.1 修改rt1的一些属性 2.2 将rtMat1材质的shader改为Unlit/Texture&#xff0c;并将rt1赋给这个材质 三、效果呈现 前言 本文记录如何将某个相机的画面做成贴图&#xff0c;即游戏某些场景中小地图做法…

时序预测 | MATLAB实现ICEEMDAN-iMPA-BiLSTM时间序列预测

时序预测 | MATLAB实现ICEEMDAN-iMPA-BiLSTM时间序列预测 目录 时序预测 | MATLAB实现ICEEMDAN-iMPA-BiLSTM时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 ICEEMDAN-iMPA-BiLSTM功率/风速预测 基于改进的自适应经验模态分解改进海洋捕食者算法双向长短期记忆…

基于SSM的农产品推广应用网站

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用Vue技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

华为云云耀云服务器L实例评测|centos系统搭建git私服

搭建git私服 前言一、云服务器二、服务器安装git三、服务器git配置1.创建文件用于存放公钥2.设置文件权限3.配置本地公钥 四、服务器部署git仓库四、git仓库到本地总结 前言 之前一直想搭建一个属于自己的git私服&#xff0c;然后没赶上厂商的活动&#xff0c;这次正好赶上华为…

学习笔记——树上哈希

普通子树哈希 树上的很多东西都是转化成链上问题的&#xff0c;比如树上哈希 树上哈希&#xff0c;主要是用于树的同构这个东西上的 什么是树的同构&#xff1f; 如图&#xff0c;不考虑节点编号&#xff0c;三棵树是同构的 将树转化成链&#xff0c;一般有两种方式&#xf…

mongodb安装全过程详解

mongodb安装全过程详解 安装mongodb环境安装mongodb shell 安装mongodb环境 进入mongodb官网下载社区版服务器 点击跳转下载地址 选择适应自己系统的版本&#xff0c;然后下载 下图为下载后的文件&#xff0c;双击进行安装 需要注意的两个点 ①选择完整安装 ②不下载mongo…

C语言——指针进阶(二)

目录 七.函数指针数组 八.指向函数指针数组的指针 九.回调函数 结尾 七.函数指针数组 说白了函数指针数组就是函数指针名字后面添加[ ]&#xff0c;二者结合成为数组。 那么这个函数指针数组到底有什么用呢&#xff1f;先不用着急&#xff0c;下面用一个计算器功能代码为大…

【Linux】——网络基础:http协议

目录 前言 应用层 认识协议 协议的概念 传输结构化数据 序列化和反序列化 网络版本计算器 服务器端Server 客户端Client 协议定制 其它 运行效果 HTTP协议 HTTP的简介 认识URL urlencode和urldecode HTTP协议格式 HTTP请求 HTTP响应 HTTP的方法 GET和POST…

时序分解 | MATLAB实现基于LMD局部均值分解的信号分解分量可视化

时序分解 | MATLAB实现基于LMD局部均值分解的信号分解分量可视化 目录 时序分解 | MATLAB实现基于LMD局部均值分解的信号分解分量可视化效果一览基本介绍程序设计参考资料 效果一览 基本介绍 LMD局部均值分解 直接替换Excel即可运行包含频谱图相关系数图 Matlab语言 1.算法新颖…

UMA 2 - Unity Multipurpose Avatar☀️七.UMA API介绍

文章目录 🟥 UMA Data DNA参数引用位置🟥 UMA API介绍🟥 UMA Data DNA参数引用位置 我们想通过代码去控制如图所示参数,达到捏脸的目的.下面就是可以控制的代码: _dna["headSize"].Set(1); _avatar.BuildCharacter();我们观察发现操控代码类似Material去设置…

01_瑞萨GUI(LVGL)移植实战教程之软件和硬件准备

本系列教程配套出有视频教程&#xff0c;观看地址&#xff1a;https://www.bilibili.com/video/BV1gV4y1e7Sg 1. 软件和硬件准备 1.1 本节要点 本节学习如何搭建开发环境&#xff0c;硬件接线&#xff0c;为我们后续的学习做好基础必要的准备。 1.2资料准备 本文档所有用到…

flink 端到端一致性

背景 我们经常会混淆flink提供的状态一致性保证和数据端到端一致性保证的关系&#xff0c;总以为他们表达的是同一个意思&#xff0c;事实上&#xff0c;他们不是一个含义&#xff0c;flink只能保证其维护的内部状态的一致性&#xff0c;而数据端到端的一致性需要数据源&#…

Python下载、安装及如何配置Pycharm(Windows 11)详细教程

本文介绍在Windows 11系统Python的下载、安装及配置Pycharm 一、下载 官网地址&#xff1a;https://www.python.org/downloads/windows/ 1、选择Python 3.10.5版本下载 二、安装 1、选择自定义安装 2、全部默认勾选&#xff0c;点击Next 3、自定义安装路径 建议勾选inst…