python数据结构学习笔记-3-数组

数组

Python的list、tuple和str是基于数组的序列,list和tuple是存放的对象的引用,str存放的是实际值(an array of characters (not an array of references)),字符在内存中是连续存储的。list、tuple和str都可以通过索引和切片进行操作。模块array可以用于创建存放值的数组,有一个限制是ctype的,不支持自定义的类型。操作方式如:primes = array( 'i' , [2, 3, 5, 7, 11, 13, 17, 19])。

python数据结构学习笔记-3-数组_第1张图片

字符串类型在使用时的一个常见的低效的使用方式和优化后的写法。低效的原因是没增加一个 字符就要先生成一个新的字符串实例,然后再连接。改进后的写法先放到列表(  list)里,然后再 jion。 

#  低效的代码片段
# WARNING: do not do this
letters =  ''                               # start with empty string
for c in document:
    if c.isalpha( ):
        letters += c                    # concatenate alphabetic character

# 好的写法 
temp = [ ]                              # start with empty list
for c in document:
    if c.isalpha( ):                        # append alphabetic character
        temp.append(c)
letters = ''.join(temp)                   # compose overall result

#更简洁的写法
letters = ''.join([c for c in document if c.isalpha( )])
letters = ''.join(c for c in document if c.isalpha( ))

动态数组

书上的动态数组的实现代码,简单易懂。
import ctypes

class DynamicArray:
    """ A dynamic array class akin to a simplified Python list."""
    
    def __init__(self):
        """ Create an empty array."""
        self._n = 0                                                         #count actual elements
        self._capacity = 1                                             #default array capacity
        self._A = self._make_array(self._capacity)     #low-level array
        
    def __len__(self):
        """Return number of elements stored in the array."""
        return self._n
    
    def __getitem__(self,k):
        """Return element at index k."""
        if not 0 <= k < self._n:
            raise IndexError('invalid index')
        return self._A[k]                                                          #retrieve from array
    
    def append(self, obj):
        """Add object to end of the array."""
        if self._n == self._capacity:                                         # not enough room
            self._resize(2*self._capacity)                                 #so double capacity
        self._A[self._n] = obj
        self._n += 1
        
    def _resize(self, c):                                                        # nonpublic utitity
        """Resize internal array to capacity c."""
        B = self._make_array(c)                                            # new (bigger) array
        for k in range(self._n):                                              # for each existing value
            B[k] = self._A[k]
        self._A = B
        self._capacity = c
    
    def _make_array(self, c):                                                 # nonpublic utitity   
        """Return new array with capacity c."""
        return (c * ctypes.py_object)()                                   # see ctypes documentation

if __name__ == '__main__':
    
    da = DynamicArray()
    da.append(6)
    da.append(2)
    
    for o in da:
        print o

列表应用

书上的两个例子。

列表应用一,应用列表(list)实现一个游戏得分的排行榜。类GameEntry记录姓名和得分,类ScoreBoard实现排行榜,它要保证添加新得分时要保证得分是按照顺序排列的,如果空间不够,就要把最后一名挤出去。

class GameEntry:
    """Represents one entry of a list of high scores."""
    
    def __init__(self, name, score):
        self._name = name
        self._score = score
        
    def get_name(self):
        return self_score
    
    def __str__(self):
        return '({0}, {1})'.format(self._name, self._score)
    
class Scoreboard:
    """Fixed-length sequence of high scores in nondecreasing order."""
    
    def __init__(self, capacity=10):
        """Initialize scoreboard with given maximum capacity.
        All entries are initially None.
        """
        self._board = [None]*capacity                                  #reserve space for future scores
        self._n = 0
    
    def __getitem__(self, k):
        """Return entry at index k."""
        return self._board[k]
    
    def __str__(self):
        """Return string representation of the high score list."""
        return '\n'.join(str(self._board[j]) for j in range(self._n))
    
    def add(self,entry):
        """Consider adding entry to high scores."""
        score = entry.get_score()
        
        # Does new entry qualify as a high score?
        # answer is yes if board not full or score is higher than last entry
        good = self._n < len(self._board) or score > self._board[-1].get_score()
        
        if good:
            if self._n < len(self._board):                      #no score drops form list
                self._n += 1                                            #so overall number increases
                
            # shift lower socres rightward to make room for new entry
            j = self._n - 1
            while j > 0 and self._board[j-1].get_score() < score:
                self._board[j] = self._board[j-1]            #shift entry from j-1 to j
                j -= 1                                                    #and decrement j
            self._board[j] = entry                               #when done, and new entry
            
        
