数据结构与算法-ADT-Array

Array ADT

一维数组是连续元素的集合,其中的每个元素都可以通过唯一的整数下标来存取。数组的大小在创建后不能修改。

ADT 定义:

  • Array(size): 创建一个长度为 size 的一维数组,并且将每个元素初始化成 None
  • length(): 返回数组中的元素个数
  • getitem(index): 返回指定下标的元素
  • setitem(index, value): 修改数组中 index 位置的元素值
  • clearing(value): 将数组中的所有元素值重置成 value
  • iterator(): 返回迭代器

Array 的实现

ctypes 模块

Python 中的许多数据类型及类实际上都是基于低层 C 语言中的相关类型实现的。Python 标准库中的 ctypes 模块可用来访问 C 语言中的各种类型及 C 类库中的功能。使用 ctypes 提供的大多数功能都要求理解一些 C 语言知识。

类似 Python 实现 string, list, tuple 和 dict,我们通过 ctypes 创建一个数组,其中的元素都是 Python 对象引用:

for i in range(5):slots[i] = None

这个数组必须先初始化后才能访问,不然会抛出异常,如 slots[0] 会抛出异常,初始化如下:

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), "Array subscript out of range"return self._elements[ index ]def __setitem__( self, index, val ):assert index >= 0 and index < len(self), "Array subscript out of range"self._elements[ index ] = valdef clear( self, val ):for i in xrange( self._size ):self._elements[ i ] = valdef __iter__( self ):return _ArrayGenerator( self._elements, self._size )def _ArrayGenerator( elements, size ):for i in range( size ):yield elements[i]

Array 的实现如下:

pyList = [4, 12, 2, 34, 17]

Python List

Python List 也是通过低层的 C 语言类型实现的,它是一个可修改的序列容器,其大小可以随着元素的添加和删除自动改变。

创建一个 Python List

pyListA = [34, 12]
pyListB = [4, 6, 31, 9]
pyListA.extend(pyListB)

以上代码将调用 list() 构造器,构造器将创建一个数组结构用来存储列表中的元素。实际上初始创建的数组大小会大于所需的容量,这样便于以后的扩展操作。

用于存储列表元素的数组实际上是刚才创建的数组中的一个子数组 subarraylen(lst) 返回该子数组的长度,而整个数组的长度为 capacity。 用数组实现的 Python List 的抽象和物理视图如下:

listUsingArrayView.png

追加元素 append

当数组容量足够时,新元素将追加到数组中,并且 list 的 length 域也相应增加。

当数组満时,List 会进行自动扩展,即:

  1. 新建一个更大容量的数组
  2. 将原数组的元素全部复制到新建的数组
  3. 将新建的数组设置为 List 的数据结构
  4. 销毁旧的数组

新建数组的大小是根据原数组的大小确定的,比如说,新数组的大小定为原数组大小的 2 倍 。 扩展后再在数组后追加元素。

扩充列表 extend

比如:

pyList.insert(3, 79)

当 pyListA 中的数组容量不够时,List 会自动进行如 append 进行的类似数组扩展操作。

插入 insert

比如:

pyList.pop(0) # remove the first item
pyList.pop() # remove the last item

当位置 3 已经有元素时,位置 3 及其后面的所有元素都将后移一个位置,并在位置 3 插入新元素。当数组容器不够,会进行和上面相似的数组扩展操作。

删除 pop

比如:

class Array2D:def __init__( self, nrows, ncols ):# Create a 1-D array to store an array reference for each row.self._theRows = Array( nrows )# Create the 1-D arrays for each row of the 2-D array.for i in range( nrows ):self._theRows[i] = Array( ncols )def numRows( self ):return len( self._theRows )def numCols( self ):return len( self._theRows[0] )# Clears the array by setting every element to the given value.def clear( self, val ):for row in range( self.numRows() ):self._theRows[row].clear( val )def __getitem__( self, xy ):assert len( xy ) == 2, "Invalid number of array subscripts."row = xy[0]col = xy[1]assert row >= 0 and row < self.numRows() and \col >= 0 and col < self.numCols(), "Array subscript out of range."the1arr = self._theRows[row]return the1arr[col]def __setitem__( self, xy, val ):assert len( xy ) == 2, "Invalid number of array subscripts."row = xy[0]col = xy[1]assert row >= 0 and row < self.numRows() and \col >= 0 and col < self.numCols(), "Array subscript out of range."the1arr = self._theRows[row]the1arr[col] = val

