用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.rhkb.cn/news/129523.html

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

相关文章

Kubernetes (K8s) 解读:微服务与容器编排的未来

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f405;&#x1f43e;猫头虎建议程序员必备技术栈一览表&#x1f4d6;&#xff1a; &#x1f6e0;️ 全栈技术 Full Stack: &#x1f4da…

设计模式篇(Java):装饰者模式

&#x1f468;‍&#x1f4bb;本文专栏&#xff1a;设计模式篇-装饰者模式 &#x1f468;‍&#x1f4bb;本文简述&#xff1a;装饰者模式的详解以及jdk中的应用 &#x1f468;‍&#x1f4bb;上一篇文章&#xff1a; 设计模式篇(Java)&#xff1a;桥接模式 &#x1f468;‍&am…

串行数据发送器

框图 THR&#xff1a;发送保持寄存器 定义了两种状态&#xff1a;空&#xff0c;满数据写入端口地址&#xff1a;00H状态读出端口地址&#xff1a;00H当THR不满时&#xff0c;可以向THR写入数据 TSR&#xff1a;发送移位寄存器 一旦TSR空而THR中有数据时&#xff0c;THR中的数…

shell中分支语句,循环语句,函数

实现对一个数组求和的函数&#xff0c;将数组作为实参传给函数 #!/bin/bash sum() {for i in $do((sumi))doneecho $sum} read -p "请输入一组数字: " -a arr sum ${arr[*]}2 调用函数&#xff0c;输出当前用户的uid gid 并使用变量接收结果 #!/bin/bashget() {uid…

2023 年高教社杯全国大学生数学建模竞赛题目 B 题 多波束测线问题

B 题 多波束测线问题 单波束测深是利用声波在水中的传播特性来测量水体深度的技术。声波在均匀介质中作匀速直线传播&#xff0c;在不同界面上产生反射&#xff0c;利用这一原理&#xff0c;从测量船换能器垂直向海底发射声波信号&#xff0c;并记录从声波发射到信号接收的传播…

VSCode自动分析代码的插件

今天来给大伙介绍一款非常好用的插件&#xff0c;它能够自动分析代码&#xff0c;并帮你完成代码的编写 效果如下图 首先我们用的是VSCode&#xff0c;&#xff08;免费随便下&#xff09; 找到扩展&#xff0c;搜索CodeGeeX&#xff0c;将它下载好&#xff0c;就可以实现了 到…

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

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

深度学习Tensorflow: CUDA_ERROR_OUT_OF_MEMORY解决办法

目前在用深度学习训练&#xff0c;训练中设置batch size后可以正常跑通&#xff0c;但是在训练一轮save_model时&#xff0c;总出现这个错误&#xff0c;即使我调batch size到1也依旧会报错。 发现是在 调用logger时出现问题。 查询后了解到是因为TensorFlow中的eager_executi…

模电课程设计

主要内容跟本科实验关系很大&#xff0c;可以用来借鉴。 包含文件有&#xff1a;实验报告、Multisim仿真文件&#xff0c;资料很全&#xff0c;有问题可以私信 目录 1、模电课设&#xff1a;用Multisim简单了解二极管 2、模电课设&#xff1a;用Multisim简析三极管与场效应…

开发者的商业智慧:产品立项策划你知道多少?

文章目录 想法的萌芽&#x1f31f;初步评估产品可行性&#x1f34a;分析核心功能和特点以及竞争对手&#x1f4dd;大健康监测&#x1f4dd;时尚新科技产品&#x1f4dd;准确性&#x1f4dd;多功能&#x1f4dd;品牌口碑&#x1f4dd;数据分析与个性化建议&#x1f4dd;社交互动…

go的iris框架进行本地资源映射到服务端

我这里使用的是HandleDirapi,有其他的请补充 package mainimport ("github.com/kataras/iris/v12" )type Hello struct{Status int json:"status"Message string json:"message" }func main(){app : iris.New()//第一个api:相当于首页app.Get(&q…

【多线程】volatile 关键字

volatile 关键字 1. 保证内存可见性2. 禁止指令重排序3. 不保证原子性 1. 保证内存可见性 内存可见性问题: 一个线程针对一个变量进行读取操作&#xff0c;另一个线程针对这个变量进行修改操作&#xff0c; 此时读到的值&#xff0c;不一定是修改后的值&#xff0c;即这个读线…

C++学习之list的实现

在了解学习list实现之前我们首先了解一下关于迭代器的分类&#xff1a; 按功能分类&#xff1a; 正向迭代器 反向迭代器 const正向迭代器 const反向迭代器 按性质分类&#xff1a; 单向迭代器 只能 例如单链表 双向迭代器 可&#xff0c;也可-- 例如双…

服务端 TCP 连接的 TIME_WAIT 过多问题的分析与解决

https://blog.csdn.net/zxlyx/article/details/120397006 本文给出一个 TIME_WAIT 状态的 TCP 连接过多的问题的解决思路&#xff0c;非常典型&#xff0c;大家可以好好看看&#xff0c;以后遇到这个问题就不会束手无策了。 问题描述 模拟高并发的场景&#xff0c;会出现批量…

《Python深度学习-Keras》精华笔记3:解决深度学习多分类问题

公众号&#xff1a;机器学习杂货店作者&#xff1a;Peter编辑&#xff1a;Peter 持续更新《Python深度学习》一书的精华内容&#xff0c;仅作为学习笔记分享。 本文是第三篇&#xff1a;介绍如何使用Keras解决Python深度学习中的多分类问题。 多分类问题和二分类问题的区别注意…

Linux dup dup2函数

/*#include <unistd.h>int dup2(int oldfd, int newfd);作用&#xff1a;重定向文件描述符oldfd 指向 a.txt, newfd 指向b.txt,调用函数之后&#xff0c;newfd和b.txt close&#xff0c;newfd指向a.txtoldfd必须是一个有效的文件描述符 */ #include <unistd.h> #i…

Vue 2 条件渲染

条件渲染相关的指令有哪些&#xff1f; v-if、v-else、v-else-ifv-show v-if 的作用 <div v-if"expression"></div>v-if 根据表达式 expression 返回的值是否为 truthy 来决定其内容是否被渲染。 Vue还实现了 v-else 和 v-else-if&#xff1a; <d…

排序算法:快速排序(三种排序方式、递归和非递归)

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;本期来给大家解读一下有关排序算法的相关知识点&#xff0c;如果看完之后对你有一定的启发&#xff0c;那么请留下你的三连&#xff0c;祝大家心想事成&#xff01; C 语 言 专 栏&#xff1a;C语言&#xff1a;从入门到精通…

autojs修改顶部标题栏颜色

顶部标题栏的名字是statusBarColor 不是toolbar。难怪我搜索半天搜不到 修改之后变成这样了 代码如下&#xff1a; "ui"; importClass(android.view.View); importClass(android.graphics.Color); ui.statusBarColor(Color.parseColor("#ffffff")); ui.…

【Spring Cloud系统】- 轻量级高可用工具Keepalive详解

【Spring Cloud系统】- 轻量级高可用工具Keepalive详解 文章目录 【Spring Cloud系统】- 轻量级高可用工具Keepalive详解一、概述二、Keepalive分类2.1 TCP的keepalive2.2 HTTP的keep-alive2.3 TCP的 KeepAlive 和 HTTP的 Keep-Alive区别 三、nginx的keepalive配置3.1 nginx保持…