def insertion_sort(A):
    """Sort list of comparable elements into nondecreading order."""
    for k in range(1, len(A)):                               # from 1 to n-1
        cur = A[k]                                                   # current element to be inserted
        j = k                                                           # find correct index j for current
        while j > 0 and A[j-1] > cur:                    # element A[j-1] must be after current
            A[j] = A[j-1]
            j -= 1
        A[j] = cur                                                  # cur is now in the right place
        

列表应用二,凯撒密码加密。

class CaesarCipher:
    """ Class for doing encryption and decryption using a Caesar cipher. """
    
    def __init__(self, shift):
        """Construct Caesar cipher using given integer shift for rotation."""
    
        encoder = [None] * 26                                         #temp array for encryption
        decoder = [None] * 26                                         #temp array for decryption
        for k in range(26):
            encoder[k] = chr((k + shift) % 26 + ord('A'))
            decoder[k] = chr((k - shift) % 26 + ord('A'))
        self._forward = ''.join(encoder)                           #will store as string
        self._backward = ''.join(decoder)                        #since fixed
        
    def encrypt(self, message):
        """Return string representing encripted message."""
        return self._transform(message, self._forward)
    
    def decrypt(self, secret):
        """Return decrypted message given encrypted secret."""
        return self._transform(secret, self._backward)
    
    def _transform(self, original, code):
        """Utility to perform transformation based on given code string."""
        msg = list(original)
        for k in range(len(msg)):
            if msg[k].isupper():
                j = ord(msg[k]) - ord('A')                      # index from 0 to 25
                msg[k] = code[j]                                  # replace this character
        return ''.join(msg)
    
if __name__ == '__main__':
    cipher = CaesarCipher(3)
    message = "THE EAGLE IS IN PLAY; MEET AS JOE'S."
    coded = cipher.encrypt(message)
    print('Secret: ', coded)
    answer = cipher.decrypt(coded)
    print('Message: ', answer)
        

二维数组

在python中二维数组表示为列表中的列表。但是要注意的是初始化时如不小心会犯错。

错误的初始化

In [1]: data = ([0]*2)*3
In [2]: print data
[0, 0, 0, 0, 0, 0]

In [3]: data = [[0]*2]*3
In [4]: data[0][1]=1
In [5]: print data
[[0, 1], [0, 1], [0, 1]]

正确的初始化

In [12]: data = [[0]*2 for j in range(3)]
In [13]: data
Out[13]: [[0, 0], [0, 0], [0, 0]]

In [14]: data[0][1]=1
In [15]: data
Out[15]: [[0, 1], [0, 0], [0, 0]]
二维数组可以用来表示平面上的位置,书上举了一个Tic-Tac-Toe游戏例子。_board是一个3×3的二维数组,记录每个位置放的是'X'、'O'或' '(无棋子); mark表示往[i][j]这个位置上放棋子(做标记), 放棋子时会进行校验;_is_win判断输赢,返回None表示未结束,还可以下。

class TicTacToe:
    """Management of a Tic-Tac-Toe game(does not do strategy)."""
    
    def __init__(self):
        """Start a new game."""
        self._board = [[' ']*3 for j in range(3)]
        self._player = 'x'
        
    def mark(self, i, j):
        """Put an X or O mark at position (i,j) for next player's turn."""
        if not (0 <= i <= 2 and 0 <= j <= 2):
            raise ValueError('Invalid board position')
        if self._board[i][j] != ' ' :
            raise ValueError('Board position occupied')
        if self.winner() is not None:
            raise ValueError('Game is already complete')
        self._board[i][j] = self._player
        if self._player == 'X':
            self._player = 'O'
        else:
            self._player = 'X'
    
    def _is_win(self, mark):
        """Check whether the board configuration is a win for the given player."""
        board = self._board                                                #local variable for shorthand
        return (mark == board[0][0] == board[0][1] == board[0][2] or  #row 0
                      mark == board[1][0] == board[1][1] == board[1][2] or  #row 1
                      mark == board[2][0] == board[2][1] == board[2][2] or  #row 2
                      mark == board[0][0] == board[1][0] == board[2][1] or  #column 0
                      mark == board[0][0] == board[1][1] == board[2][2] or  #column 1
                      mark == board[0][1] == board[1][2] == board[2][2] or  #column 2
                      mark == board[0][0] == board[1][1] == board[2][2] or  #diagonal
                      mark == board[0][2] == board[1][1] == board[2][0] )    #rev diag)
    
    def winner(self):
        """Return mark of winning player, or None to indicate a tie."""
        for mark in 'XO':
            if self._is_win(mark):
                return mark
        return None
    
    def __str__(self):
        """Return string representation of current game board."""
        rows = ['|'.join(self._board[r]) for r in range(3)]
        return '\n-----\n'.join(rows)


你可能感兴趣的:(python)