删除后,如果后面还有元素,那么被删除元素后面的所有元素将前移一个位置,以便填充删除后的空位。

当然,如果删除后的数组空位过多,也会进行相对应的收缩数组操作。

List Slice

Slice 会创建一个新的 List。

二维数组 two-dimensional array

它将数据组织成行和列,类似于表格。每个元素通过两个下标来存取。

Array2D ADT

  • Array2D(nrows, ncols): 创建一个 nrows 行,ncols 列的二维数组,并初始化每个元素为 None
  • numRows(): 返回行数
  • numCols(): 返回列数
  • clear(value): 将所有元素的值设为 value
  • getitem(row, col): 通过下标法 y=x[1,2] 来访问元素
  • setitem(row, col, value): 设置元素值

Array2D 的实现

通常有 2 种数据组织方法:

  • 使用一个一维数组,将行列上的每个元素位置映射到数组的相应位置
  • 使用数组的数组实现

下面的实现采用了数组的数组方法,将二维数组中的每一行存储在一维数组中,然后再创建一个数组,用来保存行数组(即该数组是数组的数组)。Array2D 的抽象和物理存储视图如下:

array2dView.png

有些语言的实现中,可以存取每个行,从而对每个元素的访问使用 x[r][c] 进行。为了隐藏实现细节,我们的实现不暴露行数组,从而对每个元素的访问使用 x[r,c] 进行。

实现如下:

class Array2D:def __init__( self, nrows, ncols ):# Create a 1-D array to store an array reference for each row.self._theRows = Array( nrows )# Create the 1-D arrays for each row of the 2-D array.for i in range( nrows ):self._theRows[i] = Array( ncols )def numRows( self ):return len( self._theRows )def numCols( self ):return len( self._theRows[0] )# Clears the array by setting every element to the given value.def clear( self, val ):for row in range( self.numRows() ):self._theRows[row].clear( val )def __getitem__( self, xy ):assert len( xy ) == 2, "Invalid number of array subscripts."row = xy[0]col = xy[1]assert row >= 0 and row < self.numRows() and \col >= 0 and col < self.numCols(), "Array subscript out of range."the1arr = self._theRows[row]return the1arr[col]def __setitem__( self, xy, val ):assert len( xy ) == 2, "Invalid number of array subscripts."row = xy[0]col = xy[1]assert row >= 0 and row < self.numRows() and \col >= 0 and col < self.numCols(), "Array subscript out of range."the1arr = self._theRows[row]the1arr[col] = val
实现元素的存取

__getitem__(self, index)__setitem__(self, index. value) 这两个函数定义参数中, 只有一个 index 参数,但这不会限制只能使用一个下标。当使用多个下标时,如 y = x[i,j],多个下标会组合成一个 tuple 作为 index 参数传入。

Matrix ADT

矩阵是标量值的集合,这些值以行和列的形式组织成一个固定大小的矩形网格中。

  • Matrix(nrows, ncols): 创建一个 nrows 行和 ncols 列的矩阵
  • numRows(): 返回行数
  • numCols(): 返回列数
  • getitem(row, col): 返回元素
  • setitem(row, col, scalar): 设置元素值
  • scaleBy(scalar): 矩阵中的每个元素都乘该值,操作后矩阵本身将被修改
  • transpose(): 返回一个转置矩阵
  • add(rhsMatrix): 创建并返回一个新矩阵。这两个矩阵大小必须相同
  • subtract(rhsMatrix): 相减
  • multiply(rhsMatrix): 相乘。

Matrix 的实现

一般用二维数组来实现矩阵。

实现如下:

