數據結構與算法-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.pswp.cn/news/447803.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/447803.shtml
英文地址,請注明出處:http://en.pswp.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…