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

说明

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

第1章:ADT抽象数据类型,定义数据和其操作

什么是ADT: 抽象数据类型(Abstract Data Type),学过数据结构的应该都知道。

如何为 ADT 选择数据结构

  1. 数据结构是否满足 ADT 域指定的存储要求?
  2. 数据结构是否提供数据访问和操作功能来完全实现 ADT?
  3. 高效执行?基于复杂性分析。

        下边代码是个简单的示例,比如实现一个简单的Bag类,先定义其具有的操作,然后我们再用类的magic method来实现这些方法:

class Bag:"""constructor: 构造函数sizecontainsappendremoveiter"""def __init__(self):self._items = list()def __len__(self):return len(self._items)def __contains__(self, item):return item in self._itemsdef add(self, item):self._items.append(item)def remove(self, item):assert item in self._items, 'item must in the bag'return self._items.remove(item)def __iter__(self):return _BagIterator(self._items)class _BagIterator:""" 注意这里实现了迭代器类 """def __init__(self, seq):self._bag_items = seqself._cur_item = 0def __iter__(self):return selfdef __next__(self):if self._cur_item < len(self._bag_items):item = self._bag_items[self._cur_item]self._cur_item += 1return itemelse:raise StopIterationb = Bag()
b.add(1)
b.add(2)
for i in b:     # for使用__iter__构建,用__next__迭代print(i)"""
# for 语句等价于
i = b.__iter__()
while True:try:item = i.__next__()print(item)except StopIteration:break
"""

第2章:array 和 list

        array: 定长,操作有限,但是节省内存;貌似我的生涯中还没用过,不过python3.5中我试了确实有array类,可以用import array直接导入

        list: 会预先分配内存,操作丰富,但是耗费内存。我用sys.getsizeof做了实验。我个人理解很类似C++ STL里的vector,是使用最频繁的数据结构。

  • list.append: 如果之前没有分配够内存,会重新开辟新区域,然后复制之前的数据,复杂度退化
  • list.insert: 会移动被插入区域后所有元素,O(n)
  • list.pop: pop不同位置需要的复杂度不同pop(0)是O(1)复杂度,pop()首位O(n)复杂度
  • list[]: slice操作copy数据(预留空间)到另一个list

来实现一个array的ADT:

import ctypesclass Array:def __init__(self, size):assert size > 0, 'array size must be > 0'self._size = sizePyArrayType = ctypes.py_object * sizeself._elements = PyArrayType()self.clear(None)def __len__(self):return self._sizedef __getitem__(self, index):assert index >= 0 and index < len(self), 'out of range'return self._elements[index]def __setitem__(self, index, value):assert index >= 0 and index < len(self), 'out of range'self._elements[index] = valuedef clear(self, value):""" 设置每个元素为value """for i in range(len(self)):self._elements[i] = valuedef __iter__(self):return _ArrayIterator(self._elements)class _ArrayIterator:def __init__(self, items):self._items = itemsself._idx = 0def __iter__(self):return selfdef __next__(self):if self._idex < len(self._items):val = self._items[self._idx]self._idex += 1return valelse:raise StopIteration

2.1 二维数组Two-Demensional Arrays

class Array2D:""" 要实现的方法Array2D(nrows, ncols):    constructornumRows()numCols()clear(value)getitem(i, j)setitem(i, j, val)"""def __init__(self, numrows, numcols):self._the_rows = Array(numrows)     # 数组的数组for i in range(numrows):self._the_rows[i] = Array(numcols)@propertydef numRows(self):return len(self._the_rows)@propertydef NumCols(self):return len(self._the_rows[0])def clear(self, value):for row in self._the_rows:row.clear(value)def __getitem__(self, ndx_tuple):    # ndx_tuple: (x, y)assert len(ndx_tuple) == 2row, col = ndx_tuple[0], ndx_tuple[1]assert (row >= 0 and row < self.numRows andcol >= 0 and col < self.NumCols)the_1d_array = self._the_rows[row]return the_1d_array[col]def __setitem__(self, ndx_tuple, value):assert len(ndx_tuple) == 2row, col = ndx_tuple[0], ndx_tuple[1]assert (row >= 0 and row < self.numRows andcol >= 0 and col < self.NumCols)the_1d_array = self._the_rows[row]the_1d_array[col] = value

2.2 The Matrix ADT, m行,n列。这个最好用还是用pandas处理矩阵,自己实现比较*疼

class Matrix:""" 最好用pandas的DataFrameMatrix(rows, ncols): constructornumCols()getitem(row, col)setitem(row, col, val)scaleBy(scalar): 每个元素乘scalartranspose(): 返回transpose转置add(rhsMatrix):    size must be the samesubtract(rhsMatrix)multiply(rhsMatrix)"""def __init__(self, numRows, numCols):self._theGrid = Array2D(numRows, numCols)self._theGrid.clear(0)@propertydef numRows(self):return self._theGrid.numRows@propertydef NumCols(self):return self._theGrid.numColsdef __getitem__(self, ndxTuple):return self._theGrid[ndxTuple[0], ndxTuple[1]]def __setitem__(self, ndxTuple, scalar):self._theGrid[ndxTuple[0], ndxTuple[1]] = scalardef scaleBy(self, scalar):for r in range(self.numRows):for c in range(self.numCols):self[r, c] *= scalardef __add__(self, rhsMatrix):assert (rhsMatrix.numRows == self.numRows andrhsMatrix.numCols == self.numCols)newMartrix = Matrix(self.numRows, self.numCols)for r in range(self.numRows):for c in range(self.numCols):newMartrix[r, c] = self[r, c] + rhsMatrix[r, c]

第3章:Sets 和 Maps

除了list之外,最常用的应该就是python内置的set和dict了。

3.1 sets ADT

集合是一个容器,它存储给定可比域中唯一值的集合,其中存储的值没有特定的顺序。

class Set:""" 使用list实现set ADTSet()length()contains(element)add(element)remove(element)equals(element)isSubsetOf(setB)union(setB)intersect(setB)difference(setB)iterator()"""def __init__(self):self._theElements = list()def __len__(self):return len(self._theElements)def __contains__(self, element):return element in self._theElementsdef add(self, element):if element not in self:self._theElements.append(element)def remove(self, element):assert element in self, 'The element must be set'self._theElements.remove(element)def __eq__(self, setB):if len(self) != len(setB):return Falseelse:return self.isSubsetOf(setB)def isSubsetOf(self, setB):for element in self:if element not in setB:return Falsereturn Truedef union(self, setB):newSet = Set()newSet._theElements.extend(self._theElements)for element in setB:if element not in self:newSet._theElements.append(element)return newSet

3.2 Maps or Dict: 键值对,python内部采用hash实现。

class Map:""" Map ADT list implementionMap()length()contains(key)add(key, value)remove(key)valudOf(key)iterator()"""def __init__(self):self._entryList = list()def __len__(self):return len(self._entryList)def __contains__(self, key):ndx = self._findPosition(key)return ndx is not Nonedef add(self, key, value):ndx = self._findPosition(key)if ndx is not None:self._entryList[ndx].value = valuereturn Falseelse:entry = _MapEntry(key, value)self._entryList.append(entry)return Truedef valueOf(self, key):ndx = self._findPosition(key)assert ndx is not None, 'Invalid map key'return self._entryList[ndx].valuedef remove(self, key):ndx = self._findPosition(key)assert ndx is not None, 'Invalid map key'self._entryList.pop(ndx)def __iter__(self):return _MapIterator(self._entryList)def _findPosition(self, key):for i in range(len(self)):if self._entryList[i].key == key:return ireturn Noneclass _MapEntry:    # or use collections.namedtuple('_MapEntry', 'key,value')def __init__(self, key, value):self.key = keyself.value = value

3.3 The multiArray ADT, 多维数组,一般是使用一个一维数组模拟,然后通过计算下标获取元素

class MultiArray:""" row-major or column-marjor ordering, this is row-major orderingMultiArray(d1, d2, ...dn)dims():   the number of dimensionslength(dim): the length of given array dimensionclear(value)getitem(i1, i2, ... in), index(i1,i2,i3) = i1*(d2*d3) + i2*d3 + i3setitem(i1, i2, ... in)计算下标:index(i1,i2,...in) = i1*f1 + i2*f2 + ... + i(n-1)*f(n-1) + in*1"""def __init__(self, *dimensions):# Implementation of MultiArray ADT using a 1-D # array,数组的数组的数组。。。assert len(dimensions) > 1, 'The array must have 2 or more dimensions'self._dims = dimensions# Compute to total number of elements in the arraysize = 1for d in dimensions:assert d > 0, 'Dimensions must be > 0'size *= d# Create the 1-D array to store the elementsself._elements = Array(size)# Create a 1-D array to store the equation factorsself._factors = Array(len(dimensions))self._computeFactors()@propertydef numDims(self):return len(self._dims)def length(self, dim):assert dim > 0 and dim < len(self._dims), 'Dimension component out of range'return self._dims[dim-1]def clear(self, value):self._elements.clear(value)def __getitem__(self, ndxTuple):assert len(ndxTuple) == self.numDims, 'Invalid # of array subscripts'index = self._computeIndex(ndxTuple)assert index is not None, 'Array subscript out of range'return self._elements[index]def __setitem__(self, ndxTuple, value):assert len(ndxTuple) == self.numDims, 'Invalid # of array subscripts'index = self._computeIndex(ndxTuple)assert index is not None, 'Array subscript out of range'self._elements[index] = valuedef _computeIndex(self, ndxTuple):# using the equation: i1*f1 + i2*f2 + ... + in*fnoffset = 0for j in range(len(ndxTuple)):if ndxTuple[j] < 0 or ndxTuple[j] >= self._dims[j]:return Noneelse:offset += ndexTuple[j] * self._factors[j]return offset

第4章:Algorithm Analysis

一般使用大O标记法来衡量算法的平均时间复杂度, 1 < log(n) < n < nlog(n) < n^2 < n^3 < a^n。 了解常用数据结构操作的平均时间复杂度有利于使用更高效的数据结构,当然有时候需要在时间和空间上进行衡量,有些操作甚至还会退化,比如list的append操作,如果list空间不够,会去开辟新的空间,操作复杂度退化到O(n),有时候还需要使用均摊分析(amortized)

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

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

相关文章

seata的部署和集成:部署Seata的tc-server、微服务集成seata、TC服务的高可用和异地容灾

seata的部署和集成 一、部署Seata的tc-server 1.下载 首先我们要下载seata-server包&#xff0c;地址在http&#x1f615;/seata.io/zh-cn/blog/download.html 当然&#xff0c;课前资料也准备好了&#xff1a; 2.解压 在非中文目录解压缩这个zip包&#xff0c;其目录结构…

Kafka3.0.0版本——消费者(消费者组初始化流程图解)

一、消费者组初始化流程图解 每个consumer都发送JoinGroup请求&#xff0c;如下图所示&#xff1a; 选出一个consumer作为leader&#xff0c;如下图所示&#xff1a; 把要消费的topic情况发送给leader 消费者&#xff0c;如下图所示&#xff1a; leader会负责制定消费方案…

QQ文件传输协议研究

引言 我们都知道,现在越来越多的应用采取了 HTTPS or TLS 传输协议,对于一般的协议,我们可以使用中间人技术对流量进行劫持转发,从而破解密文,这边可以参见我的另外一篇文章基于加密邮件协议的中间人攻防实战, 而对于 HTTPS 应用即使是我们采取中间人技术,也很难让浏览器…

File类操作

1. 练习一 在当前模块下的 text 文件夹中创建一个 io.txt 文件 import java.io.File; import java.io.IOException;public class Practice1 {public static void main(String[] args) {File file new File("D:\\kaifamiao");File file1 new File(file, "tex…

得帆信息副总裁——孔金:低代码在医药行业的应用实践

医药行业作为国计民生的重点行业之一&#xff0c;受到法律法规的严格监管&#xff0c;其信息化程度普遍较高&#xff0c;也是较早通过ERP&#xff08;企业资源管理系统&#xff09;、WMS&#xff08;仓储管理系统&#xff09;、TMS&#xff08;物流管理系统&#xff09;、MES&a…

AWS DynamoDB浅析

AWS DynamoDB是一个NOSQL数据库。 可以通过IAM直接控制权限&#xff0c;和AWS其他服务连用非常方便。 DynamoDB的几个概念 Partition Key&#xff1a;分区键。如果没有Sort key&#xff0c;那么Partition Key必须唯一&#xff0c;如有Sort key&#xff0c;Partition Key可以重…

dos汇编总结

前言&#xff1a; 计组课本需要学习汇编&#xff0c;可惜自己看不太懂。这里发现一个学习方法交给大家。其实新手可能一些抽象表示难理解&#xff0c;这里我把我学习的疑问点以及思路记录一下。 要点&#xff1a; 这里我以题为例给大家分析 输出输入对应大写字母的小写字母 …

MySql系列-常用命令

基础知识-常用命令 命令不区分大小写 1、mysql连接 mysql -u username -p 实例: mysql -u root -p 2、元数据查询 //服务器版本信息 SELECT VERSION( ) //当前数据库名 (或者返回空) SELECT DATABASE( ) //当前用户名 SELECT USER( ) //服务器状态 SHOW STATUS //服务…

网络原理(二)TCP的可靠传输

网络原理&#xff08;一&#xff09;目录 网络原理应用层传输层先说UDP&#xff08;不可靠传输&#xff09;重点说明&#xff34;&#xff23;&#xff30;&#xff08;可靠传输&#xff09;一、确认应答二、超时重传三、链接管理建立连接断开链接 四、滑动窗口五、流量控制&am…

Flink CDC-MySQL CDC配置及DataStream API实现代码...可实现监控采集多个数据库的多个表

MySQL CDC配置 第一步: 启用binlog 1. 检查MySQL的binlog是否已启用 show variables like %log_bin%;2. 若未启用binlog 打开MySQL配置文件my.cnf(MySQL安装目录的etc文件夹下)找到[mysqld]部分&#xff0c;添加如下配置log-binmysql-bin # 指定二进制日志文件的名称前缀…

MySQL之事务

事务概念 事务就是一组DML语句组成&#xff0c;这些语句在逻辑上存在相关性&#xff0c;这一组DML语句要么全部成功&#xff0c;要么全部失败&#xff0c;是一 个整体。 一个完整的事务&#xff0c;绝对不是简单的 sql 集合&#xff0c;还需要满足如下四个属性&#xff08;ACI…

由Qt::BlockingQueuedConnection引起的关闭Qt主页面而后台仍有进程残留

BUG&#xff1a;由Qt::BlockingQueuedConnection引起的关闭Qt主页面而后台仍有进程残留 1、错误代码示例 首先我们看下下面的代码&#xff0c;可以思考一下代码的错误之处 /** BlockingQueueDeadLock.h **/ #pragma once#include <QtWidgets/QMainWindow> #include &q…

Android 13.0 Launcher3定制之双层改单层(去掉抽屉式四)

1.概述 在13.0的系统产品开发中,对于在Launcher3中的抽屉模式中,系统默认的就是抽屉单层模式,但是在很多产品中需要默认为单层模式,就是要求去掉双层抽屉模式,接下来看下如何继续实现去掉抽屉双层模式,来变成单层模式第四节 2.Launcher3定制之双层改单层(去掉抽屉式四)的…

初阶扫雷(超详解)

✨博客主页&#xff1a;小钱编程成长记 &#x1f388;博客专栏&#xff1a;C语言小游戏 &#x1f388;推荐相关博文&#xff1a;初阶三子棋&#xff08;超详解&#xff09; 初阶扫雷 1.游戏介绍2.基本思路3.实现前的准备4.实现步骤4.1 打印菜单4.2 初始化扫雷棋盘4.3 打印扫雷棋…

单片机之硬件记录

一、概念 VBAT 当使用电池或其他电源连接到VBAT脚上时&#xff0c;当VDD断电时&#xff0c;可以保存备份寄存器的内容和维持RTC的功能。如果应用中没有使用外部电池&#xff0c;VBAT引脚应接到VDD引脚上。 VCC&#xff1a;Ccircuit 表示电路的意思,即接入电路的电压&#x…

C语言入门Day_18 判断和循坏的小结

目录 前言&#xff1a; 1.判断 2.循环 3.课堂笔记 4.思维导图 前言&#xff1a; 判断语句和循环语句都可以大致分为三个部分&#xff0c;第一个部分是固定的语法格式&#xff1b;第二部分是代码的执行顺序&#xff0c;第三部分是判断和循环成立与否的判断条件。 1.判断 1…

Allegro166版本如何在颜色管理器中实时显示层面操作指导

Allegro166版本如何在颜色管理器中实时显示层面操作指导 在用Allegro166进行PCB设计的时候,需要在颜色管理器中频繁的开关层面。但是166不像172一样在颜色管理器中可以实时的开关层面,如下图 需要打开Board Geometry/Soldermask_top层,首先需要勾选这个层面,再点击Apply即…

ubuntu 20.04 docker 安装 mysql

要在Ubuntu 20.04上安装Docker并运行MySQL容器&#xff0c;您可以按照以下步骤操作&#xff1a; 1.更新系统包列表&#xff1a; sudo apt update2.安装Docker&#xff1a; sudo apt install docker.io3.启动Docker服务并设置其开机自启动&#xff1a; sudo systemctl start…

直播|DITA内容发布工具解析 - 问答总结

9月6日&#xff0c;我们进行了一场名为“DITA内容发布工具解析”的直播。通过直播&#xff0c;大家了解到&#xff1a; DITA-OT简介 默认输出效果 定制以后输出效果 发布过程与样式定制 在问答环节&#xff0c;大家进行了热烈沟通。我将几个大家关心的问题和答复总结如下&…

Vue2进阶篇学习笔记

文章目录 Vue2进阶学习笔记前言1、Vue脚手架学习1.1 Vue脚手架概述1.2 Vue脚手架安装1.3 常用属性1.4 插件 2、组件基本概述3、非单文件组件3.1 非单文件组件的基本使用3.2 组件的嵌套 4、单文件组件4.1 快速体验4.2 Todo案例 5、浏览器本地存储6、组件的自定义事件6.1 使用自定…