from array import Array2Dclass Matrix:def __init__( self, nrow, ncols ):self._theGrid = Array2D( nrow, ncols )self._theGrid.clear( 0 )def numRows( self ):return self._theGrid.numRows()def numCols( self ):return self._theGrid.numCols()def __getitem__( self, xy ):return self._theGrid[ xy[0], xy[1] ]def __setitem__( self, xy, scalar ):self._theGrid[ xy[0], xy[1] ] = scalardef scaleBy( self, scalar ):for r in xrange( self.numRows() ):for c in xrange( self.numCols() ):self[r, c] *= scalardef transpose( self ):newMatrix = Matrix( self.numCols(), self.numRows() )for r in xrange( self.numRows() ):for c in xrange( self.numCols() ):newMatrix[c, r] = self[r, c]return newMatrixdef add( self, rhsMatrix ):assert rhsMatrix.numRows() == self.numRows() and \rhsMatrix.numCols() == self.numCols(), \"Matrix sizes not compatible for the add operation."newMatrix = Matrix( self.numRows(), self.numCols() )for r in xrange( self.numRows() ):for c in xrange( self.numCols() ):newMatrix[r, c] = self[r, c] + rhsMatrix[r, c]return newMatrixdef subtract( self, rhsMatrix ):assert rhsMatrix.numRows() == self.numRows() and \rhsMatrix.numCols() == self.numCols(), \"Matrix sizes not compatible for the add operation."newMatrix = Matrix( self.numRows(), self.numCols() )for r in xrange( self.numRows() ):for c in xrange( self.numCols() ):newMatrix[r, c] = self[r, c] - rhsMatrix[r, c]return newMatrixdef multiple( self, rhsMatrix ):assert self.numCols() == rhsMatrix.numRows(), \"Matrix sizes not compatible for the multiple operation."newMatrix = Matrix( self.numRows(), rhsMatrix.numCols() )for r in xrange( self.numRows() ):for rhsC in xrange ( rhsMatrix.numCols() ):tmp = 0for c in xrange( self.numCols() ):tmp += self[r, c] * rhsMatrix[c, r]newMatrix[r, rhsC] = tmpreturn newMatrix

应用: 游戏人生

The game of Life 是由英国数学家 John H. Conway 发明的,它能模拟生物群落的兴衰更替。该游戏可用来观察一个复杂的系统或模式如何能从一组简单的规则演化而来。

游戏规则

该游戏使用一个不限大小的矩形网格,其中的每个单元格要么是空的,要么被一个有机体占据。被占据的单元格被视作是活的,而空的单元格被视作是死的。游戏的每次演进,都会基于当前的单元格布局,创造新的“一代”。下一代中的每个单元格状态是根据以下规则确定的:

  1. 若某单元格是活的,并且有 2 或 3 个活的邻居,那么它在下一代也保持活。每个单元格有 8 个邻居。
  2. 若某单元格是活的,但它没有活的邻居,或只有一个活邻居,它在下一代会死于孤立。
  3. 一个活单元格,若有 4 个或更多个活邻居,它在下一代会死于人口过剩。
  4. 一个死单元格,当且仅当只有 3 个活邻居时,会在下一代重生。

用户先初始化配置,即指定哪些单元格是活的,然后运用以上的规则,生成下一代。可以看到,一些系统可能最终会消亡,而有些最终会进化成 “稳定” 状态。例如:

gamelife_stable1.png

gamelife_stable2.png

设计方案

一个网格 life grid 用来表示和存储游戏区。网格包含一组矩形单元格,并分成有限大小的行和列。

  • LifeGrid(nrows, ncols): 创建一个新的游戏网格。所有单元格设置为空(死)。
  • numRows(): 返回网格行数。
  • numCols(): 返回网格列数。
  • configure(coordList): 配置网格以进行下一代的演化。参数是一个 (row, col) 的序列,每一个元组表示该位置的单元格是活的。
  • clearCell(row, col): 设置单元格为空(死)。
  • setCell(row, col): 设置单元格为活。
  • isLiveCell(row, col): 返回一个布尔值,表示某个单元格是否包含一个活的有机体。
  • numLiveNeighbors(row, col): 返回某个单元格的所有活邻居个数。对于边缘的单元格,落在边缘外的邻居都认为是死的。

实现

使用一个二维数组来表示网格。每个单元格的状态使用 0 和 1 表示,0 表示死,1 表示活。这样在统计单元格的活邻居总数时,只需要将邻居的状态相加即可。实现时网格的大小是限定的,如果大小超出了,在运行过程中可以重新创建一个新的网格。

# life.py
from array import Array2Dclass LifeGrid:DEAD_CELL = 0LIVE_CELL = 1def __init__( self, nrows, ncols ):self._grid = Array2D( nrows, ncols )self.configure( list() )def numRows( self ):return self._grid.numRows()def numCols( self ):return self._grid.numCols()def configure( self, coordList ):for i in range( self.numRows() ):for j in range( self.numCols() ):self.clearCell(i, j)for coord in coordList:self.setCell( coord[0], coord[1] )def isLiveCell( self, row, col ):return self._grid[ row, col ] == LifeGrid.LIVE_CELLdef clearCell( self, row, col ):self._grid[ row, col ] = LifeGrid.DEAD_CELLdef setCell( self, row, col ):self._grid[ row, col ] = LifeGrid.LIVE_CELLdef numLiveNeighbors( self, row, col ):nrows = self.numRows()ncols = self.numCols()liveNum = 0for i in range( row-1, row+2 ):for j in range( col-1, col+2 ):if ( 0 <= i < nrows ) and ( 0 <= j < ncols ):liveNum += self._grid[i, j]liveNum -= self._grid[ row, col ]return liveNumfrom life import LifeGrid# Define the initial configuration of live cells.
INIT_CONFIG = [ (0, 0), (0, 1), (1, 0), (1, 2), (3, 2), (3, 4), (5, 4), (5, 6), (7, 6), (7, 8), (9, 8), (9, 10), (11, 10), (11, 12), (12, 11), (12, 12)]# Indicate the number of generations
#NUM_GENS = 8def main():GRID_WIDTH = int( raw_input( "Grid width:" ) )GRID_HEIGHT = int( raw_input( "Grid height:" ) )NUM_GENS = int( raw_input( "Nbr of generations to evolve:" ) )grid = LifeGrid( GRID_WIDTH, GRID_HEIGHT )grid.configure( INIT_CONFIG )# Play the game.draw( grid )for i in range( NUM_GENS ):evolve( grid )draw( grid )def evolve( grid ):liveCells = list()for i in range( grid.numRows() ):for j in range( grid.numCols() ):neighbors = grid.numLiveNeighbors( i, j )# 1. If a cell is alive and has either two or three live neighbors, the cell remains alive in the next generation. # The neighbors are the eight cells immediately surrounding a cell: vertically, horizontally, and diagonally.  # 2. A living cell that has no live neighbors or a single live neighbor dies from isolation in the next generation.# 3. A living cell that has four or more live neighbors dies from overpopulation in the next generation.# 4. A dead cell with exactly three live neighbors results in a birth and becomes alive in the next generation.# All other dead cells remain dead in the next generation.if (neighbors == 2 and grid.isLiveCell( i, j )) or \(neighbors == 3):liveCells.append( (i, j) )grid.configure( liveCells )def draw( grid ):printfor i in range( grid.numRows() ):for j in range( grid.numCols() ):if grid.isLiveCell( i, j):print '@',else:print '.',printmain()

参考:

  • Data Structures and Algorithms Using Python: Arrays

转载于:https://www.cnblogs.com/oneTOinf/p/11521438.html

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

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

相关文章

前端VUE工程不占用80端口,浏览器不带端口访问VUE项目的实现

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1.需求&#xff1a;直接域名访问项目&#xff0c;不用IP&#xff0c;也不带端口号。 1&#xff09;访问项目方法通常是 IP&#xff1a;…

新驾考科目三有四个地方易犯错 多名教练提供对策

驾考科目三 四个地方易犯错 多名驾校教练为学员分析原因提供对策 “现在电子评判&#xff0c;比起原来人工评判&#xff0c;更客观&#xff0c;更公平。”有驾校教练把自己这两天当安全员参加考试的经验拿出来与学员们分享。 18分钟来得及 “考试时间完全够用!”20日安康达驾校…

个人看过的动漫、动画电影推荐

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 我看过的不多&#xff0c;反正我觉得都挺好看的。 个人比较喜欢看电影版本的&#xff0c;不偏好多集的正宗动漫&#xff0c; 一集一集太…

广州科目三路考经历与注意事项分享

在百度找不到具体的广州本地车考考路面的流程,本人上周五刚刚考过了路面,觉得应该将过程写出来,以便后面的朋友或者想百度谷歌广州本地车考考路面情况的网友们做个参考.首先,广州本地考绝对没有其它省市路考的那么复杂,举例:1.下车检查前后轮-广州的路考不必;2.上车前喊报告什么…

ResourceDictionary主题资源替换(二) :编译期间,替换主题资源

之前的ResourceDictionary主题资源替换&#xff08;一&#xff09;通过加载顺序来覆盖之前的主题资源&#xff0c;介绍了WPF框架对ResourceDictionary资源的合并规则。 此篇介绍一种在编译期间&#xff0c;实现资源替换的方案 前言 如下图&#xff0c;项目中存在俩个主题资源字…

解决 idea 中 jsp 修改后页面不生效

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1.问题描述&#xff1a;idea 编辑 jsp , 修改好后在 浏览器访问却发现页面完全无变化 。 2.解决&#xff0c;要在 idea 中作如下设置&a…

广州交警发布科目三路考秘笈

近段时间&#xff0c;如何通过新实行的科目三电子路考成为考车一族热议的话题。各种“通关秘笈”在坊间流传。为了让广大考生了解电子路考究竟怎么考&#xff0c;7日晚&#xff0c;广州交警在微博广州交警 上发布了官方“秘笈”&#xff1a;一段长9分钟的科目三电子路考演示视频…

test0

s 转载于:https://www.cnblogs.com/oneTOinf/p/11527940.html

解决 :IDEA 修改代码后 Local Changes 中没有提示待提交文件,代码自动提交了

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 通常修改代码后 会在 Local Changes 中提示修改过的文件&#xff0c;如下&#xff1a; 2. 我的情况是 &#xff0c;在这个界面中什么…

3.1 go context代码示例

context.WithCancel返回两个有关联的对象&#xff0c;ctx与cancel&#xff0c;调用cancel发送一个空struct给ctx&#xff0c;ctx一旦接收到该对象后&#xff0c;就终止goroutine的执行;ctx是线程安全的&#xff0c;可以同时传递给多个goroutine&#xff0c;触发cancel时&#x…

JS 中去除空格和换行的正则表达式写法

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 //去除空格 String.prototype.Trim function() { return this.replace(/\s/g, ""); } //去除换行 function ClearBr(key) {…

科目三电子路考哪些情况会被评判不合格

2014年驾考科目三电子路考时需要注意&#xff0c;出现下列情形会被评判为不合格&#xff1a; 1、不按规定使用安全带或者戴安全头盔的; 2、遮挡、关闭车内音视频监控设备的; 3、不按考试员指令驾驶的; 4、不能正确使用灯光、雨刮器等车辆常用操纵件的; 5、起步时车辆后溜距离大…

FreeSql (一)入门

FreeSql 是一个功能强大的对象关系映射程序(O/RM)&#xff0c;支持 .NETCore 2.1 或 .NETFramework 4.5&#xff08;QQ群&#xff1a;4336577&#xff09; FreeSql采用MIT开源协议托管于 github。 特性 [x] 支持 CodeFirst 迁移&#xff1b;[x] 支持 DbFirst 从数据库导入实体类…

解决:Caused by: java.lang.UnsupportedOperationException: null

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1.报错&#xff1a; 严重: Servlet.service() for servlet [lbd-institution] in context with path [/ins] threw exception [Reques…

2014科目三大路考各项目操作要求

机动车驾驶员考试科目三大路考到底都考哪些项目呢&#xff1f;每个项目的具体考试要求分别是什么&#xff1f;下面就跟着小编一起来了解一下吧&#xff01; 新驾考科目三考试内容及变化&#xff1a; A、上车准备;B、起步;C、直线行驶; D、加减挡位操作;E、变更车道; F、靠边停…

FreeSql (二)自动迁移实体

FreeSql 支持 CodeFirst 迁移结构至数据库&#xff0c;这应该是(O/RM)必须标配的一个功能。 与其他(O/RM)不同FreeSql支持更多的数据库特性&#xff0c;而不只是支持基础的数据类型&#xff0c;这既是优点也是缺点&#xff0c;优点是充分利用数据库特性辅助开发&#xff0c;缺点…

IntelliJ IDEA 设置代码检查级别

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 设置代码检查等级   IntelliJ IDEA中最右下角的小按钮可以设置当前编辑文档的代码检查等级&#xff0c;如图   Inspections 为最高等…

科目三路考流程及注意事项

机动车驾驶员考试科目三路考考试流程可分为7个步骤&#xff0c;分别有什么注意事项&#xff0c;下面就让小编给大家介绍下吧&#xff01; 1.上车前&#xff0c;无论你在车辆的什么位置&#xff0c;请务必从车的右侧绕过车头走到驾驶室门前&#xff0c;先观察车前道路上是否有障…

FreeSql (三)实体特性

主键(Primary Key) class Topic {[Column(IsPrimary true)]public int Id { get; set; } } 约定&#xff1a; 当没有指明主键时&#xff0c;命名为 id 的字段将成为主键&#xff1b;&#xff08;不区分大小写&#xff09;当主键是 Guid 类型时&#xff0c;插入时会自动创建&am…

spring 中构造Constructor、@Autowired、@PostConstruct、静态方法的执行顺序 (@PostConstruct 说明)

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 关于注解 PostConstruct public interface PostConstructPostConstruct 注释用于在依赖关系注入完成之后需要执行的方法上&#xff…